Index: .hgignore
===================================================================
--- .hgignore	(revision 6018)
+++ .hgignore	(revision 6781)
@@ -24,4 +24,5 @@
 \.bak$
 \.BAK$
+\.dylib$
 \.fig$
 \.png$
Index: .hgtags
===================================================================
--- .hgtags	(revision 6278)
+++ .hgtags	(revision 6971)
@@ -103,2 +103,19 @@
 4435b6e38fd821f372846d563a290552cb427d93 2.8.4
 4994a898b0ea22bb2265efc0dbeece6617769f23 2.8.4.1
+78ffd08fed0e3c36107696e55cb6a3323e158758 2.8.4.2.rc1
+49df63f7f26417de37cce57c202a71db075ebf85 2.8.4.2
+56c204456c7552f8c1b80285e32b2a1431e167f0 2.8.4.2.1
+1cf99474ee160fe624c6f643d5b21abe6393cfac 2.8.5.alpha0
+d0eeb6a0d23d5244c9bc8e07b3f876b34d667009 2.8.5
+6365ac447ecd144dab04db8b57bec1bb51f36a20 2.8.5.1
+c0fbd1d40c679cd638221eec0e2b3ebb4cc31070 2.8.6-pre0
+60ad67923377ac916f58ff1d503912ecd6641ed0 2.8.6.pre2
+aa574320477c4aeeed043953e535aa07768d9e87 2.8.6.pre3
+971d3e37abab16e270d565312d303993379c69d8 2.8.6.pre4
+c02fdcd2a96b856832960416bfb11d3c2ce903d3 2.8.6
+63fdd88fed6d6bcd65ac2a9be710856658fe2f65 2.8.7-alpha0
+90a0785f11e5e5b2bb70d3f7d16a73c72b53b385 2.8.7.alpha2
+e5aed1d5088991074d7999444474ff0a332f3f81 2.8.7.rc1
+d9bb3fc9165b76a13f339311b54b2514f2561830 2.8.7.rc2
+cec639fdd700391e3efdc6223ec3fd5ddbc2821a 2.8.7
+9241a4ebc62899a5da6d911966bd3e01641644cc 2.8.7.1
Index: MANIFEST.in
===================================================================
--- MANIFEST.in	(revision 6034)
+++ MANIFEST.in	(revision 6650)
@@ -1,3 +1,3 @@
 recursive-include * *.c *.h *.pyx *.pyxe *.pxd *.pxi *.cc *.txt *.tex *.i *.d 00* 
-include c_lib c_lib/* install sage-push spkg-dist spkg-install MANIFEST.in README.txt .hgignore .hg .hg/* bundle export mercurial-howto.txt pull test_changed bundle export mercurial-howto.txt sage/matrix/padics/__init__.py .hgtags bundle export mercurial-howto.txt sage/dsage/README.markdown sage/libs/linbox/matrix_rational_dense_linbox.cpp sage/rings/padics/polynomial/__init__.py sage/rings/padics/polynomial/all.py
+include c_lib c_lib/* c_lib/src/* install sage-push spkg-dist spkg-install MANIFEST.in README.txt .hgignore .hg .hg/* bundle export mercurial-howto.txt pull test_changed bundle export mercurial-howto.txt sage/matrix/padics/__init__.py .hgtags bundle export mercurial-howto.txt sage/dsage/README.markdown sage/libs/linbox/matrix_rational_dense_linbox.cpp sage/rings/padics/polynomial/__init__.py sage/rings/padics/polynomial/all.py
 
Index: _lib/COPYING
===================================================================
--- c_lib/COPYING	(revision 6004)
+++ 	(revision )
@@ -1,340 +1,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year  name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
Index: _lib/ChangeLog
===================================================================
--- c_lib/ChangeLog	(revision 6004)
+++ 	(revision )
@@ -1,9 +1,0 @@
-2006-11-24  Martin Albrecht  <martin@informatik.uni-bremen.de>
-
-	* updated to work with SAGE 1.5
-	* corrected spkg-install
-
-2006-11-15  Martin Albrecht  <malb@informatik.uni-bremen.de>
-
-	* initial release
-
Index: c_lib/SConstruct
===================================================================
--- c_lib/SConstruct	(revision 6207)
+++ c_lib/SConstruct	(revision 6881)
@@ -6,5 +6,5 @@
 ##
 ##
-## 07 Sep 01:
+## 2007 Sep 01:
 ## I added a fix for trac ticket 555, which is to add the "install_lib"
 ## and "install_includes" below. 
@@ -27,4 +27,13 @@
 ## I also edited a bunch of lines below so that they didn't go over 80 chars,
 ## because I don't like seeing wrapped lines.
+##
+## 2007 Oct 01:
+## After discussion with Gonzalo Tornaria and William Stein, we 
+## decided that there's a much better solution to the above 
+## problem: make $SAGE_ROOT/local/lib/libcsage.dylib. Also, we're
+## reorganizing the directory tree to have src/ and include/
+## subdirectories, and $SAGE_ROOT/local/include has a link into
+## this directory.
+##
 import os
 
@@ -59,13 +68,11 @@
     env.Append( LINKFLAGS="-single_module -flat_namespace -undefined dynamic_lookup" )
 
+
+## We want the debug and optimization flags, since debug symbols are so useful, etc.
+env.Append( CFLAGS="-O2 -g" )
+
 # SCons doesn't automatically pull in system environment variables
 # However, we only need SAGE_LOCAL, so that's easy.
 env['SAGE_LOCAL'] = os.environ['SAGE_LOCAL']
-
-def copy_all_includes( target, source, env ):
-    path = os.environ['SAGE_LOCAL'] + "/include"
-    for f in source:
-        Copy( path, f )
-    return None
 
 # The SCons convenience function Split is the only strange thing 
@@ -73,22 +80,14 @@
 # whitespace without the syntax clutter of lists of strings.
 includes = ['$SAGE_LOCAL/include/', '$SAGE_LOCAL/include/python2.5/',
-            '$SAGE_LOCAL/include/NTL/']
-cFiles = Split( "interrupt.c  mpn_pylong.c  mpz_pylong.c  stdsage.c gmp_globals.c" )
+            '$SAGE_LOCAL/include/NTL/', 'include']
+cFiles = Split( "convert.c  interrupt.c  mpn_pylong.c  mpz_pylong.c") + \
+         Split( "stdsage.c  gmp_globals.c" )
 cppFiles = Split( "ZZ_pylong.cpp  ntl_wrap.cpp" )
+srcFiles = cFiles + cppFiles
 
-includes_to_install = Split( "ZZ_pylong.h  ccobject.h  interrupt.h") + \
-                      Split( "mpn_pylong.h  mpz_pylong.h  ntl_wrap.h  stdsage.h gmp_globals.h" )
-lib = env.SharedLibrary( "csage", cFiles + cppFiles,
-                         LIBS=['ntl', 'gmp'], LIBPATH=['$SAGE_LOCAL/lib'],
+lib = env.SharedLibrary( "csage", [ "src/" + x for x in srcFiles ],
+                         LIBS=['ntl', 'gmp', 'pari'], LIBPATH=['$SAGE_LOCAL/lib'],
                          CPPPATH=includes )
 
-env.Install( "$SAGE_LOCAL/include", includes_to_install )
-env.Install( "$SAGE_LOCAL/lib", lib )
+env.Alias( "install", [ lib ] )
 
-Command( "install_includes", includes_to_install, copy_all_includes )
-Command( "install_lib", lib, Copy( env['SAGE_LOCAL'] + "/lib", lib ) )
-
-env.Alias( "install", ["$SAGE_LOCAL/include", "$SAGE_LOCAL/lib"] )
-
-env.Alias( "branch_switch", ["$SAGE_LOCAL/include", "$SAGE_LOCAL/lib",
-                             "install_includes", "install_lib"] )
Index: _lib/ZZ_pylong.cpp
===================================================================
--- c_lib/ZZ_pylong.cpp	(revision 6052)
+++ 	(revision )
@@ -1,43 +1,0 @@
-/*****************************************************************************
-#       Copyright (C) 2007 William Stein <wstein@gmail.com>
-#
-#  Distributed under the terms of the GNU General Public License (GPL)
-#
-#    This code is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#    General Public License for more details.
-#
-#  The full text of the GPL is available at:
-#
-#                  http://www.gnu.org/licenses/
-#*****************************************************************************/
-
-/*  Author:  Joel B. Mohler <joel@kiwistrawberry.us>
-			 2007-06-17                                                      */
-
-#include "ZZ_pylong.h"
-#include "ntl_wrap.h"
-extern "C" {
-    #include "mpz_pylong.h"
-}
-
-using namespace NTL;
-
-/* ZZ -> pylong conversion */
-PyObject * ZZ_get_pylong(ZZ &z)
-{
-    mpz_t temp;
-    mpz_init(temp);
-    ZZ_to_mpz( &temp, &z );
-    return mpz_get_pylong( temp );
-}
-
-/* pylong -> ZZ conversion */
-int ZZ_set_pylong(ZZ &z, PyObject * ll)
-{
-    mpz_t temp;
-    mpz_init(temp);
-    mpz_set_pylong( temp, ll );
-    mpz_to_ZZ( &z, &temp );
-}
Index: _lib/ZZ_pylong.h
===================================================================
--- c_lib/ZZ_pylong.h	(revision 6011)
+++ 	(revision )
@@ -1,37 +1,0 @@
-/*****************************************************************************
-#       Copyright (C) 2007 William Stein <wstein@gmail.com>
-#
-#  Distributed under the terms of the GNU General Public License (GPL)
-#
-#    This code is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#    General Public License for more details.
-#
-#  The full text of the GPL is available at:
-#
-#                  http://www.gnu.org/licenses/
-#*****************************************************************************/
-
-/*  Author:  Joel B. Mohler <joel@kiwistrawberry.us>
-			 2007-06-17                                                      */
-
-#ifndef ZZ_PYLONG_H
-#define ZZ_PYLONG_H
-
-/* Yes, this is kind of weird.  I'm only wrapping this for C++ */
-#ifdef __cplusplus
-
-#include <Python.h>
-#include <NTL/ZZ.h>
-using namespace NTL;
-#include "gmp.h"
-
-/* ZZ -> pylong conversion */
-PyObject * ZZ_get_pylong(ZZ &z);
-
-/* pylong -> ZZ conversion */
-int ZZ_set_pylong(ZZ &z, PyObject * ll);
-#endif
-
-#endif
Index: _lib/ccobject.h
===================================================================
--- c_lib/ccobject.h	(revision 6011)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/******************************************************************************
-       Copyright (C) 2007 Joel B. Mohler <joel@kiwistrawberry.us>
-
-  Distributed under the terms of the GNU General Public License (GPL), Version 2.
-
-  The full text of the GPL is available at:
-                  http://www.gnu.org/licenses/
-
-******************************************************************************/
-
-/**
- * @file ccobject.h
- *
- * @author Joel B. Mohler <joel@kiwistrawberry.us>
- *
- * @brief These functions provide assistance for constructing and destructing 
- *  C++ objects from pyrex.
- *
- */
-
-#ifdef __cplusplus
-
-#include <iostream>
-#include <sstream>
-
-/* Ok, we are in C++ mode.  Lets define some templated functions for construction 
-and destruction of allocated memory chunks. */
-
-/* Allocate and Construct */
-template <class T>
-T* New(){
-  return new T();
-}
-
-/* Construct */
-template <class T>
-T* Construct(void* mem){
-  return new(mem) T();
-}
-
-/* Destruct */
-template <class T>
-void Destruct(T* mem){
-  mem->~T();
-}
-
-/* Deallocate and Destruct */
-template <class T>
-void Delete(T* mem){
-  delete mem;
-}
-
-template <class T>
-void _from_str(T* dest, char* src){
-  std::istringstream out(src);
-  out >> *dest;
-}
-
-#endif
Index: _lib/depcomp
===================================================================
--- c_lib/depcomp	(revision 6004)
+++ 	(revision )
@@ -1,530 +1,0 @@
-#! /bin/sh
-# depcomp - compile a program generating dependencies as side-effects
-
-scriptversion=2005-07-09.11
-
-# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
-
-case $1 in
-  '')
-     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
-     exit 1;
-     ;;
-  -h | --h*)
-    cat <<\EOF
-Usage: depcomp [--help] [--version] PROGRAM [ARGS]
-
-Run PROGRAMS ARGS to compile a file, generating dependencies
-as side-effects.
-
-Environment variables:
-  depmode     Dependency tracking mode.
-  source      Source file read by `PROGRAMS ARGS'.
-  object      Object file output by `PROGRAMS ARGS'.
-  DEPDIR      directory where to store dependencies.
-  depfile     Dependency file to output.
-  tmpdepfile  Temporary file to use when outputing dependencies.
-  libtool     Whether libtool is used (yes/no).
-
-Report bugs to <bug-automake@gnu.org>.
-EOF
-    exit $?
-    ;;
-  -v | --v*)
-    echo "depcomp $scriptversion"
-    exit $?
-    ;;
-esac
-
-if test -z "$depmode" || test -z "$source" || test -z "$object"; then
-  echo "depcomp: Variables source, object and depmode must be set" 1>&2
-  exit 1
-fi
-
-# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
-depfile=${depfile-`echo "$object" |
-  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
-tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
-
-rm -f "$tmpdepfile"
-
-# Some modes work just like other modes, but use different flags.  We
-# parameterize here, but still list the modes in the big case below,
-# to make depend.m4 easier to write.  Note that we *cannot* use a case
-# here, because this file can only contain one case statement.
-if test "$depmode" = hp; then
-  # HP compiler uses -M and no extra arg.
-  gccflag=-M
-  depmode=gcc
-fi
-
-if test "$depmode" = dashXmstdout; then
-   # This is just like dashmstdout with a different argument.
-   dashmflag=-xM
-   depmode=dashmstdout
-fi
-
-case "$depmode" in
-gcc3)
-## gcc 3 implements dependency tracking that does exactly what
-## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
-## it if -MD -MP comes after the -MF stuff.  Hmm.
-  "$@" -MT "$object" -MD -MP -MF "$tmpdepfile"
-  stat=$?
-  if test $stat -eq 0; then :
-  else
-    rm -f "$tmpdepfile"
-    exit $stat
-  fi
-  mv "$tmpdepfile" "$depfile"
-  ;;
-
-gcc)
-## There are various ways to get dependency output from gcc.  Here's
-## why we pick this rather obscure method:
-## - Don't want to use -MD because we'd like the dependencies to end
-##   up in a subdir.  Having to rename by hand is ugly.
-##   (We might end up doing this anyway to support other compilers.)
-## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
-##   -MM, not -M (despite what the docs say).
-## - Using -M directly means running the compiler twice (even worse
-##   than renaming).
-  if test -z "$gccflag"; then
-    gccflag=-MD,
-  fi
-  "$@" -Wp,"$gccflag$tmpdepfile"
-  stat=$?
-  if test $stat -eq 0; then :
-  else
-    rm -f "$tmpdepfile"
-    exit $stat
-  fi
-  rm -f "$depfile"
-  echo "$object : \\" > "$depfile"
-  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
-## The second -e expression handles DOS-style file names with drive letters.
-  sed -e 's/^[^:]*: / /' \
-      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
-## This next piece of magic avoids the `deleted header file' problem.
-## The problem is that when a header file which appears in a .P file
-## is deleted, the dependency causes make to die (because there is
-## typically no way to rebuild the header).  We avoid this by adding
-## dummy dependencies for each header file.  Too bad gcc doesn't do
-## this for us directly.
-  tr ' ' '
-' < "$tmpdepfile" |
-## Some versions of gcc put a space before the `:'.  On the theory
-## that the space means something, we add a space to the output as
-## well.
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly.  Breaking it into two sed invocations is a workaround.
-    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
-  rm -f "$tmpdepfile"
-  ;;
-
-hp)
-  # This case exists only to let depend.m4 do its work.  It works by
-  # looking at the text of this script.  This case will never be run,
-  # since it is checked for above.
-  exit 1
-  ;;
-
-sgi)
-  if test "$libtool" = yes; then
-    "$@" "-Wp,-MDupdate,$tmpdepfile"
-  else
-    "$@" -MDupdate "$tmpdepfile"
-  fi
-  stat=$?
-  if test $stat -eq 0; then :
-  else
-    rm -f "$tmpdepfile"
-    exit $stat
-  fi
-  rm -f "$depfile"
-
-  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
-    echo "$object : \\" > "$depfile"
-
-    # Clip off the initial element (the dependent).  Don't try to be
-    # clever and replace this with sed code, as IRIX sed won't handle
-    # lines with more than a fixed number of characters (4096 in
-    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
-    # the IRIX cc adds comments like `#:fec' to the end of the
-    # dependency line.
-    tr ' ' '
-' < "$tmpdepfile" \
-    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
-    tr '
-' ' ' >> $depfile
-    echo >> $depfile
-
-    # The second pass generates a dummy entry for each header file.
-    tr ' ' '
-' < "$tmpdepfile" \
-   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
-   >> $depfile
-  else
-    # The sourcefile does not contain any dependencies, so just
-    # store a dummy comment line, to avoid errors with the Makefile
-    # "include basename.Plo" scheme.
-    echo "#dummy" > "$depfile"
-  fi
-  rm -f "$tmpdepfile"
-  ;;
-
-aix)
-  # The C for AIX Compiler uses -M and outputs the dependencies
-  # in a .u file.  In older versions, this file always lives in the
-  # current directory.  Also, the AIX compiler puts `$object:' at the
-  # start of each line; $object doesn't have directory information.
-  # Version 6 uses the directory in both cases.
-  stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
-  tmpdepfile="$stripped.u"
-  if test "$libtool" = yes; then
-    "$@" -Wc,-M
-  else
-    "$@" -M
-  fi
-  stat=$?
-
-  if test -f "$tmpdepfile"; then :
-  else
-    stripped=`echo "$stripped" | sed 's,^.*/,,'`
-    tmpdepfile="$stripped.u"
-  fi
-
-  if test $stat -eq 0; then :
-  else
-    rm -f "$tmpdepfile"
-    exit $stat
-  fi
-
-  if test -f "$tmpdepfile"; then
-    outname="$stripped.o"
-    # Each line is of the form `foo.o: dependent.h'.
-    # Do two passes, one to just change these to
-    # `$object: dependent.h' and one to simply `dependent.h:'.
-    sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
-    sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
-  else
-    # The sourcefile does not contain any dependencies, so just
-    # store a dummy comment line, to avoid errors with the Makefile
-    # "include basename.Plo" scheme.
-    echo "#dummy" > "$depfile"
-  fi
-  rm -f "$tmpdepfile"
-  ;;
-
-icc)
-  # Intel's C compiler understands `-MD -MF file'.  However on
-  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
-  # ICC 7.0 will fill foo.d with something like
-  #    foo.o: sub/foo.c
-  #    foo.o: sub/foo.h
-  # which is wrong.  We want:
-  #    sub/foo.o: sub/foo.c
-  #    sub/foo.o: sub/foo.h
-  #    sub/foo.c:
-  #    sub/foo.h:
-  # ICC 7.1 will output
-  #    foo.o: sub/foo.c sub/foo.h
-  # and will wrap long lines using \ :
-  #    foo.o: sub/foo.c ... \
-  #     sub/foo.h ... \
-  #     ...
-
-  "$@" -MD -MF "$tmpdepfile"
-  stat=$?
-  if test $stat -eq 0; then :
-  else
-    rm -f "$tmpdepfile"
-    exit $stat
-  fi
-  rm -f "$depfile"
-  # Each line is of the form `foo.o: dependent.h',
-  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
-  # Do two passes, one to just change these to
-  # `$object: dependent.h' and one to simply `dependent.h:'.
-  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
-  # Some versions of the HPUX 10.20 sed can't process this invocation
-  # correctly.  Breaking it into two sed invocations is a workaround.
-  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
-    sed -e 's/$/ :/' >> "$depfile"
-  rm -f "$tmpdepfile"
-  ;;
-
-tru64)
-   # The Tru64 compiler uses -MD to generate dependencies as a side
-   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
-   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
-   # dependencies in `foo.d' instead, so we check for that too.
-   # Subdirectories are respected.
-   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
-   test "x$dir" = "x$object" && dir=
-   base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
-
-   if test "$libtool" = yes; then
-      # With Tru64 cc, shared objects can also be used to make a
-      # static library.  This mecanism is used in libtool 1.4 series to
-      # handle both shared and static libraries in a single compilation.
-      # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
-      #
-      # With libtool 1.5 this exception was removed, and libtool now
-      # generates 2 separate objects for the 2 libraries.  These two
-      # compilations output dependencies in in $dir.libs/$base.o.d and
-      # in $dir$base.o.d.  We have to check for both files, because
-      # one of the two compilations can be disabled.  We should prefer
-      # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
-      # automatically cleaned when .libs/ is deleted, while ignoring
-      # the former would cause a distcleancheck panic.
-      tmpdepfile1=$dir.libs/$base.lo.d   # libtool 1.4
-      tmpdepfile2=$dir$base.o.d          # libtool 1.5
-      tmpdepfile3=$dir.libs/$base.o.d    # libtool 1.5
-      tmpdepfile4=$dir.libs/$base.d      # Compaq CCC V6.2-504
-      "$@" -Wc,-MD
-   else
-      tmpdepfile1=$dir$base.o.d
-      tmpdepfile2=$dir$base.d
-      tmpdepfile3=$dir$base.d
-      tmpdepfile4=$dir$base.d
-      "$@" -MD
-   fi
-
-   stat=$?
-   if test $stat -eq 0; then :
-   else
-      rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
-      exit $stat
-   fi
-
-   for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
-   do
-     test -f "$tmpdepfile" && break
-   done
-   if test -f "$tmpdepfile"; then
-      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
-      # That's a tab and a space in the [].
-      sed -e 's,^.*\.[a-z]*:[	 ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
-   else
-      echo "#dummy" > "$depfile"
-   fi
-   rm -f "$tmpdepfile"
-   ;;
-
-#nosideeffect)
-  # This comment above is used by automake to tell side-effect
-  # dependency tracking mechanisms from slower ones.
-
-dashmstdout)
-  # Important note: in order to support this mode, a compiler *must*
-  # always write the preprocessed file to stdout, regardless of -o.
-  "$@" || exit $?
-
-  # Remove the call to Libtool.
-  if test "$libtool" = yes; then
-    while test $1 != '--mode=compile'; do
-      shift
-    done
-    shift
-  fi
-
-  # Remove `-o $object'.
-  IFS=" "
-  for arg
-  do
-    case $arg in
-    -o)
-      shift
-      ;;
-    $object)
-      shift
-      ;;
-    *)
-      set fnord "$@" "$arg"
-      shift # fnord
-      shift # $arg
-      ;;
-    esac
-  done
-
-  test -z "$dashmflag" && dashmflag=-M
-  # Require at least two characters before searching for `:'
-  # in the target name.  This is to cope with DOS-style filenames:
-  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
-  "$@" $dashmflag |
-    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
-  rm -f "$depfile"
-  cat < "$tmpdepfile" > "$depfile"
-  tr ' ' '
-' < "$tmpdepfile" | \
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly.  Breaking it into two sed invocations is a workaround.
-    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
-  rm -f "$tmpdepfile"
-  ;;
-
-dashXmstdout)
-  # This case only exists to satisfy depend.m4.  It is never actually
-  # run, as this mode is specially recognized in the preamble.
-  exit 1
-  ;;
-
-makedepend)
-  "$@" || exit $?
-  # Remove any Libtool call
-  if test "$libtool" = yes; then
-    while test $1 != '--mode=compile'; do
-      shift
-    done
-    shift
-  fi
-  # X makedepend
-  shift
-  cleared=no
-  for arg in "$@"; do
-    case $cleared in
-    no)
-      set ""; shift
-      cleared=yes ;;
-    esac
-    case "$arg" in
-    -D*|-I*)
-      set fnord "$@" "$arg"; shift ;;
-    # Strip any option that makedepend may not understand.  Remove
-    # the object too, otherwise makedepend will parse it as a source file.
-    -*|$object)
-      ;;
-    *)
-      set fnord "$@" "$arg"; shift ;;
-    esac
-  done
-  obj_suffix="`echo $object | sed 's/^.*\././'`"
-  touch "$tmpdepfile"
-  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
-  rm -f "$depfile"
-  cat < "$tmpdepfile" > "$depfile"
-  sed '1,2d' "$tmpdepfile" | tr ' ' '
-' | \
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly.  Breaking it into two sed invocations is a workaround.
-    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
-  rm -f "$tmpdepfile" "$tmpdepfile".bak
-  ;;
-
-cpp)
-  # Important note: in order to support this mode, a compiler *must*
-  # always write the preprocessed file to stdout.
-  "$@" || exit $?
-
-  # Remove the call to Libtool.
-  if test "$libtool" = yes; then
-    while test $1 != '--mode=compile'; do
-      shift
-    done
-    shift
-  fi
-
-  # Remove `-o $object'.
-  IFS=" "
-  for arg
-  do
-    case $arg in
-    -o)
-      shift
-      ;;
-    $object)
-      shift
-      ;;
-    *)
-      set fnord "$@" "$arg"
-      shift # fnord
-      shift # $arg
-      ;;
-    esac
-  done
-
-  "$@" -E |
-    sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-       -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
-    sed '$ s: \\$::' > "$tmpdepfile"
-  rm -f "$depfile"
-  echo "$object : \\" > "$depfile"
-  cat < "$tmpdepfile" >> "$depfile"
-  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
-  rm -f "$tmpdepfile"
-  ;;
-
-msvisualcpp)
-  # Important note: in order to support this mode, a compiler *must*
-  # always write the preprocessed file to stdout, regardless of -o,
-  # because we must use -o when running libtool.
-  "$@" || exit $?
-  IFS=" "
-  for arg
-  do
-    case "$arg" in
-    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
-	set fnord "$@"
-	shift
-	shift
-	;;
-    *)
-	set fnord "$@" "$arg"
-	shift
-	shift
-	;;
-    esac
-  done
-  "$@" -E |
-  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
-  rm -f "$depfile"
-  echo "$object : \\" > "$depfile"
-  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::	\1 \\:p' >> "$depfile"
-  echo "	" >> "$depfile"
-  . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
-  rm -f "$tmpdepfile"
-  ;;
-
-none)
-  exec "$@"
-  ;;
-
-*)
-  echo "Unknown depmode $depmode" 1>&2
-  exit 1
-  ;;
-esac
-
-exit 0
-
-# Local Variables:
-# mode: shell-script
-# sh-indentation: 2
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
-# End:
Index: _lib/gmp_globals.c
===================================================================
--- c_lib/gmp_globals.c	(revision 6226)
+++ 	(revision )
@@ -1,49 +1,0 @@
-#include "gmp_globals.h"
-
-mpz_t u, v, q, u0, u1, u2, v0, v1, v2, t0, t1, t2, x, y, sqr, m2;
-mpq_t tmp;
-
-mpz_t a1, a2, mod1, mod2, g, s, t, xx;
-
-mpz_t crtrr_a, crtrr_mod;
-
-mpz_t rand_val, rand_n, rand_n1;
-
-gmp_randstate_t rand_state;
-
-void init_mpz_globals() {
-  mpz_init(u);  mpz_init(v); mpz_init(q);
-  mpz_init(u0); mpz_init(u1); mpz_init(u2);
-  mpz_init(v0); mpz_init(v1); mpz_init(v2);
-  mpz_init(t0); mpz_init(t1); mpz_init(t2);
-  mpz_init(x);  mpz_init(y);
-  mpz_init(sqr);  mpz_init(m2);
-  mpq_init(tmp);
-
-  mpz_init(a1); mpz_init(a2); mpz_init(mod1); mpz_init(mod2);
-  mpz_init(g); mpz_init(s); mpz_init(t); mpz_init(xx);
-
-  mpz_init(crtrr_a); mpz_init(crtrr_mod);
-
-  mpz_init(rand_val); mpz_init(rand_n); mpz_init(rand_n1);
-
-  gmp_randinit_default(rand_state);
-}
-
-void clear_mpz_globals() {
-  mpz_clear(u);  mpz_clear(v); mpz_clear(q);
-  mpz_clear(u0); mpz_clear(u1); mpz_clear(u2);
-  mpz_clear(v0); mpz_clear(v1); mpz_clear(v2);
-  mpz_clear(t0); mpz_clear(t1); mpz_clear(t2);
-  mpz_clear(x);  mpz_clear(y);
-  mpz_clear(sqr);  mpz_clear(m2);
-  mpq_init(tmp);
-
-  mpz_clear(a1); mpz_clear(a2); mpz_clear(mod1); mpz_clear(mod2);
-  mpz_clear(g); mpz_clear(s); mpz_clear(t); mpz_clear(xx);
-
-  mpz_clear(crtrr_a); mpz_clear(crtrr_mod);
-
-  mpz_clear(rand_val); mpz_clear(rand_n); mpz_clear(rand_n1);
-}
-
Index: _lib/gmp_globals.h
===================================================================
--- c_lib/gmp_globals.h	(revision 6226)
+++ 	(revision )
@@ -1,17 +1,0 @@
-#include <gmp.h>
-
-// these vars are all used in rational reconstruction; they're cached so we don't
-// have to recreate them with every call.
-extern mpz_t u, v, q, u0, u1, u2, v0, v1, v2, t0, t1, t2, x, y, sqr, m2;
-extern mpq_t tmp;
-
-extern mpz_t a1, a2, mod1, mod2, g, s, t, xx;
-
-extern mpz_t crtrr_a, crtrr_mod;
-
-extern mpz_t rand_val, rand_n, rand_n1;
-
-extern gmp_randstate_t rand_state;
-
-void init_mpz_globals();
-void clear_mpz_globals();
Index: c_lib/include/ZZ_pylong.h
===================================================================
--- c_lib/include/ZZ_pylong.h	(revision 6597)
+++ c_lib/include/ZZ_pylong.h	(revision 6597)
@@ -0,0 +1,37 @@
+/*****************************************************************************
+#       Copyright (C) 2007 William Stein <wstein@gmail.com>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************/
+
+/*  Author:  Joel B. Mohler <joel@kiwistrawberry.us>
+			 2007-06-17                                                      */
+
+#ifndef ZZ_PYLONG_H
+#define ZZ_PYLONG_H
+
+/* Yes, this is kind of weird.  I'm only wrapping this for C++ */
+#ifdef __cplusplus
+
+#include <Python.h>
+#include <NTL/ZZ.h>
+using namespace NTL;
+#include "gmp.h"
+
+/* ZZ -> pylong conversion */
+PyObject * ZZ_get_pylong(ZZ &z);
+
+/* pylong -> ZZ conversion */
+int ZZ_set_pylong(ZZ &z, PyObject * ll);
+#endif
+
+#endif
Index: c_lib/include/ccobject.h
===================================================================
--- c_lib/include/ccobject.h	(revision 6873)
+++ c_lib/include/ccobject.h	(revision 6873)
@@ -0,0 +1,73 @@
+/******************************************************************************
+       Copyright (C) 2007 Joel B. Mohler <joel@kiwistrawberry.us>
+
+  Distributed under the terms of the GNU General Public License (GPL), Version 2.
+
+  The full text of the GPL is available at:
+                  http://www.gnu.org/licenses/
+
+******************************************************************************/
+
+/**
+ * @file ccobject.h
+ *
+ * @author Joel B. Mohler <joel@kiwistrawberry.us>
+ *
+ * @brief These functions provide assistance for constructing and destructing 
+ *  C++ objects from pyrex.
+ *
+ */
+
+#ifdef __cplusplus
+
+#include <iostream>
+#include <sstream>
+
+/* Ok, we are in C++ mode.  Lets define some templated functions for construction 
+and destruction of allocated memory chunks. */
+
+/* Allocate and Construct */
+template <class T>
+T* New(){
+  return new T();
+}
+
+/* Construct */
+template <class T>
+T* Construct(void* mem){
+  return new(mem) T();
+}
+
+/* Destruct */
+template <class T>
+void Destruct(T* mem){
+  mem->~T();
+}
+
+/* Deallocate and Destruct */
+template <class T>
+void Delete(T* mem){
+  delete mem;
+}
+
+template <class T>
+bool _equal(T lhs, T rhs)
+{
+    return lhs == rhs;
+}
+
+template <class T>
+void _from_str(T* dest, char* src){
+  std::istringstream out(src);
+  out >> *dest;
+}
+
+template <class T>
+PyObject* _to_PyString(const T *x) 
+{
+  std::ostringstream instore;
+  instore << (*x);
+  return PyString_FromString(instore.str().data());
+}
+
+#endif
Index: c_lib/include/convert.h
===================================================================
--- c_lib/include/convert.h	(revision 6883)
+++ c_lib/include/convert.h	(revision 6883)
@@ -0,0 +1,17 @@
+/*
+
+  convert.h
+  2007 Aug 19
+  Author: Craig Citro
+
+  C header for conversions to and from pari types.
+  
+*/
+
+#include <gmp.h>
+#include <pari/pari.h>
+#include <stdio.h>
+
+void t_INT_to_ZZ ( mpz_t value, GEN g );
+
+void ZZ_to_t_INT ( GEN *g, mpz_t value );
Index: c_lib/include/gmp_globals.h
===================================================================
--- c_lib/include/gmp_globals.h	(revision 7016)
+++ c_lib/include/gmp_globals.h	(revision 7016)
@@ -0,0 +1,24 @@
+#include <gmp.h>
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+#else
+#define EXTERN extern
+#endif
+
+// these vars are all used in rational reconstruction; they're cached so we don't
+// have to recreate them with every call.
+EXTERN mpz_t u, v, q, u0, u1, u2, v0, v1, v2, t0, t1, t2, x, y, ssqr, m2;
+EXTERN mpq_t tmp;
+
+EXTERN mpz_t a1, a2, mod1, mod2, g, s, t, xx;
+
+EXTERN mpz_t crtrr_a, crtrr_mod;
+
+EXTERN mpz_t rand_val, rand_n, rand_n1;
+
+EXTERN gmp_randstate_t rand_state;
+
+EXTERN void init_mpz_globals();
+EXTERN void clear_mpz_globals();
+
Index: c_lib/include/interrupt.h
===================================================================
--- c_lib/include/interrupt.h	(revision 6597)
+++ c_lib/include/interrupt.h	(revision 6597)
@@ -0,0 +1,242 @@
+/******************************************************************************
+       Copyright (C) 2006 William Stein <wstein@gmail.com>
+                     2006 Martin Albrecht <malb@informatik.uni-bremen.de>
+
+  Distributed under the terms of the GNU General Public License (GPL), Version 2.
+
+  The full text of the GPL is available at:
+                  http://www.gnu.org/licenses/
+
+******************************************************************************/
+
+#ifndef FOO_H
+#define FOO_H
+#include <setjmp.h>
+#include <Python.h>
+#include <signal.h>
+
+
+
+/* In your Pyrex code, put 
+
+    _sig_on
+    [pure c code block]
+    _sig_off
+
+   to get signal handling capabilities. 
+
+   VERY VERY IMPORTANT:  
+       1. These *must* always come in pairs. E.g., if you have just 
+          a _sig_off without a corresponding _sig_on, then ctrl-c
+          later in the interpreter will sigfault!
+
+       2. Do *not* put these in the __init__ method of a Pyrex extension
+          class, or you'll get crashes. 
+
+       3. Do not put these around any non-pure C code!!!!
+
+       4. If you need to do a check of control-c inside a loop, e.g.,
+          when constructing a matrix, put _sig_check instead of using
+          _sig_on then _sig_off.
+*/
+
+/**
+ * bitmask to enable the sage signal handler
+ */
+
+#define SIG_SAGE_HANDLER 1
+
+/**
+ * bitmask to enable long jumps
+ */
+#define SIG_LONG_JMP 2
+
+/**
+ * bitmask that a signal has been received.
+ *
+ */
+
+#define SIG_SIGNAL_RECEIVED 4
+
+/**
+ * default signal handler for SIGINT, SIGALRM, SIGSEGV, SIGABRT,
+ * SIGFPE in the context of SAGE. It calls the default Python handler
+ * if _signals.sage_handler == 0.
+ */
+
+void sage_signal_handler(int n);
+
+
+/**
+ * fallback signal handlers
+ */
+void sig_handle_sigsegv(int n);
+void sig_handle_sigbus(int n);
+void sig_handle_sigfpe(int n);
+
+/**
+ * Supposed to be called exactly once to ensure the SAGE signal
+ * handler is the default signal handler. This function implements a
+ * mechanism to make sure it is only called once so it is safe to call
+ * it more than once.
+ *
+ */
+
+void setup_signal_handler(void);
+
+#if defined (__sun__) || defined (__sun)   /* Needed for Solaris below. */
+   typedef void (*__sighandler_t )();
+#endif
+
+/**
+ * All relevant data for the signal handler is bundled in this struct.
+ *
+ */
+
+struct sage_signals {
+
+  /**
+   * Bitmask which determines what to do in the signal handler. Let
+   * bit 0 be the least significant bit, then the bitmask is as follows:
+   \verbatim
+     bit | semantic
+     -------------------------------------------
+       0 | use sage signal handler (1) or default (0)
+       1 | use longjmp (1) or return (0)
+       2 | signal received (1) or not (0)
+   \endverbatim
+   * 
+   * You may want to use the provided definitions SIG_SAGE_HANDLER,
+   * SIG_LONG_JMP, SIG_SIGNAL_RECEIVED.
+   */
+
+  int mpio;
+
+  /**
+   * An internal buffer holding where to jump after a signal has been
+   * received, don't touch!
+   */
+
+  sigjmp_buf env;
+
+
+  /**
+   * An optional string may be passed to the signal handler which will
+   * be printed. Use _sig_str for that.
+   */
+  char *s;
+  
+
+  /** 
+   * Unfortunately signal handler function declarations vary HUGELY
+   * from platform to platform:
+   */
+
+#if defined(__CYGWIN32__)     /* Windows XP */
+
+  _sig_func_ptr  python_handler;
+
+#elif defined(__FreeBSD__)    /* FreeBSD */
+
+  sig_t  python_handler;
+
+#elif defined(__APPLE__)      /* OSX */
+
+  sig_t  python_handler;
+
+#elif defined (__sun__) || defined (__sun)   /* Solaris */
+
+  __sighandler_t  python_handler;
+
+#else                                   /* Other, e.g., Linux */
+
+  __sighandler_t python_handler;
+
+#endif
+
+};
+
+/**
+ * The actual object.
+ */
+
+extern struct sage_signals _signals;
+
+/**
+ * Enables SAGE signal handling for the following C block. This macro
+ * *MUST* be followed by _sig_off.
+ *
+ *
+ * See also @ref _sig_str
+ */
+
+#define _sig_on if (_signals.mpio == 0) { _signals.mpio = 1+2; _signals.s = NULL;\
+                 if (sigsetjmp(_signals.env,1)) { \
+                  _signals.mpio = 0;   \
+                  return(0); \
+                } } // else { _signals.s = "Unbalanced _sig_on/_sig_off\n"; fprintf(stderr, _signals.s); sage_signal_handler(SIGABRT); }
+
+/* /\** */
+/*  * Enables SAGE signal handling for the following C block. This macro */
+/*  * *MUST* be followed by _sig_off_short. */
+/*  * */
+/*  * If the following block takes very little time to compute this macro */
+/*  * is the right choice. Otherwise _sig_on is appropriate. */
+/*  * */
+/*  * See also _sig_on and _sig_str. */
+/*  * */
+/*  *\/ */
+
+/* #define _sig_on_short _signals.mpio = 1 */
+
+
+/**
+ * Same as @ref _sig_on but with string support
+ *
+ */
+ 
+#define _sig_str(mstring) if (_signals.mpio == 0) { _signals.mpio = 1+2; \
+                _signals.s = mstring; \
+                if (sigsetjmp(_signals.env,1)) { \
+                  _signals.mpio = 0; \
+                 return(0); \
+                } } //else { _signals.s = "Unbalanced _sig_str/_sig_off\n"; fprintf(stderr, _signals.s); sage_signal_handler(SIGABRT); }
+
+
+/**
+ *
+ *
+ */
+
+#define _sig_off _signals.mpio = 0; 
+
+
+/* /\** */
+/*  * */
+/*  * */
+/*  *\/ */
+
+/* #define _sig_off_short (_signals.mpio & 4) */
+
+
+/**
+ *
+ *
+ */
+
+#define _sig_check _sig_on _sig_off
+
+#endif /* FOO_H */
+
+/*
+I thought maybe the following would work nicely, instead of just
+returning, but no (it crashes sometimes!).  Also the line number is
+not set correctly.  The only way I can imagine setting this correctly
+is if the following bit of code is generated within pyrex, since pyrex
+knows the line numbers.
+
+	             PyErr_SetString(PyExc_RuntimeError, "(complete C-level traceback not available)"); \
+		     __pyx_filename = __pyx_f[1]; __pyx_lineno = 0; goto __pyx_L1; \
+                }
+
+*/
Index: c_lib/include/mpn_pylong.h
===================================================================
--- c_lib/include/mpn_pylong.h	(revision 6597)
+++ c_lib/include/mpn_pylong.h	(revision 6597)
@@ -0,0 +1,49 @@
+#ifndef MPN_PYLONG_H
+#define MPN_PYLONG_H
+
+#include <Python.h>
+#include <gmp.h>
+
+/************************************************************/
+
+/* Python internals for pylong */
+
+#include <longintrepr.h>
+typedef int py_size_t; /* what python uses for ob_size */
+
+/************************************************************/
+
+/* mpn -> pylong conversion */
+
+int mpn_pylong_size (mp_ptr up, mp_size_t un);
+
+/* Assume digits points to a chunk of size size
+ * where size >= mpn_pylong_size(up, un)
+ */
+void mpn_get_pylong (digit *digits, py_size_t size, mp_ptr up, mp_size_t un);
+
+/************************************************************/
+
+/* pylong -> mpn conversion */
+
+mp_size_t mpn_size_from_pylong (digit *digits, py_size_t size);
+
+/* Assume up points to a chunk of size un
+ * where un >= mpn_size_from_pylong(digits, size)
+ */
+void mpn_set_pylong (mp_ptr up, mp_size_t un, digit *digits, py_size_t size);
+
+/************************************************************/
+
+/* Python hashing */
+
+/*
+ * for an mpz, this number has to be multiplied by the sign
+ * also remember to catch -1 and map it to -2 !
+ */
+
+long mpn_pythonhash (mp_ptr up, mp_size_t un);
+
+/************************************************************/
+
+#endif
Index: c_lib/include/mpz_pylong.h
===================================================================
--- c_lib/include/mpz_pylong.h	(revision 6597)
+++ c_lib/include/mpz_pylong.h	(revision 6597)
@@ -0,0 +1,19 @@
+#ifndef MPZ_PYLONG_H
+#define MPZ_PYLONG_H
+
+#include <Python.h>
+#include <gmp.h>
+
+/* mpz -> pylong conversion */
+PyObject * mpz_get_pylong(mpz_srcptr z);
+
+/* mpz -> pyint/pylong conversion */
+PyObject * mpz_get_pyintlong(mpz_srcptr z);
+
+/* pylong -> mpz conversion */
+int mpz_set_pylong(mpz_ptr z, PyObject * ll);
+
+/* mpz python hash */
+long mpz_pythonhash (mpz_srcptr z);
+
+#endif
Index: c_lib/include/ntl_wrap.h
===================================================================
--- c_lib/include/ntl_wrap.h	(revision 7049)
+++ c_lib/include/ntl_wrap.h	(revision 7049)
@@ -0,0 +1,328 @@
+#ifdef __cplusplus
+#include <NTL/ZZ.h>
+#include <NTL/ZZX.h>
+#include <NTL/ZZ_pXFactoring.h>
+#include <NTL/ZZXFactoring.h>
+#include <NTL/ZZ_p.h>
+#include <NTL/ZZ_pX.h>
+#include <NTL/ZZ_pE.h>
+#include <NTL/ZZ_pEX.h>
+#include <NTL/lzz_p.h>
+#include <NTL/lzz_pX.h>
+#include <NTL/mat_ZZ.h>
+#include <NTL/mat_poly_ZZ.h>
+#include <NTL/GF2E.h>
+#include <NTL/GF2X.h>
+#include <NTL/GF2EX.h>
+#include <NTL/mat_GF2E.h>
+#include <NTL/HNF.h>
+#include <gmp.h>
+using namespace NTL;
+#endif
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+#else 
+#define EXTERN
+#endif
+
+#include "Python.h"
+#include "ccobject.h"
+
+EXTERN void del_charstar(char*);
+
+////////  ZZ //////////
+
+#ifndef __cplusplus
+struct ZZ;
+#endif
+
+EXTERN int ZZ_to_int(const struct ZZ* x);
+EXTERN struct ZZ* int_to_ZZ(int value);
+EXTERN void ZZ_to_mpz(mpz_t* output, const struct ZZ* x);
+EXTERN void mpz_to_ZZ(struct ZZ *output, const mpz_t* x);
+EXTERN void ZZ_set_from_int(struct ZZ* x, int value);
+/*Random-number generation */
+//EXTERN void setSeed(const struct ZZ* n);
+//EXTERN struct ZZ* ZZ_randomBnd(const struct ZZ* x);
+//EXTERN struct ZZ* ZZ_randomBits(long n);
+
+EXTERN long ZZ_remove(struct ZZ x, const struct ZZ a, const struct ZZ p);
+
+
+////////  ZZ_p //////////
+
+#ifndef __cplusplus
+struct ZZ_p;
+#endif
+
+#ifdef __cplusplus  // sorry, if you want a C version, feel free to add it
+EXTERN int ZZ_p_to_int(const ZZ_p& x);
+EXTERN ZZ_p int_to_ZZ_p(int value);
+#endif
+EXTERN void ZZ_p_set_from_int(struct ZZ_p* x, int value);
+EXTERN struct ZZ_p* ZZ_p_pow(const struct ZZ_p* x, long e);
+EXTERN void ntl_ZZ_set_modulus(struct ZZ* x);
+EXTERN struct ZZ_p* ZZ_p_inv(struct ZZ_p* x);
+EXTERN struct ZZ_p* ZZ_p_neg(struct ZZ_p* x);
+EXTERN struct ZZ_p* ZZ_p_random(void);
+EXTERN void ZZ_p_modulus(struct ZZ* mod, const struct ZZ_p* x);
+
+
+EXTERN struct ZZ_pContext* ZZ_pContext_new(struct ZZ* p);
+EXTERN struct ZZ_pContext* ZZ_pContext_construct(void* mem, struct ZZ* p);
+
+//////// ZZX //////////
+#ifndef __cplusplus
+struct ZZX;
+#endif
+
+EXTERN char* ZZX_repr(struct ZZX* x);
+EXTERN struct ZZX* ZZX_copy(struct ZZX* x);
+EXTERN void ZZX_setitem_from_int(struct ZZX* x, long i, int value);
+EXTERN int ZZX_getitem_as_int(struct ZZX* x, long i);
+EXTERN void ZZX_getitem_as_mpz(mpz_t* output, struct ZZX* x, long i);
+EXTERN struct ZZX* ZZX_div(struct ZZX* x, struct ZZX* y, int* divisible);
+EXTERN void ZZX_quo_rem(struct ZZX* x, struct ZZX* other, struct ZZX** r, struct ZZX** q);
+EXTERN struct ZZX* ZZX_square(struct ZZX* x);
+EXTERN int ZZX_equal(struct ZZX* x, struct ZZX* y);
+EXTERN int ZZX_is_monic(struct ZZX* x);
+EXTERN struct ZZX* ZZX_neg(struct ZZX* x);
+EXTERN struct ZZX* ZZX_left_shift(struct ZZX* x, long n);
+EXTERN struct ZZX* ZZX_right_shift(struct ZZX* x, long n);
+EXTERN char* ZZX_content(struct ZZX* x);
+EXTERN struct ZZX* ZZX_primitive_part(struct ZZX* x);
+EXTERN void ZZX_pseudo_quo_rem(struct ZZX* x, struct ZZX* y, struct ZZX** r, struct ZZX** q);
+EXTERN struct ZZX* ZZX_gcd(struct ZZX* x, struct ZZX* y);
+EXTERN void ZZX_xgcd(struct ZZX* x, struct ZZX* y, struct ZZ** r, struct ZZX** s, struct ZZX** t, int proof);
+EXTERN long ZZX_degree(struct ZZX* x);
+EXTERN struct ZZ* ZZX_leading_coefficient(struct ZZX* x);
+EXTERN char* ZZX_constant_term(struct ZZX* x);
+EXTERN void ZZX_set_x(struct ZZX* x);
+EXTERN int ZZX_is_x(struct ZZX* x);
+EXTERN struct ZZX* ZZX_derivative(struct ZZX* x);
+EXTERN struct ZZX* ZZX_reverse(struct ZZX* x);
+EXTERN struct ZZX* ZZX_reverse_hi(struct ZZX* x, int hi);
+EXTERN struct ZZX* ZZX_truncate(struct ZZX* x, long m);
+EXTERN struct ZZX* ZZX_multiply_and_truncate(struct ZZX* x, struct ZZX* y, long m);
+EXTERN struct ZZX* ZZX_square_and_truncate(struct ZZX* x, long m);
+EXTERN struct ZZX* ZZX_invert_and_truncate(struct ZZX* x, long m);
+EXTERN struct ZZX* ZZX_multiply_mod(struct ZZX* x, struct ZZX* y,  struct ZZX* modulus);
+EXTERN struct ZZ* ZZX_trace_mod(struct ZZX* x, struct ZZX* y);
+/* EXTERN struct ZZ* ZZX_polyeval(struct ZZX* f, struct ZZ* a); */
+EXTERN char* ZZX_trace_list(struct ZZX* x);
+EXTERN struct ZZ* ZZX_resultant(struct ZZX* x, struct ZZX* y, int proof);
+EXTERN struct ZZ* ZZX_norm_mod(struct ZZX* x, struct ZZX* y, int proof);
+EXTERN struct ZZ* ZZX_discriminant(struct ZZX* x, int proof);
+EXTERN struct ZZX* ZZX_charpoly_mod(struct ZZX* x, struct ZZX* y, int proof);
+EXTERN struct ZZX* ZZX_minpoly_mod(struct ZZX* x, struct ZZX* y);
+EXTERN void ZZX_clear(struct ZZX* x);
+EXTERN void ZZX_preallocate_space(struct ZZX* x, long n);
+
+//////// ZZXFactoring //////////
+
+// OUTPUT: v -- pointer to list of n ZZX elements (the squarefree factors)
+//         e -- point to list of e longs (the exponents)
+//         n -- length of above two lists
+//  The lists v and e are mallocd, and must be freed by the calling code.
+EXTERN void ZZX_squarefree_decomposition(struct ZZX*** v, long** e, long* n, struct ZZX* x);
+
+
+//////// ZZ_pX //////////
+#ifndef __cplusplus
+struct ZZ_pX;
+#endif
+
+EXTERN struct ZZ_pX* ZZ_pX_init();
+EXTERN char* ZZ_pX_repr(struct ZZ_pX* x);
+EXTERN struct ZZ_pX* ZZ_pX_copy(struct ZZ_pX* x);
+EXTERN void ZZ_pX_setitem_from_int(struct ZZ_pX* x, long i, int value);
+EXTERN int ZZ_pX_getitem_as_int(struct ZZ_pX* x, long i);
+EXTERN struct ZZ_pX* ZZ_pX_div(struct ZZ_pX* x, struct ZZ_pX* y, int* divisible);
+EXTERN struct ZZ_pX* ZZ_pX_mod(struct ZZ_pX* x, struct ZZ_pX* y);
+EXTERN void ZZ_pX_quo_rem(struct ZZ_pX* x, struct ZZ_pX* other, struct ZZ_pX** r, struct ZZ_pX** q);
+EXTERN struct ZZ_pX* ZZ_pX_square(struct ZZ_pX* x);
+EXTERN int ZZ_pX_equal(struct ZZ_pX* x, struct ZZ_pX* y);
+EXTERN int ZZ_pX_is_monic(struct ZZ_pX* x);
+EXTERN struct ZZ_pX* ZZ_pX_neg(struct ZZ_pX* x);
+EXTERN struct ZZ_pX* ZZ_pX_left_shift(struct ZZ_pX* x, long n);
+EXTERN struct ZZ_pX* ZZ_pX_right_shift(struct ZZ_pX* x, long n);
+EXTERN void ZZ_pX_quo_rem(struct ZZ_pX* x, struct ZZ_pX* y, struct ZZ_pX** r, struct ZZ_pX** q);
+EXTERN struct ZZ_pX* ZZ_pX_gcd(struct ZZ_pX* x, struct ZZ_pX* y);
+EXTERN void ZZ_pX_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b);
+EXTERN void ZZ_pX_plain_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b);
+EXTERN long ZZ_pX_degree(struct ZZ_pX* x);
+EXTERN void ZZ_pX_set_x(struct ZZ_pX* x);
+EXTERN int ZZ_pX_is_x(struct ZZ_pX* x);
+EXTERN struct ZZ_pX* ZZ_pX_derivative(struct ZZ_pX* x);
+EXTERN struct ZZ_pX* ZZ_pX_reverse(struct ZZ_pX* x);
+EXTERN struct ZZ_pX* ZZ_pX_reverse_hi(struct ZZ_pX* x, int hi);
+EXTERN struct ZZ_pX* ZZ_pX_truncate(struct ZZ_pX* x, long m);
+EXTERN struct ZZ_pX* ZZ_pX_multiply_and_truncate(struct ZZ_pX* x, struct ZZ_pX* y, long m);
+EXTERN struct ZZ_pX* ZZ_pX_square_and_truncate(struct ZZ_pX* x, long m);
+EXTERN struct ZZ_pX* ZZ_pX_invert_and_truncate(struct ZZ_pX* x, long m);
+EXTERN struct ZZ_pX* ZZ_pX_multiply_mod(struct ZZ_pX* x, struct ZZ_pX* y,  struct ZZ_pX* modulus);
+EXTERN struct ZZ_p* ZZ_pX_trace_mod(struct ZZ_pX* x, struct ZZ_pX* y);
+EXTERN char* ZZ_pX_trace_list(struct ZZ_pX* x);
+EXTERN struct ZZ_p* ZZ_pX_resultant(struct ZZ_pX* x, struct ZZ_pX* y);
+EXTERN struct ZZ_p* ZZ_pX_norm_mod(struct ZZ_pX* x, struct ZZ_pX* y);
+EXTERN struct ZZ_pX* ZZ_pX_charpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y);
+EXTERN struct ZZ_pX* ZZ_pX_minpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y);
+EXTERN void ZZ_pX_clear(struct ZZ_pX* x);
+EXTERN void ZZ_pX_preallocate_space(struct ZZ_pX* x, long n);
+
+// Factoring elements of ZZ_pX:
+// OUTPUT: v -- pointer to list of n ZZ_pX elements (the irred factors)
+//         e -- point to list of e longs (the exponents)
+//         n -- length of above two lists
+//  The lists v and e are mallocd, and must be freed by the calling code.
+EXTERN void ZZ_pX_factor(struct ZZ_pX*** v, long** e, long* n, struct ZZ_pX* x, long verbose);
+EXTERN void ZZ_pX_linear_roots(struct ZZ_p*** v, long* n, struct ZZ_pX* f);
+
+//////// zz_p //////////
+
+#ifndef __cplusplus
+struct zz_p;
+#endif
+
+#define zz_p_set_from_long( obj1, obj2 )\
+        (obj1) = (obj2)
+#define NTL_zz_p_DOUBLE_EQUALS( obj1, obj2 )\
+        (obj1) == (obj2)
+
+EXTERN struct zz_pContext* zz_pContext_new(long p);
+EXTERN struct zz_pContext* zz_pContext_construct(void* mem, long p);
+EXTERN void zz_pContext_restore(struct zz_pContext* ctx);
+
+//////// zz_pX //////////
+
+#ifndef __cplusplus
+struct zz_pX; 
+#endif 
+
+#define NTL_zz_pX_DOUBLE_EQUALS( obj1, obj2 )\
+        (obj1) == (obj2)
+
+//////// ZZ_pEContext ///////////////
+
+#ifndef __cplusplus
+struct ZZ_pEContext;
+#endif
+
+EXTERN struct ZZ_pEContext* ZZ_pEContext_new(struct ZZ_pX *f);
+EXTERN struct ZZ_pEContext* ZZ_pEContext_construct(void* mem, struct ZZ_pX *f);
+EXTERN void ZZ_pEContext_restore(struct ZZ_pEContext* ctx);
+
+//////// ZZ_pE ////////////
+
+#ifndef __cplusplus
+struct ZZ_pE;
+#endif
+
+EXTERN struct ZZ_pX ZZ_pE_to_ZZ_pX(struct ZZ_pE x);
+
+//////// ZZ_pEX /////////
+
+#ifndef __cplusplus
+struct ZZ_pEX;
+#endif
+
+//////// mat_ZZ //////////
+
+#ifndef __cplusplus
+struct mat_ZZ;
+#endif
+
+EXTERN void mat_ZZ_SetDims(struct mat_ZZ* mZZ, long nrows, long ncols);
+EXTERN struct mat_ZZ* mat_ZZ_pow(const struct mat_ZZ* x, long e);
+EXTERN long mat_ZZ_nrows(const struct mat_ZZ* x);
+EXTERN long mat_ZZ_ncols(const struct mat_ZZ* x);
+EXTERN void mat_ZZ_setitem(struct mat_ZZ* x, int i, int j, const struct ZZ* z);
+EXTERN struct ZZ* mat_ZZ_getitem(const struct mat_ZZ* x, int i, int j);
+EXTERN struct ZZ* mat_ZZ_determinant(const struct mat_ZZ* x, long deterministic);
+EXTERN struct mat_ZZ* mat_ZZ_HNF(const struct mat_ZZ* A, const struct ZZ* D);
+EXTERN struct ZZX* mat_ZZ_charpoly(const struct mat_ZZ* A);
+EXTERN long mat_ZZ_LLL(struct ZZ **det, struct mat_ZZ *x, long a, long b, long verbose);
+EXTERN long mat_ZZ_LLL_U(struct ZZ **det, struct mat_ZZ *x, struct mat_ZZ *U, long a, long b, long verbose);
+
+/* //////// ZZ_p ////////// */
+/* #ifndef __cplusplus */
+/* struct ZZ_p; */
+/* #endif */
+
+/* EXTERN void ZZ_p_set_modulus(const struct ZZ* p); */
+/* EXTERN struct ZZ_p* new_ZZ_p(void); */
+/* EXTERN void del_ZZ_p(struct ZZ_p* x); */
+/* EXTERN struct ZZ_p* ZZ_p_add(const struct ZZ_p* x, const struct ZZ_p* y); */
+/* EXTERN struct ZZ_p* ZZ_p_sub(const struct ZZ_p* x, const struct ZZ_p* y); */
+/* EXTERN struct ZZ_p* ZZ_p_mul(const struct ZZ_p* x, const struct ZZ_p* y); */
+/* EXTERN struct ZZ_p* ZZ_p_pow(const struct ZZ_p* x, long e); */
+/* EXTERN int ZZ_p_is_zero(struct ZZ_p*x ); */
+/* EXTERN int ZZ_p_is_one(struct ZZ_p*x ); */
+
+
+//////// ZZ_pE //////////
+#ifndef __cplusplus
+struct ZZ_pE;
+#endif
+
+// EXTERN struct ZZ_pE* new_ZZ_pE
+
+
+
+//////// ZZ_pEX //////////
+
+//#ifndef __cplusplus
+//struct ZZ_pEX;
+//#endif
+
+//EXTERN struct ZZ_pEX* new_ZZ_pEX
+
+/////// GF2X ////////////////
+#ifndef __cplusplus
+struct GF2X;
+#endif
+
+EXTERN struct GF2X* GF2X_pow(const struct GF2X* x, long e);
+EXTERN struct GF2X* GF2X_neg(struct GF2X* x);
+EXTERN long GF2X_deg(struct GF2X* x);
+EXTERN void GF2X_hex(long h);
+EXTERN PyObject* GF2X_to_bin(const struct GF2X* x);
+EXTERN PyObject* GF2X_to_hex(const struct GF2X* x);
+
+
+/////// GF2E ////////////////
+
+#ifndef __cplusplus
+struct GF2E;
+#endif
+
+EXTERN struct GF2E* GF2E_pow(const struct GF2E* x, long e);
+EXTERN struct GF2E* GF2E_neg(struct GF2E* x);
+EXTERN void ntl_GF2E_set_modulus(struct GF2X* x);
+EXTERN long GF2E_degree();
+EXTERN const struct GF2X *GF2E_modulus();
+EXTERN struct GF2E *GF2E_random(void);
+EXTERN long GF2E_trace(struct GF2E *x);
+EXTERN const struct GF2X *GF2E_ntl_GF2X(struct GF2E *x);
+
+//////// mat_GF2E //////////
+
+#ifndef __cplusplus
+struct mat_GF2E;
+#endif
+
+EXTERN void mat_GF2E_SetDims(struct mat_GF2E* mGF2E, long nrows, long ncols);
+EXTERN struct mat_GF2E* mat_GF2E_pow(const struct mat_GF2E* x, long e);
+EXTERN long mat_GF2E_nrows(const struct mat_GF2E* x);
+EXTERN long mat_GF2E_ncols(const struct mat_GF2E* x);
+EXTERN void mat_GF2E_setitem(struct mat_GF2E* x, int i, int j, const struct GF2E* z);
+EXTERN struct GF2E* mat_GF2E_getitem(const struct mat_GF2E* x, int i, int j);
+EXTERN struct GF2E* mat_GF2E_determinant(const struct mat_GF2E* x);
+EXTERN long mat_GF2E_gauss(struct mat_GF2E *x, long w);
+EXTERN struct mat_GF2E* mat_GF2E_transpose(const struct mat_GF2E* x);
+
+
+
+//EXTERN struct mat_GF2E* mat_GF2E_HNF(const struct mat_GF2E* A, const struct GF2E* D);
+//EXTERN struct GF2EX* mat_GF2E_charpoly(const struct mat_GF2E* A);
Index: c_lib/include/stdsage.h
===================================================================
--- c_lib/include/stdsage.h	(revision 6689)
+++ c_lib/include/stdsage.h	(revision 6689)
@@ -0,0 +1,193 @@
+/******************************************************************************
+       Copyright (C) 2006 William Stein <wstein@gmail.com>
+                     2006 Martin Albrecht <malb@informatik.uni-bremen.de>
+
+  Distributed under the terms of the GNU General Public License (GPL), Version 2.
+
+  The full text of the GPL is available at:
+                  http://www.gnu.org/licenses/
+
+******************************************************************************/
+
+/**
+ * @file stdsage.h
+ *
+ * @author William Stein <wstein@gmail.com>
+ * @auhtor Martin Albrecht <malb@informatik.uni-bremen.de>
+ *
+ * @brief General C (.h) code this is useful to include in any pyrex module.
+ *
+ * Put 
+ @verbatim
+ 
+  include 'relative/path/to/stdsage.pxi' 
+
+ @endverbatim
+ *
+ * at the top of your Pyrex file. 
+ *
+ * These are mostly things that can't be done in Pyrex.
+ */
+
+#ifndef STDSAGE_H
+#define STDSAGE_H
+
+#include "Python.h"
+
+/* Building with this not commented out causes
+   serious problems on RHEL5 64-bit for Kiran Kedlaya... i.e., it doesn't work. */
+/* #include "ccobject.h" */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************
+          For PARI 
+          Memory management
+
+ *****************************************/
+
+#define set_gel(x, n, z)  gel(x,n)=z;
+
+/******************************************
+ Some macros exported for Pyrex in cdefs.pxi
+ ****************************************/
+
+/** Tests whether zzz_obj is of type zzz_type. The zzz_type must be a
+ * built-in or extension type. This is just a C++-compatible wrapper
+ * for PyObject_TypeCheck. 
+ */
+#define PY_TYPE_CHECK(zzz_obj, zzz_type) \
+    (PyObject_TypeCheck((PyObject*)(zzz_obj), (PyTypeObject*)(zzz_type)))
+
+/** Tests whether zzz_obj is exactly of type zzz_type. The zzz_type must be a
+  * built-in or extension type.  
+  */
+#define PY_TYPE_CHECK_EXACT(zzz_obj, zzz_type) \
+  ((PyTypeObject*)PY_TYPE(zzz_obj) == (PyTypeObject*)(zzz_type))
+  
+/** Returns the type field of a python object, cast to void*. The
+ *  returned value should only be used as an opaque object e.g. for
+ *  type comparisons. 
+ */
+#define PY_TYPE(zzz_obj) ((void*)((zzz_obj)->ob_type))
+
+/** Constructs a new object of type zzz_type by calling tp_new
+ *  directly, with no arguments. 
+ */
+
+#define PY_NEW(zzz_type) \
+    (((PyTypeObject*)(zzz_type))->tp_new((PyTypeObject*)(zzz_type), global_empty_tuple, NULL)) 
+
+  
+  /** Constructs a new object of type the same type as zzz_obj by calling tp_new
+   *  directly, with no arguments. 
+   */
+  
+#define PY_NEW_SAME_TYPE(zzz_obj) \
+  PY_NEW(PY_TYPE(zzz_obj)) 
+  
+/** Resets the tp_new slot of zzz_type1 to point to the tp_new slot of
+ *  zzz_type2. This is used in SAGE to speed up Pyrex's boilerplate
+ *  object construction code by skipping irrelevant base class tp_new
+ *  methods. 
+ */
+#define PY_SET_TP_NEW(zzz_type1, zzz_type2) \
+    (((PyTypeObject*)zzz_type1)->tp_new = ((PyTypeObject*)zzz_type2)->tp_new)
+
+
+/**
+ * Tests whether the given object has a python dictionary. 
+ */
+#define HAS_DICTIONARY(zzz_obj) \
+    (((PyObject*)(zzz_obj))->ob_type->tp_dictoffset != NULL)
+
+/** 
+ * Very very unsafe access to the list of pointers to PyObject*'s
+ * underlying a list / sequence.  This does error checking of any kind
+ * -- make damn sure you hand it a list or sequence!
+ */
+#define FAST_SEQ_UNSAFE(zzz_obj) \
+    PySequence_Fast_ITEMS(PySequence_Fast(zzz_obj, "expected sequence type"))
+
+/** Returns the type field of a python object, cast to void*. The
+ *  returned value should only be used as an opaque object e.g. for
+ *  type comparisons.
+ */
+#define PY_IS_NUMERIC(zzz_obj) \
+     (PyInt_Check(zzz_obj) ||  PyBool_Check(zzz_obj) || PyLong_Check(zzz_obj) || \
+       PyFloat_Check(zzz_obj) || PyComplex_Check(zzz_obj))
+
+
+/** This is exactly the same as isinstance (and does return a Python
+ *  bool), but the second argument must be a C-extension type -- so it
+ *  can't be a Python class or a list.  If you just want an int return
+ *  value, i.e., aren't going to pass this back to Python, just use
+ *  PY_TYPE_CHECK. 
+ */
+#define IS_INSTANCE(zzz_obj, zzz_type) \
+    PyBool_FromLong(PY_TYPE_CHECK(zzz_obj, zzz_type))
+
+
+/** 
+ * A global empty python tuple object. This is used to speed up some
+ * python API calls where we want to avoid constructing a tuple every
+ * time. 
+ */
+
+extern PyObject* global_empty_tuple;
+
+
+
+/*****************************************
+          Memory management
+
+NOTE -- before changing these away from Python's keep the following in
+mind (from the Python C/API guide):
+
+"In most situations, however, it is recommended to allocate memory from
+the Python heap specifically because the latter is under control of
+the Python memory manager. For example, this is required when the
+interpreter is extended with new object types written in C. Another
+reason for using the Python heap is the desire to inform the Python
+memory manager about the memory needs of the extension module. Even
+when the requested memory is used exclusively for internal,
+highly-specific purposes, delegating all memory requests to the Python
+memory manager causes the interpreter to have a more accurate image of
+its memory footprint as a whole. Consequently, under certain
+circumstances, the Python memory manager may or may not trigger
+appropriate actions, like garbage collection, memory compaction or
+other preventive procedures. Note that by using the C library
+allocator as shown in the previous example, the allocated memory for
+the I/O buffer escapes completely the Python memory manager."
+
+ *****************************************/
+
+#define sage_malloc  malloc
+#define sage_free    free
+#define sage_realloc realloc
+
+/**
+ * Initialisation of singal handlers, global variables, etc. Called
+ * exactly once at SAGE start-up. 
+ *
+ * @note: It is safe to call this function more than once but nothing
+ * will happen after the first call.
+ */
+void init_csage(void);
+
+
+
+/**
+ * a handy macro to be placed at the top of a function definition
+ * below the variable declarations to ensure a function is called once
+ * at maximum.
+ */
+#define _CALLED_ONLY_ONCE static int ncalls = 0; if (ncalls>0) return; else ncalls++
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: _lib/interrupt.c
===================================================================
--- c_lib/interrupt.c	(revision 6011)
+++ 	(revision )
@@ -1,142 +1,0 @@
-/******************************************************************************
-       Copyright (C) 2006 William Stein <wstein@gmail.com>
-                     2006 Martin Albrecht <malb@informatik.uni-bremen.de>
-
-  Distributed under the terms of the GNU General Public License (GPL), Version 2.
-
-  The full text of the GPL is available at:
-                  http://www.gnu.org/licenses/
-
-******************************************************************************/
-
-#include "stdsage.h"
-#include "interrupt.h"
-#include <stdio.h>
-
-struct sage_signals _signals;
-
-void msg(char* s);
-
-void sage_signal_handler(int sig) {
-
-  char *s = _signals.s;
-  _signals.s = NULL;
-
-  //we override the default handler
-  if ( _signals.mpio && 1 ) {
-
-    //what to do?
-
-    switch(sig) {
-
-    case SIGINT:
-      if( s ) {
-	PyErr_SetString(PyExc_KeyboardInterrupt, s);
-      } else {
-	PyErr_SetString(PyExc_KeyboardInterrupt, "");
-      }
-      break;
-
-    case SIGALRM:
-      if( s ) {
-	PyErr_SetString(PyExc_KeyboardInterrupt, s);
-      } else {
-	PyErr_SetString(PyExc_KeyboardInterrupt, "Alarm received");
-      }
-      break;
-
-    default:
-      if( s ) {
-	PyErr_SetString(PyExc_RuntimeError, s);
-      } else {
-	PyErr_SetString(PyExc_RuntimeError, "");
-      }
-    }
-
-
-    //notify 'calling' function
-
-    _signals.mpio |= 4;
-
-    //where to go next?
-    if ( _signals.mpio && 2 ) {
-      siglongjmp(_signals.env, sig);
-    } else {
-      //this case shouldn't happen as _sig_[on|off]_short is disabled
-      return;
-    }
-    
-  } else {
-
-    //we use the default handler
-    _signals.mpio = 0;
-
-    switch(sig) {
-    case SIGSEGV: 
-      sig_handle_sigsegv(sig);
-      break;
-    case SIGBUS: 
-      sig_handle_sigbus(sig);
-      break;
-    case SIGFPE: 
-      sig_handle_sigfpe(sig);
-      break;
-    default:
-      _signals.python_handler(sig);
-      break;
-    };
-  }
-}
-
-void setup_signal_handler(void) {
-  void *tmp = NULL;
-
-  //we need to make sure not to store our own signal handler as the old one
-  //because that would cause infinite recursion if an error occurs and we are
-  //not supposed to catch it.
-  tmp = signal(SIGINT, sage_signal_handler);
-
-  if(sage_signal_handler != tmp) {
-    _signals.python_handler = tmp;
-  }
-  
-  _signals.s = NULL;
-
-/*  signal(SIGBUS, sig_handle_sigbus); */
-  signal(SIGBUS, sage_signal_handler);
-
-  signal(SIGALRM,sage_signal_handler);
-  signal(SIGSEGV,sage_signal_handler);
-  signal(SIGABRT,sage_signal_handler);
-  signal(SIGFPE,sage_signal_handler);
-}
-
-
-void msg(char* s) {
-  fprintf(stderr, "\n\n------------------------------------------------------------\n");
-  fprintf(stderr, s);
-  fprintf(stderr, "This probably occured because a *compiled* component\n");
-  fprintf(stderr, "of SAGE has a bug in it (typically accessing invalid memory)\n");
-  fprintf(stderr, "or is not properly wrapped with _sig_on, _sig_off.\n");
-  fprintf(stderr, "You might want to run SAGE under gdb with 'sage -gdb' to debug this.\n");
-  fprintf(stderr, "SAGE will now terminate (sorry).\n");
-  fprintf(stderr, "------------------------------------------------------------\n\n");
-}
-
-void sig_handle_sigsegv(int n) {
-  msg("Unhandled SIGSEGV: A segmentation fault occured in SAGE.\n");
-  PyErr_SetString(PyExc_KeyboardInterrupt, "");
-  exit(1);
-}
-
-void sig_handle_sigbus(int n) {
-  msg("Unhandled SIGBUS: A bus error occured in SAGE.\n");
-  PyErr_SetString(PyExc_KeyboardInterrupt, "");
-  exit(1);
-}
-
-void sig_handle_sigfpe(int n) {
-  msg("Unhandled SIGFPE: An unhandled floating point exception occured in SAGE.\n");
-  PyErr_SetString(PyExc_KeyboardInterrupt, "");
-  exit(1);
-}
Index: _lib/interrupt.h
===================================================================
--- c_lib/interrupt.h	(revision 6011)
+++ 	(revision )
@@ -1,240 +1,0 @@
-/******************************************************************************
-       Copyright (C) 2006 William Stein <wstein@gmail.com>
-                     2006 Martin Albrecht <malb@informatik.uni-bremen.de>
-
-  Distributed under the terms of the GNU General Public License (GPL), Version 2.
-
-  The full text of the GPL is available at:
-                  http://www.gnu.org/licenses/
-
-******************************************************************************/
-
-#ifndef FOO_H
-#define FOO_H
-#include <setjmp.h>
-#include <Python.h>
-#include <signal.h>
-
-
-
-/* In your Pyrex code, put 
-
-    _sig_on
-    [pure c code block]
-    _sig_off
-
-   to get signal handling capabilities. 
-
-   VERY VERY IMPORTANT:  
-       1. These *must* always come in pairs. E.g., if you have just 
-          a _sig_off without a corresponding _sig_on, then ctrl-c
-          later in the interpreter will sigfault!
-
-       2. Do *not* put these in the __init__ method of a Pyrex extension
-          class, or you'll get crashes. 
-
-       3. Do not put these around any non-pure C code!!!!
-
-       4. If you need to do a check of control-c inside a loop, e.g.,
-          when constructing a matrix, put _sig_check instead of using
-          _sig_on then _sig_off.
-*/
-
-/**
- * bitmask to enable the sage signal handler
- */
-
-#define SIG_SAGE_HANDLER 1
-
-/**
- * bitmask to enable long jumps
- */
-#define SIG_LONG_JMP 2
-
-/**
- * bitmask that a signal has been received.
- *
- */
-
-#define SIG_SIGNAL_RECEIVED 4
-
-/**
- * default signal handler for SIGINT, SIGALRM, SIGSEGV, SIGABRT,
- * SIGFPE in the context of SAGE. It calls the default Python handler
- * if _signals.sage_handler == 0.
- */
-
-void sage_signal_handler(int n);
-
-
-/**
- * fallback signal handlers
- */
-void sig_handle_sigsegv(int n);
-void sig_handle_sigbus(int n);
-void sig_handle_sigfpe(int n);
-
-/**
- * Supposed to be called exactly once to ensure the SAGE signal
- * handler is the default signal handler. This function implements a
- * mechanism to make sure it is only called once so it is safe to call
- * it more than once.
- *
- */
-
-void setup_signal_handler(void);
-
-#if defined (__sun__) || defined (__sun)   /* Needed for Solaris below. */
-   typedef void (*__sighandler_t )();
-#endif
-
-/**
- * All relevant data for the signal handler is bundled in this struct.
- *
- */
-
-struct sage_signals {
-
-  /**
-   * Bitmask which determines what to do in the signal handler. Let
-   * bit 0 be the least significant bit, then the bitmask is as follows:
-   \verbatim
-     bit | semantic
-     -------------------------------------------
-       0 | use sage signal handler (1) or default (0)
-       1 | use longjmp (1) or return (0)
-       2 | signal received (1) or not (0)
-   \endverbatim
-   * 
-   * You may want to use the provided definitions SIG_SAGE_HANDLER,
-   * SIG_LONG_JMP, SIG_SIGNAL_RECEIVED.
-   */
-
-  int mpio;
-
-  /**
-   * An internal buffer holding where to jump after a signal has been
-   * received, don't touch!
-   */
-
-  sigjmp_buf env;
-
-
-  /**
-   * An optional string may be passed to the signal handler which will
-   * be printed. Use _sig_str for that.
-   */
-  char *s;
-  
-
-  /** 
-   * Unfortunately signal handler function declarations vary HUGELY
-   * from platform to platform:
-   */
-
-#if defined(__CYGWIN32__)     /* Windows XP */
-
-  _sig_func_ptr  python_handler;
-
-#elif defined(__FreeBSD__)    /* FreeBSD */
-
-  sig_t  python_handler;
-
-#elif defined(__APPLE__)      /* OSX */
-
-  sig_t  python_handler;
-
-#elif defined (__sun__) || defined (__sun)   /* Solaris */
-
-  __sighandler_t  python_handler;
-
-#else                                   /* Other, e.g., Linux */
-
-  __sighandler_t python_handler;
-
-#endif
-
-};
-
-/**
- * The actual object.
- */
-
-extern struct sage_signals _signals;
-
-/**
- * Enables SAGE signal handling for the following C block. This macro
- * *MUST* be followed by _sig_off.
- *
- *
- * See also @ref _sig_str
- */
-
-#define _sig_on  _signals.mpio = 1+2; _signals.s = NULL;\
-                if (sigsetjmp(_signals.env,1)) { \
-                  return(0); \
-                }
-
-/* /\** */
-/*  * Enables SAGE signal handling for the following C block. This macro */
-/*  * *MUST* be followed by _sig_off_short. */
-/*  * */
-/*  * If the following block takes very little time to compute this macro */
-/*  * is the right choice. Otherwise _sig_on is appropriate. */
-/*  * */
-/*  * See also _sig_on and _sig_str. */
-/*  * */
-/*  *\/ */
-
-/* #define _sig_on_short _signals.mpio = 1 */
-
-
-/**
- * Same as @ref _sig_on but with string support
- *
- */
- 
-#define _sig_str(mstring) _signals.mpio = 1+2; \
-                _signals.s = mstring; \
-                if (sigsetjmp(_signals.env,1)) { \
-                 return(0); \
-                }
-
-
-/**
- *
- *
- */
-
-#define _sig_off _signals.mpio = 0;
-
-
-/* /\** */
-/*  * */
-/*  * */
-/*  *\/ */
-
-/* #define _sig_off_short (_signals.mpio & 4) */
-
-
-/**
- *
- *
- */
-
-#define _sig_check _sig_on _sig_off
-
-#endif /* FOO_H */
-
-/*
-I thought maybe the following would work nicely, instead of just
-returning, but no (it crashes sometimes!).  Also the line number is
-not set correctly.  The only way I can imagine setting this correctly
-is if the following bit of code is generated within pyrex, since pyrex
-knows the line numbers.
-
-	             PyErr_SetString(PyExc_RuntimeError, "(complete C-level traceback not available)"); \
-		     __pyx_filename = __pyx_f[1]; __pyx_lineno = 0; goto __pyx_L1; \
-                }
-
-*/
Index: _lib/ltmain.sh
===================================================================
--- c_lib/ltmain.sh	(revision 6004)
+++ 	(revision )
@@ -1,6871 +1,0 @@
-# ltmain.sh - Provide generalized library-building support services.
-# NOTE: Changing this file will not affect anything until you rerun configure.
-#
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
-# Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-basename="s,^.*/,,g"
-
-# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
-# is ksh but when the shell is invoked as "sh" and the current value of
-# the _XPG environment variable is not equal to 1 (one), the special
-# positional parameter $0, within a function call, is the name of the
-# function.
-progpath="$0"
-
-# The name of this program:
-progname=`echo "$progpath" | $SED $basename`
-modename="$progname"
-
-# Global variables:
-EXIT_SUCCESS=0
-EXIT_FAILURE=1
-
-PROGRAM=ltmain.sh
-PACKAGE=libtool
-VERSION="1.5.22 Debian 1.5.22-4"
-TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
-
-# See if we are running on zsh, and set the options which allow our
-# commands through without removal of \ escapes.
-if test -n "${ZSH_VERSION+set}" ; then
-  setopt NO_GLOB_SUBST
-fi
-
-# Check that we have a working $echo.
-if test "X$1" = X--no-reexec; then
-  # Discard the --no-reexec flag, and continue.
-  shift
-elif test "X$1" = X--fallback-echo; then
-  # Avoid inline document here, it may be left over
-  :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
-  # Yippee, $echo works!
-  :
-else
-  # Restart under the correct shell, and then maybe $echo will work.
-  exec $SHELL "$progpath" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
-  # used as fallback echo
-  shift
-  cat <<EOF
-$*
-EOF
-  exit $EXIT_SUCCESS
-fi
-
-default_mode=
-help="Try \`$progname --help' for more information."
-magic="%%%MAGIC variable%%%"
-mkdir="mkdir"
-mv="mv -f"
-rm="rm -f"
-
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed="${SED}"' -e 1s/^X//'
-sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
-# test EBCDIC or ASCII
-case `echo X|tr X '\101'` in
- A) # ASCII based system
-    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
-  SP2NL='tr \040 \012'
-  NL2SP='tr \015\012 \040\040'
-  ;;
- *) # EBCDIC based system
-  SP2NL='tr \100 \n'
-  NL2SP='tr \r\n \100\100'
-  ;;
-esac
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-# We save the old values to restore during execute mode.
-if test "${LC_ALL+set}" = set; then
-  save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
-fi
-if test "${LANG+set}" = set; then
-  save_LANG="$LANG"; LANG=C; export LANG
-fi
-
-# Make sure IFS has a sensible default
-lt_nl='
-'
-IFS=" 	$lt_nl"
-
-if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
-  $echo "$modename: not configured to build any kind of library" 1>&2
-  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-  exit $EXIT_FAILURE
-fi
-
-# Global variables.
-mode=$default_mode
-nonopt=
-prev=
-prevopt=
-run=
-show="$echo"
-show_help=
-execute_dlfiles=
-duplicate_deps=no
-preserve_args=
-lo2o="s/\\.lo\$/.${objext}/"
-o2lo="s/\\.${objext}\$/.lo/"
-
-#####################################
-# Shell function definitions:
-# This seems to be the best place for them
-
-# func_mktempdir [string]
-# Make a temporary directory that won't clash with other running
-# libtool processes, and avoids race conditions if possible.  If
-# given, STRING is the basename for that directory.
-func_mktempdir ()
-{
-    my_template="${TMPDIR-/tmp}/${1-$progname}"
-
-    if test "$run" = ":"; then
-      # Return a directory name, but don't create it in dry-run mode
-      my_tmpdir="${my_template}-$$"
-    else
-
-      # If mktemp works, use that first and foremost
-      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
-
-      if test ! -d "$my_tmpdir"; then
-	# Failing that, at least try and use $RANDOM to avoid a race
-	my_tmpdir="${my_template}-${RANDOM-0}$$"
-
-	save_mktempdir_umask=`umask`
-	umask 0077
-	$mkdir "$my_tmpdir"
-	umask $save_mktempdir_umask
-      fi
-
-      # If we're not in dry-run mode, bomb out on failure
-      test -d "$my_tmpdir" || {
-        $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
-	exit $EXIT_FAILURE
-      }
-    fi
-
-    $echo "X$my_tmpdir" | $Xsed
-}
-
-
-# func_win32_libid arg
-# return the library type of file 'arg'
-#
-# Need a lot of goo to handle *both* DLLs and import libs
-# Has to be a shell function in order to 'eat' the argument
-# that is supplied when $file_magic_command is called.
-func_win32_libid ()
-{
-  win32_libid_type="unknown"
-  win32_fileres=`file -L $1 2>/dev/null`
-  case $win32_fileres in
-  *ar\ archive\ import\ library*) # definitely import
-    win32_libid_type="x86 archive import"
-    ;;
-  *ar\ archive*) # could be an import, or static
-    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
-      $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
-      win32_nmres=`eval $NM -f posix -A $1 | \
-	$SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'`
-      case $win32_nmres in
-      import*)  win32_libid_type="x86 archive import";;
-      *)        win32_libid_type="x86 archive static";;
-      esac
-    fi
-    ;;
-  *DLL*)
-    win32_libid_type="x86 DLL"
-    ;;
-  *executable*) # but shell scripts are "executable" too...
-    case $win32_fileres in
-    *MS\ Windows\ PE\ Intel*)
-      win32_libid_type="x86 DLL"
-      ;;
-    esac
-    ;;
-  esac
-  $echo $win32_libid_type
-}
-
-
-# func_infer_tag arg
-# Infer tagged configuration to use if any are available and
-# if one wasn't chosen via the "--tag" command line option.
-# Only attempt this if the compiler in the base compile
-# command doesn't match the default compiler.
-# arg is usually of the form 'gcc ...'
-func_infer_tag ()
-{
-    if test -n "$available_tags" && test -z "$tagname"; then
-      CC_quoted=
-      for arg in $CC; do
-	case $arg in
-	  *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	  arg="\"$arg\""
-	  ;;
-	esac
-	CC_quoted="$CC_quoted $arg"
-      done
-      case $@ in
-      # Blanks in the command may have been stripped by the calling shell,
-      # but not from the CC environment variable when configure was run.
-      " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
-      # Blanks at the start of $base_compile will cause this to fail
-      # if we don't check for them as well.
-      *)
-	for z in $available_tags; do
-	  if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
-	    # Evaluate the configuration.
-	    eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
-	    CC_quoted=
-	    for arg in $CC; do
-	    # Double-quote args containing other shell metacharacters.
-	    case $arg in
-	      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	      arg="\"$arg\""
-	      ;;
-	    esac
-	    CC_quoted="$CC_quoted $arg"
-	  done
-	    case "$@ " in
-	      " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
-	      # The compiler in the base compile command matches
-	      # the one in the tagged configuration.
-	      # Assume this is the tagged configuration we want.
-	      tagname=$z
-	      break
-	      ;;
-	    esac
-	  fi
-	done
-	# If $tagname still isn't set, then no tagged configuration
-	# was found and let the user know that the "--tag" command
-	# line option must be used.
-	if test -z "$tagname"; then
-	  $echo "$modename: unable to infer tagged configuration"
-	  $echo "$modename: specify a tag with \`--tag'" 1>&2
-	  exit $EXIT_FAILURE
-#        else
-#          $echo "$modename: using $tagname tagged configuration"
-	fi
-	;;
-      esac
-    fi
-}
-
-
-# func_extract_an_archive dir oldlib
-func_extract_an_archive ()
-{
-    f_ex_an_ar_dir="$1"; shift
-    f_ex_an_ar_oldlib="$1"
-
-    $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
-    $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
-    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
-     :
-    else
-      $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
-      exit $EXIT_FAILURE
-    fi
-}
-
-# func_extract_archives gentop oldlib ...
-func_extract_archives ()
-{
-    my_gentop="$1"; shift
-    my_oldlibs=${1+"$@"}
-    my_oldobjs=""
-    my_xlib=""
-    my_xabs=""
-    my_xdir=""
-    my_status=""
-
-    $show "${rm}r $my_gentop"
-    $run ${rm}r "$my_gentop"
-    $show "$mkdir $my_gentop"
-    $run $mkdir "$my_gentop"
-    my_status=$?
-    if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
-      exit $my_status
-    fi
-
-    for my_xlib in $my_oldlibs; do
-      # Extract the objects.
-      case $my_xlib in
-	[\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
-	*) my_xabs=`pwd`"/$my_xlib" ;;
-      esac
-      my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
-      my_xdir="$my_gentop/$my_xlib"
-
-      $show "${rm}r $my_xdir"
-      $run ${rm}r "$my_xdir"
-      $show "$mkdir $my_xdir"
-      $run $mkdir "$my_xdir"
-      exit_status=$?
-      if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
-	exit $exit_status
-      fi
-      case $host in
-      *-darwin*)
-	$show "Extracting $my_xabs"
-	# Do not bother doing anything if just a dry run
-	if test -z "$run"; then
-	  darwin_orig_dir=`pwd`
-	  cd $my_xdir || exit $?
-	  darwin_archive=$my_xabs
-	  darwin_curdir=`pwd`
-	  darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
-	  darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
-	  if test -n "$darwin_arches"; then 
-	    darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
-	    darwin_arch=
-	    $show "$darwin_base_archive has multiple architectures $darwin_arches"
-	    for darwin_arch in  $darwin_arches ; do
-	      mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
-	      lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
-	      cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
-	      func_extract_an_archive "`pwd`" "${darwin_base_archive}"
-	      cd "$darwin_curdir"
-	      $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
-	    done # $darwin_arches
-      ## Okay now we have a bunch of thin objects, gotta fatten them up :)
-	    darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
-	    darwin_file=
-	    darwin_files=
-	    for darwin_file in $darwin_filelist; do
-	      darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
-	      lipo -create -output "$darwin_file" $darwin_files
-	    done # $darwin_filelist
-	    ${rm}r unfat-$$
-	    cd "$darwin_orig_dir"
-	  else
-	    cd "$darwin_orig_dir"
- 	    func_extract_an_archive "$my_xdir" "$my_xabs"
-	  fi # $darwin_arches
-	fi # $run
-	;;
-      *)
-        func_extract_an_archive "$my_xdir" "$my_xabs"
-        ;;
-      esac
-      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
-    done
-    func_extract_archives_result="$my_oldobjs"
-}
-# End of Shell function definitions
-#####################################
-
-# Darwin sucks
-eval std_shrext=\"$shrext_cmds\"
-
-disable_libs=no
-
-# Parse our command line options once, thoroughly.
-while test "$#" -gt 0
-do
-  arg="$1"
-  shift
-
-  case $arg in
-  -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
-  *) optarg= ;;
-  esac
-
-  # If the previous option needs an argument, assign it.
-  if test -n "$prev"; then
-    case $prev in
-    execute_dlfiles)
-      execute_dlfiles="$execute_dlfiles $arg"
-      ;;
-    tag)
-      tagname="$arg"
-      preserve_args="${preserve_args}=$arg"
-
-      # Check whether tagname contains only valid characters
-      case $tagname in
-      *[!-_A-Za-z0-9,/]*)
-	$echo "$progname: invalid tag name: $tagname" 1>&2
-	exit $EXIT_FAILURE
-	;;
-      esac
-
-      case $tagname in
-      CC)
-	# Don't test for the "default" C tag, as we know, it's there, but
-	# not specially marked.
-	;;
-      *)
-	if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
-	  taglist="$taglist $tagname"
-	  # Evaluate the configuration.
-	  eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
-	else
-	  $echo "$progname: ignoring unknown tag $tagname" 1>&2
-	fi
-	;;
-      esac
-      ;;
-    *)
-      eval "$prev=\$arg"
-      ;;
-    esac
-
-    prev=
-    prevopt=
-    continue
-  fi
-
-  # Have we seen a non-optional argument yet?
-  case $arg in
-  --help)
-    show_help=yes
-    ;;
-
-  --version)
-    $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
-    $echo
-    $echo "Copyright (C) 2005  Free Software Foundation, Inc."
-    $echo "This is free software; see the source for copying conditions.  There is NO"
-    $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-    exit $?
-    ;;
-
-  --config)
-    ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
-    # Now print the configurations for the tags.
-    for tagname in $taglist; do
-      ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
-    done
-    exit $?
-    ;;
-
-  --debug)
-    $echo "$progname: enabling shell trace mode"
-    set -x
-    preserve_args="$preserve_args $arg"
-    ;;
-
-  --dry-run | -n)
-    run=:
-    ;;
-
-  --features)
-    $echo "host: $host"
-    if test "$build_libtool_libs" = yes; then
-      $echo "enable shared libraries"
-    else
-      $echo "disable shared libraries"
-    fi
-    if test "$build_old_libs" = yes; then
-      $echo "enable static libraries"
-    else
-      $echo "disable static libraries"
-    fi
-    exit $?
-    ;;
-
-  --finish) mode="finish" ;;
-
-  --mode) prevopt="--mode" prev=mode ;;
-  --mode=*) mode="$optarg" ;;
-
-  --preserve-dup-deps) duplicate_deps="yes" ;;
-
-  --quiet | --silent)
-    show=:
-    preserve_args="$preserve_args $arg"
-    ;;
-
-  --tag)
-    prevopt="--tag"
-    prev=tag
-    preserve_args="$preserve_args --tag"
-    ;;
-  --tag=*)
-    set tag "$optarg" ${1+"$@"}
-    shift
-    prev=tag
-    preserve_args="$preserve_args --tag"
-    ;;
-
-  -dlopen)
-    prevopt="-dlopen"
-    prev=execute_dlfiles
-    ;;
-
-  -*)
-    $echo "$modename: unrecognized option \`$arg'" 1>&2
-    $echo "$help" 1>&2
-    exit $EXIT_FAILURE
-    ;;
-
-  *)
-    nonopt="$arg"
-    break
-    ;;
-  esac
-done
-
-if test -n "$prevopt"; then
-  $echo "$modename: option \`$prevopt' requires an argument" 1>&2
-  $echo "$help" 1>&2
-  exit $EXIT_FAILURE
-fi
-
-case $disable_libs in
-no) 
-  ;;
-shared)
-  build_libtool_libs=no
-  build_old_libs=yes
-  ;;
-static)
-  build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
-  ;;
-esac
-
-# If this variable is set in any of the actions, the command in it
-# will be execed at the end.  This prevents here-documents from being
-# left over by shells.
-exec_cmd=
-
-if test -z "$show_help"; then
-
-  # Infer the operation mode.
-  if test -z "$mode"; then
-    $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
-    $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
-    case $nonopt in
-    *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
-      mode=link
-      for arg
-      do
-	case $arg in
-	-c)
-	   mode=compile
-	   break
-	   ;;
-	esac
-      done
-      ;;
-    *db | *dbx | *strace | *truss)
-      mode=execute
-      ;;
-    *install*|cp|mv)
-      mode=install
-      ;;
-    *rm)
-      mode=uninstall
-      ;;
-    *)
-      # If we have no mode, but dlfiles were specified, then do execute mode.
-      test -n "$execute_dlfiles" && mode=execute
-
-      # Just use the default operation mode.
-      if test -z "$mode"; then
-	if test -n "$nonopt"; then
-	  $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
-	else
-	  $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
-	fi
-      fi
-      ;;
-    esac
-  fi
-
-  # Only execute mode is allowed to have -dlopen flags.
-  if test -n "$execute_dlfiles" && test "$mode" != execute; then
-    $echo "$modename: unrecognized option \`-dlopen'" 1>&2
-    $echo "$help" 1>&2
-    exit $EXIT_FAILURE
-  fi
-
-  # Change the help message to a mode-specific one.
-  generic_help="$help"
-  help="Try \`$modename --help --mode=$mode' for more information."
-
-  # These modes are in order of execution frequency so that they run quickly.
-  case $mode in
-  # libtool compile mode
-  compile)
-    modename="$modename: compile"
-    # Get the compilation command and the source file.
-    base_compile=
-    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
-    suppress_opt=yes
-    suppress_output=
-    arg_mode=normal
-    libobj=
-    later=
-
-    for arg
-    do
-      case $arg_mode in
-      arg  )
-	# do not "continue".  Instead, add this to base_compile
-	lastarg="$arg"
-	arg_mode=normal
-	;;
-
-      target )
-	libobj="$arg"
-	arg_mode=normal
-	continue
-	;;
-
-      normal )
-	# Accept any command-line options.
-	case $arg in
-	-o)
-	  if test -n "$libobj" ; then
-	    $echo "$modename: you cannot specify \`-o' more than once" 1>&2
-	    exit $EXIT_FAILURE
-	  fi
-	  arg_mode=target
-	  continue
-	  ;;
-
-	-static | -prefer-pic | -prefer-non-pic)
-	  later="$later $arg"
-	  continue
-	  ;;
-
-	-no-suppress)
-	  suppress_opt=no
-	  continue
-	  ;;
-
-	-Xcompiler)
-	  arg_mode=arg  #  the next one goes into the "base_compile" arg list
-	  continue      #  The current "srcfile" will either be retained or
-	  ;;            #  replaced later.  I would guess that would be a bug.
-
-	-Wc,*)
-	  args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
-	  lastarg=
-	  save_ifs="$IFS"; IFS=','
- 	  for arg in $args; do
-	    IFS="$save_ifs"
-
-	    # Double-quote args containing other shell metacharacters.
-	    # Many Bourne shells cannot handle close brackets correctly
-	    # in scan sets, so we specify it separately.
-	    case $arg in
-	      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	      arg="\"$arg\""
-	      ;;
-	    esac
-	    lastarg="$lastarg $arg"
-	  done
-	  IFS="$save_ifs"
-	  lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
-
-	  # Add the arguments to base_compile.
-	  base_compile="$base_compile $lastarg"
-	  continue
-	  ;;
-
-	* )
-	  # Accept the current argument as the source file.
-	  # The previous "srcfile" becomes the current argument.
-	  #
-	  lastarg="$srcfile"
-	  srcfile="$arg"
-	  ;;
-	esac  #  case $arg
-	;;
-      esac    #  case $arg_mode
-
-      # Aesthetically quote the previous argument.
-      lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
-
-      case $lastarg in
-      # Double-quote args containing other shell metacharacters.
-      # Many Bourne shells cannot handle close brackets correctly
-      # in scan sets, and some SunOS ksh mistreat backslash-escaping
-      # in scan sets (worked around with variable expansion),
-      # and furthermore cannot handle '|' '&' '(' ')' in scan sets 
-      # at all, so we specify them separately.
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	lastarg="\"$lastarg\""
-	;;
-      esac
-
-      base_compile="$base_compile $lastarg"
-    done # for arg
-
-    case $arg_mode in
-    arg)
-      $echo "$modename: you must specify an argument for -Xcompile"
-      exit $EXIT_FAILURE
-      ;;
-    target)
-      $echo "$modename: you must specify a target with \`-o'" 1>&2
-      exit $EXIT_FAILURE
-      ;;
-    *)
-      # Get the name of the library object.
-      [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
-      ;;
-    esac
-
-    # Recognize several different file suffixes.
-    # If the user specifies -o file.o, it is replaced with file.lo
-    xform='[cCFSifmso]'
-    case $libobj in
-    *.ada) xform=ada ;;
-    *.adb) xform=adb ;;
-    *.ads) xform=ads ;;
-    *.asm) xform=asm ;;
-    *.c++) xform=c++ ;;
-    *.cc) xform=cc ;;
-    *.ii) xform=ii ;;
-    *.class) xform=class ;;
-    *.cpp) xform=cpp ;;
-    *.cxx) xform=cxx ;;
-    *.f90) xform=f90 ;;
-    *.for) xform=for ;;
-    *.java) xform=java ;;
-    esac
-
-    libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
-
-    case $libobj in
-    *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
-    *)
-      $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
-      exit $EXIT_FAILURE
-      ;;
-    esac
-
-    func_infer_tag $base_compile
-
-    for arg in $later; do
-      case $arg in
-      -static)
-	build_old_libs=yes
-	continue
-	;;
-
-      -prefer-pic)
-	pic_mode=yes
-	continue
-	;;
-
-      -prefer-non-pic)
-	pic_mode=no
-	continue
-	;;
-      esac
-    done
-
-    qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
-    case $qlibobj in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	qlibobj="\"$qlibobj\"" ;;
-    esac
-    test "X$libobj" != "X$qlibobj" \
-	&& $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' 	&()|`$[]' \
-	&& $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
-    objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
-    xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
-    if test "X$xdir" = "X$obj"; then
-      xdir=
-    else
-      xdir=$xdir/
-    fi
-    lobj=${xdir}$objdir/$objname
-
-    if test -z "$base_compile"; then
-      $echo "$modename: you must specify a compilation command" 1>&2
-      $echo "$help" 1>&2
-      exit $EXIT_FAILURE
-    fi
-
-    # Delete any leftover library objects.
-    if test "$build_old_libs" = yes; then
-      removelist="$obj $lobj $libobj ${libobj}T"
-    else
-      removelist="$lobj $libobj ${libobj}T"
-    fi
-
-    $run $rm $removelist
-    trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
-
-    # On Cygwin there's no "real" PIC flag so we must build both object types
-    case $host_os in
-    cygwin* | mingw* | pw32* | os2*)
-      pic_mode=default
-      ;;
-    esac
-    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
-      # non-PIC code in shared libraries is not supported
-      pic_mode=default
-    fi
-
-    # Calculate the filename of the output object if compiler does
-    # not support -o with -c
-    if test "$compiler_c_o" = no; then
-      output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
-      lockfile="$output_obj.lock"
-      removelist="$removelist $output_obj $lockfile"
-      trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
-    else
-      output_obj=
-      need_locks=no
-      lockfile=
-    fi
-
-    # Lock this critical section if it is needed
-    # We use this script file to make the link, it avoids creating a new file
-    if test "$need_locks" = yes; then
-      until $run ln "$progpath" "$lockfile" 2>/dev/null; do
-	$show "Waiting for $lockfile to be removed"
-	sleep 2
-      done
-    elif test "$need_locks" = warn; then
-      if test -f "$lockfile"; then
-	$echo "\
-*** ERROR, $lockfile exists and contains:
-`cat $lockfile 2>/dev/null`
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together.  If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
-	$run $rm $removelist
-	exit $EXIT_FAILURE
-      fi
-      $echo "$srcfile" > "$lockfile"
-    fi
-
-    if test -n "$fix_srcfile_path"; then
-      eval srcfile=\"$fix_srcfile_path\"
-    fi
-    qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
-    case $qsrcfile in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-      qsrcfile="\"$qsrcfile\"" ;;
-    esac
-
-    $run $rm "$libobj" "${libobj}T"
-
-    # Create a libtool object file (analogous to a ".la" file),
-    # but don't create it if we're doing a dry run.
-    test -z "$run" && cat > ${libobj}T <<EOF
-# $libobj - a libtool object file
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# Name of the PIC object.
-EOF
-
-    # Only build a PIC object if we are building libtool libraries.
-    if test "$build_libtool_libs" = yes; then
-      # Without this assignment, base_compile gets emptied.
-      fbsd_hideous_sh_bug=$base_compile
-
-      if test "$pic_mode" != no; then
-	command="$base_compile $qsrcfile $pic_flag"
-      else
-	# Don't build PIC code
-	command="$base_compile $qsrcfile"
-      fi
-
-      if test ! -d "${xdir}$objdir"; then
-	$show "$mkdir ${xdir}$objdir"
-	$run $mkdir ${xdir}$objdir
-	exit_status=$?
-	if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
-	  exit $exit_status
-	fi
-      fi
-
-      if test -z "$output_obj"; then
-	# Place PIC objects in $objdir
-	command="$command -o $lobj"
-      fi
-
-      $run $rm "$lobj" "$output_obj"
-
-      $show "$command"
-      if $run eval "$command"; then :
-      else
-	test -n "$output_obj" && $run $rm $removelist
-	exit $EXIT_FAILURE
-      fi
-
-      if test "$need_locks" = warn &&
-	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
-	$echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together.  If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
-	$run $rm $removelist
-	exit $EXIT_FAILURE
-      fi
-
-      # Just move the object if needed, then go on to compile the next one
-      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
-	$show "$mv $output_obj $lobj"
-	if $run $mv $output_obj $lobj; then :
-	else
-	  error=$?
-	  $run $rm $removelist
-	  exit $error
-	fi
-      fi
-
-      # Append the name of the PIC object to the libtool object file.
-      test -z "$run" && cat >> ${libobj}T <<EOF
-pic_object='$objdir/$objname'
-
-EOF
-
-      # Allow error messages only from the first compilation.
-      if test "$suppress_opt" = yes; then
-        suppress_output=' >/dev/null 2>&1'
-      fi
-    else
-      # No PIC object so indicate it doesn't exist in the libtool
-      # object file.
-      test -z "$run" && cat >> ${libobj}T <<EOF
-pic_object=none
-
-EOF
-    fi
-
-    # Only build a position-dependent object if we build old libraries.
-    if test "$build_old_libs" = yes; then
-      if test "$pic_mode" != yes; then
-	# Don't build PIC code
-	command="$base_compile $qsrcfile"
-      else
-	command="$base_compile $qsrcfile $pic_flag"
-      fi
-      if test "$compiler_c_o" = yes; then
-	command="$command -o $obj"
-      fi
-
-      # Suppress compiler output if we already did a PIC compilation.
-      command="$command$suppress_output"
-      $run $rm "$obj" "$output_obj"
-      $show "$command"
-      if $run eval "$command"; then :
-      else
-	$run $rm $removelist
-	exit $EXIT_FAILURE
-      fi
-
-      if test "$need_locks" = warn &&
-	 test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
-	$echo "\
-*** ERROR, $lockfile contains:
-`cat $lockfile 2>/dev/null`
-
-but it should contain:
-$srcfile
-
-This indicates that another process is trying to use the same
-temporary object file, and libtool could not work around it because
-your compiler does not support \`-c' and \`-o' together.  If you
-repeat this compilation, it may succeed, by chance, but you had better
-avoid parallel builds (make -j) in this platform, or get a better
-compiler."
-
-	$run $rm $removelist
-	exit $EXIT_FAILURE
-      fi
-
-      # Just move the object if needed
-      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
-	$show "$mv $output_obj $obj"
-	if $run $mv $output_obj $obj; then :
-	else
-	  error=$?
-	  $run $rm $removelist
-	  exit $error
-	fi
-      fi
-
-      # Append the name of the non-PIC object the libtool object file.
-      # Only append if the libtool object file exists.
-      test -z "$run" && cat >> ${libobj}T <<EOF
-# Name of the non-PIC object.
-non_pic_object='$objname'
-
-EOF
-    else
-      # Append the name of the non-PIC object the libtool object file.
-      # Only append if the libtool object file exists.
-      test -z "$run" && cat >> ${libobj}T <<EOF
-# Name of the non-PIC object.
-non_pic_object=none
-
-EOF
-    fi
-
-    $run $mv "${libobj}T" "${libobj}"
-
-    # Unlock the critical section if it was locked
-    if test "$need_locks" != no; then
-      $run $rm "$lockfile"
-    fi
-
-    exit $EXIT_SUCCESS
-    ;;
-
-  # libtool link mode
-  link | relink)
-    modename="$modename: link"
-    case $host in
-    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
-      # It is impossible to link a dll without this setting, and
-      # we shouldn't force the makefile maintainer to figure out
-      # which system we are compiling for in order to pass an extra
-      # flag for every libtool invocation.
-      # allow_undefined=no
-
-      # FIXME: Unfortunately, there are problems with the above when trying
-      # to make a dll which has undefined symbols, in which case not
-      # even a static library is built.  For now, we need to specify
-      # -no-undefined on the libtool link line when we can be certain
-      # that all symbols are satisfied, otherwise we get a static library.
-      allow_undefined=yes
-      ;;
-    *)
-      allow_undefined=yes
-      ;;
-    esac
-    libtool_args="$nonopt"
-    base_compile="$nonopt $@"
-    compile_command="$nonopt"
-    finalize_command="$nonopt"
-
-    compile_rpath=
-    finalize_rpath=
-    compile_shlibpath=
-    finalize_shlibpath=
-    convenience=
-    old_convenience=
-    deplibs=
-    old_deplibs=
-    compiler_flags=
-    linker_flags=
-    dllsearchpath=
-    lib_search_path=`pwd`
-    inst_prefix_dir=
-
-    avoid_version=no
-    dlfiles=
-    dlprefiles=
-    dlself=no
-    export_dynamic=no
-    export_symbols=
-    export_symbols_regex=
-    generated=
-    libobjs=
-    ltlibs=
-    module=no
-    no_install=no
-    objs=
-    non_pic_objects=
-    notinst_path= # paths that contain not-installed libtool libraries
-    precious_files_regex=
-    prefer_static_libs=no
-    preload=no
-    prev=
-    prevarg=
-    release=
-    rpath=
-    xrpath=
-    perm_rpath=
-    temp_rpath=
-    thread_safe=no
-    vinfo=
-    vinfo_number=no
-
-    func_infer_tag $base_compile
-
-    # We need to know -static, to get the right output filenames.
-    for arg
-    do
-      case $arg in
-      -all-static | -static)
-	if test "X$arg" = "X-all-static"; then
-	  if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
-	    $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
-	  fi
-	  if test -n "$link_static_flag"; then
-	    dlopen_self=$dlopen_self_static
-	  fi
-	  prefer_static_libs=yes
-	else
-	  if test -z "$pic_flag" && test -n "$link_static_flag"; then
-	    dlopen_self=$dlopen_self_static
-	  fi
-	  prefer_static_libs=built
-	fi
-	build_libtool_libs=no
-	build_old_libs=yes
-	break
-	;;
-      esac
-    done
-
-    # See if our shared archives depend on static archives.
-    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
-
-    # Go through the arguments, transforming them on the way.
-    while test "$#" -gt 0; do
-      arg="$1"
-      shift
-      case $arg in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
-	;;
-      *) qarg=$arg ;;
-      esac
-      libtool_args="$libtool_args $qarg"
-
-      # If the previous option needs an argument, assign it.
-      if test -n "$prev"; then
-	case $prev in
-	output)
-	  compile_command="$compile_command @OUTPUT@"
-	  finalize_command="$finalize_command @OUTPUT@"
-	  ;;
-	esac
-
-	case $prev in
-	dlfiles|dlprefiles)
-	  if test "$preload" = no; then
-	    # Add the symbol object into the linking commands.
-	    compile_command="$compile_command @SYMFILE@"
-	    finalize_command="$finalize_command @SYMFILE@"
-	    preload=yes
-	  fi
-	  case $arg in
-	  *.la | *.lo) ;;  # We handle these cases below.
-	  force)
-	    if test "$dlself" = no; then
-	      dlself=needless
-	      export_dynamic=yes
-	    fi
-	    prev=
-	    continue
-	    ;;
-	  self)
-	    if test "$prev" = dlprefiles; then
-	      dlself=yes
-	    elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
-	      dlself=yes
-	    else
-	      dlself=needless
-	      export_dynamic=yes
-	    fi
-	    prev=
-	    continue
-	    ;;
-	  *)
-	    if test "$prev" = dlfiles; then
-	      dlfiles="$dlfiles $arg"
-	    else
-	      dlprefiles="$dlprefiles $arg"
-	    fi
-	    prev=
-	    continue
-	    ;;
-	  esac
-	  ;;
-	expsyms)
-	  export_symbols="$arg"
-	  if test ! -f "$arg"; then
-	    $echo "$modename: symbol file \`$arg' does not exist"
-	    exit $EXIT_FAILURE
-	  fi
-	  prev=
-	  continue
-	  ;;
-	expsyms_regex)
-	  export_symbols_regex="$arg"
-	  prev=
-	  continue
-	  ;;
-	inst_prefix)
-	  inst_prefix_dir="$arg"
-	  prev=
-	  continue
-	  ;;
-	precious_regex)
-	  precious_files_regex="$arg"
-	  prev=
-	  continue
-	  ;;
-	release)
-	  release="-$arg"
-	  prev=
-	  continue
-	  ;;
-	objectlist)
-	  if test -f "$arg"; then
-	    save_arg=$arg
-	    moreargs=
-	    for fil in `cat $save_arg`
-	    do
-#	      moreargs="$moreargs $fil"
-	      arg=$fil
-	      # A libtool-controlled object.
-
-	      # Check to see that this really is a libtool object.
-	      if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-		pic_object=
-		non_pic_object=
-
-		# Read the .lo file
-		# If there is no directory component, then add one.
-		case $arg in
-		*/* | *\\*) . $arg ;;
-		*) . ./$arg ;;
-		esac
-
-		if test -z "$pic_object" || \
-		   test -z "$non_pic_object" ||
-		   test "$pic_object" = none && \
-		   test "$non_pic_object" = none; then
-		  $echo "$modename: cannot find name of object for \`$arg'" 1>&2
-		  exit $EXIT_FAILURE
-		fi
-
-		# Extract subdirectory from the argument.
-		xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
-		if test "X$xdir" = "X$arg"; then
-		  xdir=
-		else
-		  xdir="$xdir/"
-		fi
-
-		if test "$pic_object" != none; then
-		  # Prepend the subdirectory the object is found in.
-		  pic_object="$xdir$pic_object"
-
-		  if test "$prev" = dlfiles; then
-		    if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
-		      dlfiles="$dlfiles $pic_object"
-		      prev=
-		      continue
-		    else
-		      # If libtool objects are unsupported, then we need to preload.
-		      prev=dlprefiles
-		    fi
-		  fi
-
-		  # CHECK ME:  I think I busted this.  -Ossama
-		  if test "$prev" = dlprefiles; then
-		    # Preload the old-style object.
-		    dlprefiles="$dlprefiles $pic_object"
-		    prev=
-		  fi
-
-		  # A PIC object.
-		  libobjs="$libobjs $pic_object"
-		  arg="$pic_object"
-		fi
-
-		# Non-PIC object.
-		if test "$non_pic_object" != none; then
-		  # Prepend the subdirectory the object is found in.
-		  non_pic_object="$xdir$non_pic_object"
-
-		  # A standard non-PIC object
-		  non_pic_objects="$non_pic_objects $non_pic_object"
-		  if test -z "$pic_object" || test "$pic_object" = none ; then
-		    arg="$non_pic_object"
-		  fi
-		else
-		  # If the PIC object exists, use it instead.
-		  # $xdir was prepended to $pic_object above.
-		  non_pic_object="$pic_object"
-		  non_pic_objects="$non_pic_objects $non_pic_object"
-		fi
-	      else
-		# Only an error if not doing a dry-run.
-		if test -z "$run"; then
-		  $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
-		  exit $EXIT_FAILURE
-		else
-		  # Dry-run case.
-
-		  # Extract subdirectory from the argument.
-		  xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
-		  if test "X$xdir" = "X$arg"; then
-		    xdir=
-		  else
-		    xdir="$xdir/"
-		  fi
-
-		  pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
-		  non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
-		  libobjs="$libobjs $pic_object"
-		  non_pic_objects="$non_pic_objects $non_pic_object"
-		fi
-	      fi
-	    done
-	  else
-	    $echo "$modename: link input file \`$save_arg' does not exist"
-	    exit $EXIT_FAILURE
-	  fi
-	  arg=$save_arg
-	  prev=
-	  continue
-	  ;;
-	rpath | xrpath)
-	  # We need an absolute path.
-	  case $arg in
-	  [\\/]* | [A-Za-z]:[\\/]*) ;;
-	  *)
-	    $echo "$modename: only absolute run-paths are allowed" 1>&2
-	    exit $EXIT_FAILURE
-	    ;;
-	  esac
-	  if test "$prev" = rpath; then
-	    case "$rpath " in
-	    *" $arg "*) ;;
-	    *) rpath="$rpath $arg" ;;
-	    esac
-	  else
-	    case "$xrpath " in
-	    *" $arg "*) ;;
-	    *) xrpath="$xrpath $arg" ;;
-	    esac
-	  fi
-	  prev=
-	  continue
-	  ;;
-	xcompiler)
-	  compiler_flags="$compiler_flags $qarg"
-	  prev=
-	  compile_command="$compile_command $qarg"
-	  finalize_command="$finalize_command $qarg"
-	  continue
-	  ;;
-	xlinker)
-	  linker_flags="$linker_flags $qarg"
-	  compiler_flags="$compiler_flags $wl$qarg"
-	  prev=
-	  compile_command="$compile_command $wl$qarg"
-	  finalize_command="$finalize_command $wl$qarg"
-	  continue
-	  ;;
-	xcclinker)
-	  linker_flags="$linker_flags $qarg"
-	  compiler_flags="$compiler_flags $qarg"
-	  prev=
-	  compile_command="$compile_command $qarg"
-	  finalize_command="$finalize_command $qarg"
-	  continue
-	  ;;
-	shrext)
-  	  shrext_cmds="$arg"
-	  prev=
-	  continue
-	  ;;
-	darwin_framework|darwin_framework_skip)
-	  test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
-	  compile_command="$compile_command $arg"
-	  finalize_command="$finalize_command $arg"
-	  prev=
-	  continue
-	  ;;
-	*)
-	  eval "$prev=\"\$arg\""
-	  prev=
-	  continue
-	  ;;
-	esac
-      fi # test -n "$prev"
-
-      prevarg="$arg"
-
-      case $arg in
-      -all-static)
-	if test -n "$link_static_flag"; then
-	  compile_command="$compile_command $link_static_flag"
-	  finalize_command="$finalize_command $link_static_flag"
-	fi
-	continue
-	;;
-
-      -allow-undefined)
-	# FIXME: remove this flag sometime in the future.
-	$echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
-	continue
-	;;
-
-      -avoid-version)
-	avoid_version=yes
-	continue
-	;;
-
-      -dlopen)
-	prev=dlfiles
-	continue
-	;;
-
-      -dlpreopen)
-	prev=dlprefiles
-	continue
-	;;
-
-      -export-dynamic)
-	export_dynamic=yes
-	continue
-	;;
-
-      -export-symbols | -export-symbols-regex)
-	if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
-	  $echo "$modename: more than one -exported-symbols argument is not allowed"
-	  exit $EXIT_FAILURE
-	fi
-	if test "X$arg" = "X-export-symbols"; then
-	  prev=expsyms
-	else
-	  prev=expsyms_regex
-	fi
-	continue
-	;;
-
-      -framework|-arch|-isysroot)
-	case " $CC " in
-	  *" ${arg} ${1} "* | *" ${arg}	${1} "*) 
-		prev=darwin_framework_skip ;;
-	  *) compiler_flags="$compiler_flags $arg"
-	     prev=darwin_framework ;;
-	esac
-	compile_command="$compile_command $arg"
-	finalize_command="$finalize_command $arg"
-	continue
-	;;
-
-      -inst-prefix-dir)
-	prev=inst_prefix
-	continue
-	;;
-
-      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
-      # so, if we see these flags be careful not to treat them like -L
-      -L[A-Z][A-Z]*:*)
-	case $with_gcc/$host in
-	no/*-*-irix* | /*-*-irix*)
-	  compile_command="$compile_command $arg"
-	  finalize_command="$finalize_command $arg"
-	  ;;
-	esac
-	continue
-	;;
-
-      -L*)
-	dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
-	# We need an absolute path.
-	case $dir in
-	[\\/]* | [A-Za-z]:[\\/]*) ;;
-	*)
-	  absdir=`cd "$dir" && pwd`
-	  if test -z "$absdir"; then
-	    $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
-	    absdir="$dir"
-	    notinst_path="$notinst_path $dir"
-	  fi
-	  dir="$absdir"
-	  ;;
-	esac
-	case "$deplibs " in
-	*" -L$dir "*) ;;
-	*)
-	  deplibs="$deplibs -L$dir"
-	  lib_search_path="$lib_search_path $dir"
-	  ;;
-	esac
-	case $host in
-	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
-	  testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
-	  case :$dllsearchpath: in
-	  *":$dir:"*) ;;
-	  *) dllsearchpath="$dllsearchpath:$dir";;
-	  esac
-	  case :$dllsearchpath: in
-	  *":$testbindir:"*) ;;
-	  *) dllsearchpath="$dllsearchpath:$testbindir";;
-	  esac
-	  ;;
-	esac
-	continue
-	;;
-
-      -l*)
-	if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
-	  case $host in
-	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
-	    # These systems don't actually have a C or math library (as such)
-	    continue
-	    ;;
-	  *-*-os2*)
-	    # These systems don't actually have a C library (as such)
-	    test "X$arg" = "X-lc" && continue
-	    ;;
-	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
-	    # Do not include libc due to us having libc/libc_r.
-	    test "X$arg" = "X-lc" && continue
-	    ;;
-	  *-*-rhapsody* | *-*-darwin1.[012])
-	    # Rhapsody C and math libraries are in the System framework
-	    deplibs="$deplibs -framework System"
-	    continue
-	    ;;
-	  *-*-sco3.2v5* | *-*-sco5v6*)
-	    # Causes problems with __ctype
-	    test "X$arg" = "X-lc" && continue
-	    ;;
-	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
-	    # Compiler inserts libc in the correct place for threads to work
-	    test "X$arg" = "X-lc" && continue
-	    ;;
-	  esac
-	elif test "X$arg" = "X-lc_r"; then
-	 case $host in
-	 *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
-	   # Do not include libc_r directly, use -pthread flag.
-	   continue
-	   ;;
-	 esac
-	fi
-	deplibs="$deplibs $arg"
-	continue
-	;;
-
-      # Tru64 UNIX uses -model [arg] to determine the layout of C++
-      # classes, name mangling, and exception handling.
-      -model)
-	compile_command="$compile_command $arg"
-	compiler_flags="$compiler_flags $arg"
-	finalize_command="$finalize_command $arg"
-	prev=xcompiler
-	continue
-	;;
-
-     -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
-	compiler_flags="$compiler_flags $arg"
-	compile_command="$compile_command $arg"
-	finalize_command="$finalize_command $arg"
-	continue
-	;;
-
-      -module)
-	module=yes
-	continue
-	;;
-
-      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
-      # -r[0-9][0-9]* specifies the processor on the SGI compiler
-      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
-      # +DA*, +DD* enable 64-bit mode on the HP compiler
-      # -q* pass through compiler args for the IBM compiler
-      # -m* pass through architecture-specific compiler args for GCC
-      # -m*, -t[45]*, -txscale* pass through architecture-specific
-      # compiler args for GCC
-      # -pg pass through profiling flag for GCC
-      # @file GCC response files
-      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \
-      -t[45]*|-txscale*|@*)
-
-	# Unknown arguments in both finalize_command and compile_command need
-	# to be aesthetically quoted because they are evaled later.
-	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-	case $arg in
-	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	  arg="\"$arg\""
-	  ;;
-	esac
-        compile_command="$compile_command $arg"
-        finalize_command="$finalize_command $arg"
-        compiler_flags="$compiler_flags $arg"
-        continue
-        ;;
-
-      -shrext)
-	prev=shrext
-	continue
-	;;
-
-      -no-fast-install)
-	fast_install=no
-	continue
-	;;
-
-      -no-install)
-	case $host in
-	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
-	  # The PATH hackery in wrapper scripts is required on Windows
-	  # in order for the loader to find any dlls it needs.
-	  $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
-	  $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
-	  fast_install=no
-	  ;;
-	*) no_install=yes ;;
-	esac
-	continue
-	;;
-
-      -no-undefined)
-	allow_undefined=no
-	continue
-	;;
-
-      -objectlist)
-	prev=objectlist
-	continue
-	;;
-
-      -o) prev=output ;;
-
-      -precious-files-regex)
-	prev=precious_regex
-	continue
-	;;
-
-      -release)
-	prev=release
-	continue
-	;;
-
-      -rpath)
-	prev=rpath
-	continue
-	;;
-
-      -R)
-	prev=xrpath
-	continue
-	;;
-
-      -R*)
-	dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
-	# We need an absolute path.
-	case $dir in
-	[\\/]* | [A-Za-z]:[\\/]*) ;;
-	*)
-	  $echo "$modename: only absolute run-paths are allowed" 1>&2
-	  exit $EXIT_FAILURE
-	  ;;
-	esac
-	case "$xrpath " in
-	*" $dir "*) ;;
-	*) xrpath="$xrpath $dir" ;;
-	esac
-	continue
-	;;
-
-      -static)
-	# The effects of -static are defined in a previous loop.
-	# We used to do the same as -all-static on platforms that
-	# didn't have a PIC flag, but the assumption that the effects
-	# would be equivalent was wrong.  It would break on at least
-	# Digital Unix and AIX.
-	continue
-	;;
-
-      -thread-safe)
-	thread_safe=yes
-	continue
-	;;
-
-      -version-info)
-	prev=vinfo
-	continue
-	;;
-      -version-number)
-	prev=vinfo
-	vinfo_number=yes
-	continue
-	;;
-
-      -Wc,*)
-	args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
-	arg=
-	save_ifs="$IFS"; IFS=','
-	for flag in $args; do
-	  IFS="$save_ifs"
-	  case $flag in
-	    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	    flag="\"$flag\""
-	    ;;
-	  esac
-	  arg="$arg $wl$flag"
-	  compiler_flags="$compiler_flags $flag"
-	done
-	IFS="$save_ifs"
-	arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
-	;;
-
-      -Wl,*)
-	args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
-	arg=
-	save_ifs="$IFS"; IFS=','
-	for flag in $args; do
-	  IFS="$save_ifs"
-	  case $flag in
-	    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	    flag="\"$flag\""
-	    ;;
-	  esac
-	  arg="$arg $wl$flag"
-	  compiler_flags="$compiler_flags $wl$flag"
-	  linker_flags="$linker_flags $flag"
-	done
-	IFS="$save_ifs"
-	arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
-	;;
-
-      -Xcompiler)
-	prev=xcompiler
-	continue
-	;;
-
-      -Xlinker)
-	prev=xlinker
-	continue
-	;;
-
-      -XCClinker)
-	prev=xcclinker
-	continue
-	;;
-
-      # Some other compiler flag.
-      -* | +*)
-	# Unknown arguments in both finalize_command and compile_command need
-	# to be aesthetically quoted because they are evaled later.
-	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-	case $arg in
-	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	  arg="\"$arg\""
-	  ;;
-	esac
-	;;
-
-      *.$objext)
-	# A standard object.
-	objs="$objs $arg"
-	;;
-
-      *.lo)
-	# A libtool-controlled object.
-
-	# Check to see that this really is a libtool object.
-	if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-	  pic_object=
-	  non_pic_object=
-
-	  # Read the .lo file
-	  # If there is no directory component, then add one.
-	  case $arg in
-	  */* | *\\*) . $arg ;;
-	  *) . ./$arg ;;
-	  esac
-
-	  if test -z "$pic_object" || \
-	     test -z "$non_pic_object" ||
-	     test "$pic_object" = none && \
-	     test "$non_pic_object" = none; then
-	    $echo "$modename: cannot find name of object for \`$arg'" 1>&2
-	    exit $EXIT_FAILURE
-	  fi
-
-	  # Extract subdirectory from the argument.
-	  xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
-	  if test "X$xdir" = "X$arg"; then
-	    xdir=
- 	  else
-	    xdir="$xdir/"
-	  fi
-
-	  if test "$pic_object" != none; then
-	    # Prepend the subdirectory the object is found in.
-	    pic_object="$xdir$pic_object"
-
-	    if test "$prev" = dlfiles; then
-	      if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
-		dlfiles="$dlfiles $pic_object"
-		prev=
-		continue
-	      else
-		# If libtool objects are unsupported, then we need to preload.
-		prev=dlprefiles
-	      fi
-	    fi
-
-	    # CHECK ME:  I think I busted this.  -Ossama
-	    if test "$prev" = dlprefiles; then
-	      # Preload the old-style object.
-	      dlprefiles="$dlprefiles $pic_object"
-	      prev=
-	    fi
-
-	    # A PIC object.
-	    libobjs="$libobjs $pic_object"
-	    arg="$pic_object"
-	  fi
-
-	  # Non-PIC object.
-	  if test "$non_pic_object" != none; then
-	    # Prepend the subdirectory the object is found in.
-	    non_pic_object="$xdir$non_pic_object"
-
-	    # A standard non-PIC object
-	    non_pic_objects="$non_pic_objects $non_pic_object"
-	    if test -z "$pic_object" || test "$pic_object" = none ; then
-	      arg="$non_pic_object"
-	    fi
-	  else
-	    # If the PIC object exists, use it instead.
-	    # $xdir was prepended to $pic_object above.
-	    non_pic_object="$pic_object"
-	    non_pic_objects="$non_pic_objects $non_pic_object"
-	  fi
-	else
-	  # Only an error if not doing a dry-run.
-	  if test -z "$run"; then
-	    $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
-	    exit $EXIT_FAILURE
-	  else
-	    # Dry-run case.
-
-	    # Extract subdirectory from the argument.
-	    xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
-	    if test "X$xdir" = "X$arg"; then
-	      xdir=
-	    else
-	      xdir="$xdir/"
-	    fi
-
-	    pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
-	    non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
-	    libobjs="$libobjs $pic_object"
-	    non_pic_objects="$non_pic_objects $non_pic_object"
-	  fi
-	fi
-	;;
-
-      *.$libext)
-	# An archive.
-	deplibs="$deplibs $arg"
-	old_deplibs="$old_deplibs $arg"
-	continue
-	;;
-
-      *.la)
-	# A libtool-controlled library.
-
-	if test "$prev" = dlfiles; then
-	  # This library was specified with -dlopen.
-	  dlfiles="$dlfiles $arg"
-	  prev=
-	elif test "$prev" = dlprefiles; then
-	  # The library was specified with -dlpreopen.
-	  dlprefiles="$dlprefiles $arg"
-	  prev=
-	else
-	  deplibs="$deplibs $arg"
-	fi
-	continue
-	;;
-
-      # Some other compiler argument.
-      *)
-	# Unknown arguments in both finalize_command and compile_command need
-	# to be aesthetically quoted because they are evaled later.
-	arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-	case $arg in
-	*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	  arg="\"$arg\""
-	  ;;
-	esac
-	;;
-      esac # arg
-
-      # Now actually substitute the argument into the commands.
-      if test -n "$arg"; then
-	compile_command="$compile_command $arg"
-	finalize_command="$finalize_command $arg"
-      fi
-    done # argument parsing loop
-
-    if test -n "$prev"; then
-      $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
-      $echo "$help" 1>&2
-      exit $EXIT_FAILURE
-    fi
-
-    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
-      eval arg=\"$export_dynamic_flag_spec\"
-      compile_command="$compile_command $arg"
-      finalize_command="$finalize_command $arg"
-    fi
-
-    oldlibs=
-    # calculate the name of the file, without its directory
-    outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
-    libobjs_save="$libobjs"
-
-    if test -n "$shlibpath_var"; then
-      # get the directories listed in $shlibpath_var
-      eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
-    else
-      shlib_search_path=
-    fi
-    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
-    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
-
-    output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
-    if test "X$output_objdir" = "X$output"; then
-      output_objdir="$objdir"
-    else
-      output_objdir="$output_objdir/$objdir"
-    fi
-    # Create the object directory.
-    if test ! -d "$output_objdir"; then
-      $show "$mkdir $output_objdir"
-      $run $mkdir $output_objdir
-      exit_status=$?
-      if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
-	exit $exit_status
-      fi
-    fi
-
-    # Determine the type of output
-    case $output in
-    "")
-      $echo "$modename: you must specify an output file" 1>&2
-      $echo "$help" 1>&2
-      exit $EXIT_FAILURE
-      ;;
-    *.$libext) linkmode=oldlib ;;
-    *.lo | *.$objext) linkmode=obj ;;
-    *.la) linkmode=lib ;;
-    *) linkmode=prog ;; # Anything else should be a program.
-    esac
-
-    case $host in
-    *cygwin* | *mingw* | *pw32*)
-      # don't eliminate duplications in $postdeps and $predeps
-      duplicate_compiler_generated_deps=yes
-      ;;
-    *)
-      duplicate_compiler_generated_deps=$duplicate_deps
-      ;;
-    esac
-    specialdeplibs=
-
-    libs=
-    # Find all interdependent deplibs by searching for libraries
-    # that are linked more than once (e.g. -la -lb -la)
-    for deplib in $deplibs; do
-      if test "X$duplicate_deps" = "Xyes" ; then
-	case "$libs " in
-	*" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
-	esac
-      fi
-      libs="$libs $deplib"
-    done
-
-    if test "$linkmode" = lib; then
-      libs="$predeps $libs $compiler_lib_search_path $postdeps"
-
-      # Compute libraries that are listed more than once in $predeps
-      # $postdeps and mark them as special (i.e., whose duplicates are
-      # not to be eliminated).
-      pre_post_deps=
-      if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
-	for pre_post_dep in $predeps $postdeps; do
-	  case "$pre_post_deps " in
-	  *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
-	  esac
-	  pre_post_deps="$pre_post_deps $pre_post_dep"
-	done
-      fi
-      pre_post_deps=
-    fi
-
-    deplibs=
-    newdependency_libs=
-    newlib_search_path=
-    need_relink=no # whether we're linking any uninstalled libtool libraries
-    notinst_deplibs= # not-installed libtool libraries
-    case $linkmode in
-    lib)
-	passes="conv link"
-	for file in $dlfiles $dlprefiles; do
-	  case $file in
-	  *.la) ;;
-	  *)
-	    $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
-	    exit $EXIT_FAILURE
-	    ;;
-	  esac
-	done
-	;;
-    prog)
-	compile_deplibs=
-	finalize_deplibs=
-	alldeplibs=no
-	newdlfiles=
-	newdlprefiles=
-	passes="conv scan dlopen dlpreopen link"
-	;;
-    *)  passes="conv"
-	;;
-    esac
-    for pass in $passes; do
-      if test "$linkmode,$pass" = "lib,link" ||
-	 test "$linkmode,$pass" = "prog,scan"; then
-	libs="$deplibs"
-	deplibs=
-      fi
-      if test "$linkmode" = prog; then
-	case $pass in
-	dlopen) libs="$dlfiles" ;;
-	dlpreopen) libs="$dlprefiles" ;;
-	link)
-	  libs="$deplibs %DEPLIBS%"
-	  test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
-	  ;;
-	esac
-      fi
-      if test "$pass" = dlopen; then
-	# Collect dlpreopened libraries
-	save_deplibs="$deplibs"
-	deplibs=
-      fi
-      for deplib in $libs; do
-	lib=
-	found=no
-	case $deplib in
-	-mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
-	  if test "$linkmode,$pass" = "prog,link"; then
-	    compile_deplibs="$deplib $compile_deplibs"
-	    finalize_deplibs="$deplib $finalize_deplibs"
-	  else
-	    compiler_flags="$compiler_flags $deplib"
-	  fi
-	  continue
-	  ;;
-	-l*)
-	  if test "$linkmode" != lib && test "$linkmode" != prog; then
-	    $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
-	    continue
-	  fi
-	  name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
-	  for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
-	    for search_ext in .la $std_shrext .so .a; do
-	      # Search the libtool library
-	      lib="$searchdir/lib${name}${search_ext}"
-	      if test -f "$lib"; then
-		if test "$search_ext" = ".la"; then
-		  found=yes
-		else
-		  found=no
-		fi
-		break 2
-	      fi
-	    done
-	  done
-	  if test "$found" != yes; then
-	    # deplib doesn't seem to be a libtool library
-	    if test "$linkmode,$pass" = "prog,link"; then
-	      compile_deplibs="$deplib $compile_deplibs"
-	      finalize_deplibs="$deplib $finalize_deplibs"
-	    else
-	      deplibs="$deplib $deplibs"
-	      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
-	    fi
-	    continue
-	  else # deplib is a libtool library
-	    # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
-	    # We need to do some special things here, and not later.
-	    if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-	      case " $predeps $postdeps " in
-	      *" $deplib "*)
-		if (${SED} -e '2q' $lib |
-                    grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-		  library_names=
-		  old_library=
-		  case $lib in
-		  */* | *\\*) . $lib ;;
-		  *) . ./$lib ;;
-		  esac
-		  for l in $old_library $library_names; do
-		    ll="$l"
-		  done
-		  if test "X$ll" = "X$old_library" ; then # only static version available
-		    found=no
-		    ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
-		    test "X$ladir" = "X$lib" && ladir="."
-		    lib=$ladir/$old_library
-		    if test "$linkmode,$pass" = "prog,link"; then
-		      compile_deplibs="$deplib $compile_deplibs"
-		      finalize_deplibs="$deplib $finalize_deplibs"
-		    else
-		      deplibs="$deplib $deplibs"
-		      test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
-		    fi
-		    continue
-		  fi
-		fi
-	        ;;
-	      *) ;;
-	      esac
-	    fi
-	  fi
-	  ;; # -l
-	-L*)
-	  case $linkmode in
-	  lib)
-	    deplibs="$deplib $deplibs"
-	    test "$pass" = conv && continue
-	    newdependency_libs="$deplib $newdependency_libs"
-	    newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
-	    ;;
-	  prog)
-	    if test "$pass" = conv; then
-	      deplibs="$deplib $deplibs"
-	      continue
-	    fi
-	    if test "$pass" = scan; then
-	      deplibs="$deplib $deplibs"
-	    else
-	      compile_deplibs="$deplib $compile_deplibs"
-	      finalize_deplibs="$deplib $finalize_deplibs"
-	    fi
-	    newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
-	    ;;
-	  *)
-	    $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
-	    ;;
-	  esac # linkmode
-	  continue
-	  ;; # -L
-	-R*)
-	  if test "$pass" = link; then
-	    dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
-	    # Make sure the xrpath contains only unique directories.
-	    case "$xrpath " in
-	    *" $dir "*) ;;
-	    *) xrpath="$xrpath $dir" ;;
-	    esac
-	  fi
-	  deplibs="$deplib $deplibs"
-	  continue
-	  ;;
-	*.la) lib="$deplib" ;;
-	*.$libext)
-	  if test "$pass" = conv; then
-	    deplibs="$deplib $deplibs"
-	    continue
-	  fi
-	  case $linkmode in
-	  lib)
-	    valid_a_lib=no
-	    case $deplibs_check_method in
-	      match_pattern*)
-		set dummy $deplibs_check_method
-	        match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
-		if eval $echo \"$deplib\" 2>/dev/null \
-		    | $SED 10q \
-		    | $EGREP "$match_pattern_regex" > /dev/null; then
-		  valid_a_lib=yes
-		fi
-		;;
-	      pass_all)
-		valid_a_lib=yes
-		;;
-            esac
-	    if test "$valid_a_lib" != yes; then
-	      $echo
-	      $echo "*** Warning: Trying to link with static lib archive $deplib."
-	      $echo "*** I have the capability to make that library automatically link in when"
-	      $echo "*** you link to this library.  But I can only do this if you have a"
-	      $echo "*** shared version of the library, which you do not appear to have"
-	      $echo "*** because the file extensions .$libext of this argument makes me believe"
-	      $echo "*** that it is just a static archive that I should not used here."
-	    else
-	      $echo
-	      $echo "*** Warning: Linking the shared library $output against the"
-	      $echo "*** static library $deplib is not portable!"
-	      deplibs="$deplib $deplibs"
-	    fi
-	    continue
-	    ;;
-	  prog)
-	    if test "$pass" != link; then
-	      deplibs="$deplib $deplibs"
-	    else
-	      compile_deplibs="$deplib $compile_deplibs"
-	      finalize_deplibs="$deplib $finalize_deplibs"
-	    fi
-	    continue
-	    ;;
-	  esac # linkmode
-	  ;; # *.$libext
-	*.lo | *.$objext)
-	  if test "$pass" = conv; then
-	    deplibs="$deplib $deplibs"
-	  elif test "$linkmode" = prog; then
-	    if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
-	      # If there is no dlopen support or we're linking statically,
-	      # we need to preload.
-	      newdlprefiles="$newdlprefiles $deplib"
-	      compile_deplibs="$deplib $compile_deplibs"
-	      finalize_deplibs="$deplib $finalize_deplibs"
-	    else
-	      newdlfiles="$newdlfiles $deplib"
-	    fi
-	  fi
-	  continue
-	  ;;
-	%DEPLIBS%)
-	  alldeplibs=yes
-	  continue
-	  ;;
-	esac # case $deplib
-	if test "$found" = yes || test -f "$lib"; then :
-	else
-	  $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
-	  exit $EXIT_FAILURE
-	fi
-
-	# Check to see that this really is a libtool archive.
-	if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-	else
-	  $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-	  exit $EXIT_FAILURE
-	fi
-
-	ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
-	test "X$ladir" = "X$lib" && ladir="."
-
-	dlname=
-	dlopen=
-	dlpreopen=
-	libdir=
-	library_names=
-	old_library=
-	# If the library was installed with an old release of libtool,
-	# it will not redefine variables installed, or shouldnotlink
-	installed=yes
-	shouldnotlink=no
-	avoidtemprpath=
-
-
-	# Read the .la file
-	case $lib in
-	*/* | *\\*) . $lib ;;
-	*) . ./$lib ;;
-	esac
-
-	if test "$linkmode,$pass" = "lib,link" ||
-	   test "$linkmode,$pass" = "prog,scan" ||
-	   { test "$linkmode" != prog && test "$linkmode" != lib; }; then
-	  test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
-	  test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
-	fi
-
-	if test "$pass" = conv; then
-	  # Only check for convenience libraries
-	  deplibs="$lib $deplibs"
-	  if test -z "$libdir"; then
-	    if test -z "$old_library"; then
-	      $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
-	      exit $EXIT_FAILURE
-	    fi
-	    # It is a libtool convenience library, so add in its objects.
-	    convenience="$convenience $ladir/$objdir/$old_library"
-	    old_convenience="$old_convenience $ladir/$objdir/$old_library"
-	    tmp_libs=
-	    for deplib in $dependency_libs; do
-	      deplibs="$deplib $deplibs"
-              if test "X$duplicate_deps" = "Xyes" ; then
-	        case "$tmp_libs " in
-	        *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
-	        esac
-              fi
-	      tmp_libs="$tmp_libs $deplib"
-	    done
-	  elif test "$linkmode" != prog && test "$linkmode" != lib; then
-	    $echo "$modename: \`$lib' is not a convenience library" 1>&2
-	    exit $EXIT_FAILURE
-	  fi
-	  continue
-	fi # $pass = conv
-
-
-	# Get the name of the library we link against.
-	linklib=
-	for l in $old_library $library_names; do
-	  linklib="$l"
-	done
-	if test -z "$linklib"; then
-	  $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
-	  exit $EXIT_FAILURE
-	fi
-
-	# This library was specified with -dlopen.
-	if test "$pass" = dlopen; then
-	  if test -z "$libdir"; then
-	    $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
-	    exit $EXIT_FAILURE
-	  fi
-	  if test -z "$dlname" ||
-	     test "$dlopen_support" != yes ||
-	     test "$build_libtool_libs" = no; then
-	    # If there is no dlname, no dlopen support or we're linking
-	    # statically, we need to preload.  We also need to preload any
-	    # dependent libraries so libltdl's deplib preloader doesn't
-	    # bomb out in the load deplibs phase.
-	    dlprefiles="$dlprefiles $lib $dependency_libs"
-	  else
-	    newdlfiles="$newdlfiles $lib"
-	  fi
-	  continue
-	fi # $pass = dlopen
-
-	# We need an absolute path.
-	case $ladir in
-	[\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
-	*)
-	  abs_ladir=`cd "$ladir" && pwd`
-	  if test -z "$abs_ladir"; then
-	    $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
-	    $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
-	    abs_ladir="$ladir"
-	  fi
-	  ;;
-	esac
-	laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
-
-	# Find the relevant object directory and library name.
-	if test "X$installed" = Xyes; then
-	  if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
-	    $echo "$modename: warning: library \`$lib' was moved." 1>&2
-	    dir="$ladir"
-	    absdir="$abs_ladir"
-	    libdir="$abs_ladir"
-	  else
-	    dir="$libdir"
-	    absdir="$libdir"
-	  fi
-	  test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
-	else
-	  if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
-	    dir="$ladir"
-	    absdir="$abs_ladir"
-	    # Remove this search path later
-	    notinst_path="$notinst_path $abs_ladir"
-	  else
-	    dir="$ladir/$objdir"
-	    absdir="$abs_ladir/$objdir"
-	    # Remove this search path later
-	    notinst_path="$notinst_path $abs_ladir"
-	  fi
-	fi # $installed = yes
-	name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
-
-	# This library was specified with -dlpreopen.
-	if test "$pass" = dlpreopen; then
-	  if test -z "$libdir"; then
-	    $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
-	    exit $EXIT_FAILURE
-	  fi
-	  # Prefer using a static library (so that no silly _DYNAMIC symbols
-	  # are required to link).
-	  if test -n "$old_library"; then
-	    newdlprefiles="$newdlprefiles $dir/$old_library"
-	  # Otherwise, use the dlname, so that lt_dlopen finds it.
-	  elif test -n "$dlname"; then
-	    newdlprefiles="$newdlprefiles $dir/$dlname"
-	  else
-	    newdlprefiles="$newdlprefiles $dir/$linklib"
-	  fi
-	fi # $pass = dlpreopen
-
-	if test -z "$libdir"; then
-	  # Link the convenience library
-	  if test "$linkmode" = lib; then
-	    deplibs="$dir/$old_library $deplibs"
-	  elif test "$linkmode,$pass" = "prog,link"; then
-	    compile_deplibs="$dir/$old_library $compile_deplibs"
-	    finalize_deplibs="$dir/$old_library $finalize_deplibs"
-	  else
-	    deplibs="$lib $deplibs" # used for prog,scan pass
-	  fi
-	  continue
-	fi
-
-
-	if test "$linkmode" = prog && test "$pass" != link; then
-	  newlib_search_path="$newlib_search_path $ladir"
-	  deplibs="$lib $deplibs"
-
-	  linkalldeplibs=no
-	  if test "$link_all_deplibs" != no || test -z "$library_names" ||
-	     test "$build_libtool_libs" = no; then
-	    linkalldeplibs=yes
-	  fi
-
-	  tmp_libs=
-	  for deplib in $dependency_libs; do
-	    case $deplib in
-	    -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
-	    esac
-	    # Need to link against all dependency_libs?
-	    if test "$linkalldeplibs" = yes; then
-	      deplibs="$deplib $deplibs"
-	    else
-	      # Need to hardcode shared library paths
-	      # or/and link against static libraries
-	      newdependency_libs="$deplib $newdependency_libs"
-	    fi
-	    if test "X$duplicate_deps" = "Xyes" ; then
-	      case "$tmp_libs " in
-	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
-	      esac
-	    fi
-	    tmp_libs="$tmp_libs $deplib"
-	  done # for deplib
-	  continue
-	fi # $linkmode = prog...
-
-	if test "$linkmode,$pass" = "prog,link"; then
-	  if test -n "$library_names" &&
-	     { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
-	    # We need to hardcode the library path
-	    if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
-	      # Make sure the rpath contains only unique directories.
-	      case "$temp_rpath " in
-	      *" $dir "*) ;;
-	      *" $absdir "*) ;;
-	      *) temp_rpath="$temp_rpath $absdir" ;;
-	      esac
-	    fi
-
-	    # Hardcode the library path.
-	    # Skip directories that are in the system default run-time
-	    # search path.
-	    case " $sys_lib_dlsearch_path " in
-	    *" $absdir "*) ;;
-	    *)
-	      case "$compile_rpath " in
-	      *" $absdir "*) ;;
-	      *) compile_rpath="$compile_rpath $absdir"
-	      esac
-	      ;;
-	    esac
-	    case " $sys_lib_dlsearch_path " in
-	    *" $libdir "*) ;;
-	    *)
-	      case "$finalize_rpath " in
-	      *" $libdir "*) ;;
-	      *) finalize_rpath="$finalize_rpath $libdir"
-	      esac
-	      ;;
-	    esac
-	  fi # $linkmode,$pass = prog,link...
-
-	  if test "$alldeplibs" = yes &&
-	     { test "$deplibs_check_method" = pass_all ||
-	       { test "$build_libtool_libs" = yes &&
-		 test -n "$library_names"; }; }; then
-	    # We only need to search for static libraries
-	    continue
-	  fi
-	fi
-
-	link_static=no # Whether the deplib will be linked statically
-	use_static_libs=$prefer_static_libs
-	if test "$use_static_libs" = built && test "$installed" = yes ; then
-	  use_static_libs=no
-	fi
-	if test -n "$library_names" &&
-	   { test "$use_static_libs" = no || test -z "$old_library"; }; then
-	  if test "$installed" = no; then
-	    notinst_deplibs="$notinst_deplibs $lib"
-	    need_relink=yes
-	  fi
-	  # This is a shared library
-
-	  # Warn about portability, can't link against -module's on
-	  # some systems (darwin)
-	  if test "$shouldnotlink" = yes && test "$pass" = link ; then
-	    $echo
-	    if test "$linkmode" = prog; then
-	      $echo "*** Warning: Linking the executable $output against the loadable module"
-	    else
-	      $echo "*** Warning: Linking the shared library $output against the loadable module"
-	    fi
-	    $echo "*** $linklib is not portable!"
-	  fi
-	  if test "$linkmode" = lib &&
-	     test "$hardcode_into_libs" = yes; then
-	    # Hardcode the library path.
-	    # Skip directories that are in the system default run-time
-	    # search path.
-	    case " $sys_lib_dlsearch_path " in
-	    *" $absdir "*) ;;
-	    *)
-	      case "$compile_rpath " in
-	      *" $absdir "*) ;;
-	      *) compile_rpath="$compile_rpath $absdir"
-	      esac
-	      ;;
-	    esac
-	    case " $sys_lib_dlsearch_path " in
-	    *" $libdir "*) ;;
-	    *)
-	      case "$finalize_rpath " in
-	      *" $libdir "*) ;;
-	      *) finalize_rpath="$finalize_rpath $libdir"
-	      esac
-	      ;;
-	    esac
-	  fi
-
-	  if test -n "$old_archive_from_expsyms_cmds"; then
-	    # figure out the soname
-	    set dummy $library_names
-	    realname="$2"
-	    shift; shift
-	    libname=`eval \\$echo \"$libname_spec\"`
-	    # use dlname if we got it. it's perfectly good, no?
-	    if test -n "$dlname"; then
-	      soname="$dlname"
-	    elif test -n "$soname_spec"; then
-	      # bleh windows
-	      case $host in
-	      *cygwin* | mingw*)
-		major=`expr $current - $age`
-		versuffix="-$major"
-		;;
-	      esac
-	      eval soname=\"$soname_spec\"
-	    else
-	      soname="$realname"
-	    fi
-
-	    # Make a new name for the extract_expsyms_cmds to use
-	    soroot="$soname"
-	    soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
-	    newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
-
-	    # If the library has no export list, then create one now
-	    if test -f "$output_objdir/$soname-def"; then :
-	    else
-	      $show "extracting exported symbol list from \`$soname'"
-	      save_ifs="$IFS"; IFS='~'
-	      cmds=$extract_expsyms_cmds
-	      for cmd in $cmds; do
-		IFS="$save_ifs"
-		eval cmd=\"$cmd\"
-		$show "$cmd"
-		$run eval "$cmd" || exit $?
-	      done
-	      IFS="$save_ifs"
-	    fi
-
-	    # Create $newlib
-	    if test -f "$output_objdir/$newlib"; then :; else
-	      $show "generating import library for \`$soname'"
-	      save_ifs="$IFS"; IFS='~'
-	      cmds=$old_archive_from_expsyms_cmds
-	      for cmd in $cmds; do
-		IFS="$save_ifs"
-		eval cmd=\"$cmd\"
-		$show "$cmd"
-		$run eval "$cmd" || exit $?
-	      done
-	      IFS="$save_ifs"
-	    fi
-	    # make sure the library variables are pointing to the new library
-	    dir=$output_objdir
-	    linklib=$newlib
-	  fi # test -n "$old_archive_from_expsyms_cmds"
-
-	  if test "$linkmode" = prog || test "$mode" != relink; then
-	    add_shlibpath=
-	    add_dir=
-	    add=
-	    lib_linked=yes
-	    case $hardcode_action in
-	    immediate | unsupported)
-	      if test "$hardcode_direct" = no; then
-		add="$dir/$linklib"
-		case $host in
-		  *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
-		  *-*-sysv4*uw2*) add_dir="-L$dir" ;;
-		  *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
-		    *-*-unixware7*) add_dir="-L$dir" ;;
-		  *-*-darwin* )
-		    # if the lib is a module then we can not link against
-		    # it, someone is ignoring the new warnings I added
-		    if /usr/bin/file -L $add 2> /dev/null |
-                      $EGREP ": [^:]* bundle" >/dev/null ; then
-		      $echo "** Warning, lib $linklib is a module, not a shared library"
-		      if test -z "$old_library" ; then
-		        $echo
-		        $echo "** And there doesn't seem to be a static archive available"
-		        $echo "** The link will probably fail, sorry"
-		      else
-		        add="$dir/$old_library"
-		      fi
-		    fi
-		esac
-	      elif test "$hardcode_minus_L" = no; then
-		case $host in
-		*-*-sunos*) add_shlibpath="$dir" ;;
-		esac
-		add_dir="-L$dir"
-		add="-l$name"
-	      elif test "$hardcode_shlibpath_var" = no; then
-		add_shlibpath="$dir"
-		add="-l$name"
-	      else
-		lib_linked=no
-	      fi
-	      ;;
-	    relink)
-	      if test "$hardcode_direct" = yes; then
-		add="$dir/$linklib"
-	      elif test "$hardcode_minus_L" = yes; then
-		add_dir="-L$dir"
-		# Try looking first in the location we're being installed to.
-		if test -n "$inst_prefix_dir"; then
-		  case $libdir in
-		    [\\/]*)
-		      add_dir="$add_dir -L$inst_prefix_dir$libdir"
-		      ;;
-		  esac
-		fi
-		add="-l$name"
-	      elif test "$hardcode_shlibpath_var" = yes; then
-		add_shlibpath="$dir"
-		add="-l$name"
-	      else
-		lib_linked=no
-	      fi
-	      ;;
-	    *) lib_linked=no ;;
-	    esac
-
-	    if test "$lib_linked" != yes; then
-	      $echo "$modename: configuration error: unsupported hardcode properties"
-	      exit $EXIT_FAILURE
-	    fi
-
-	    if test -n "$add_shlibpath"; then
-	      case :$compile_shlibpath: in
-	      *":$add_shlibpath:"*) ;;
-	      *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
-	      esac
-	    fi
-	    if test "$linkmode" = prog; then
-	      test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
-	      test -n "$add" && compile_deplibs="$add $compile_deplibs"
-	    else
-	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
-	      test -n "$add" && deplibs="$add $deplibs"
-	      if test "$hardcode_direct" != yes && \
-		 test "$hardcode_minus_L" != yes && \
-		 test "$hardcode_shlibpath_var" = yes; then
-		case :$finalize_shlibpath: in
-		*":$libdir:"*) ;;
-		*) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
-		esac
-	      fi
-	    fi
-	  fi
-
-	  if test "$linkmode" = prog || test "$mode" = relink; then
-	    add_shlibpath=
-	    add_dir=
-	    add=
-	    # Finalize command for both is simple: just hardcode it.
-	    if test "$hardcode_direct" = yes; then
-	      add="$libdir/$linklib"
-	    elif test "$hardcode_minus_L" = yes; then
-	      add_dir="-L$libdir"
-	      add="-l$name"
-	    elif test "$hardcode_shlibpath_var" = yes; then
-	      case :$finalize_shlibpath: in
-	      *":$libdir:"*) ;;
-	      *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
-	      esac
-	      add="-l$name"
-	    elif test "$hardcode_automatic" = yes; then
-	      if test -n "$inst_prefix_dir" &&
-		 test -f "$inst_prefix_dir$libdir/$linklib" ; then
-	        add="$inst_prefix_dir$libdir/$linklib"
-	      else
-	        add="$libdir/$linklib"
-	      fi
-	    else
-	      # We cannot seem to hardcode it, guess we'll fake it.
-	      add_dir="-L$libdir"
-	      # Try looking first in the location we're being installed to.
-	      if test -n "$inst_prefix_dir"; then
-		case $libdir in
-		  [\\/]*)
-		    add_dir="$add_dir -L$inst_prefix_dir$libdir"
-		    ;;
-		esac
-	      fi
-	      add="-l$name"
-	    fi
-
-	    if test "$linkmode" = prog; then
-	      test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
-	      test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
-	    else
-	      test -n "$add_dir" && deplibs="$add_dir $deplibs"
-	      test -n "$add" && deplibs="$add $deplibs"
-	    fi
-	  fi
-	elif test "$linkmode" = prog; then
-	  # Here we assume that one of hardcode_direct or hardcode_minus_L
-	  # is not unsupported.  This is valid on all known static and
-	  # shared platforms.
-	  if test "$hardcode_direct" != unsupported; then
-	    test -n "$old_library" && linklib="$old_library"
-	    compile_deplibs="$dir/$linklib $compile_deplibs"
-	    finalize_deplibs="$dir/$linklib $finalize_deplibs"
-	  else
-	    compile_deplibs="-l$name -L$dir $compile_deplibs"
-	    finalize_deplibs="-l$name -L$dir $finalize_deplibs"
-	  fi
-	elif test "$build_libtool_libs" = yes; then
-	  # Not a shared library
-	  if test "$deplibs_check_method" != pass_all; then
-	    # We're trying link a shared library against a static one
-	    # but the system doesn't support it.
-
-	    # Just print a warning and add the library to dependency_libs so
-	    # that the program can be linked against the static library.
-	    $echo
-	    $echo "*** Warning: This system can not link to static lib archive $lib."
-	    $echo "*** I have the capability to make that library automatically link in when"
-	    $echo "*** you link to this library.  But I can only do this if you have a"
-	    $echo "*** shared version of the library, which you do not appear to have."
-	    if test "$module" = yes; then
-	      $echo "*** But as you try to build a module library, libtool will still create "
-	      $echo "*** a static module, that should work as long as the dlopening application"
-	      $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
-	      if test -z "$global_symbol_pipe"; then
-		$echo
-		$echo "*** However, this would only work if libtool was able to extract symbol"
-		$echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
-		$echo "*** not find such a program.  So, this module is probably useless."
-		$echo "*** \`nm' from GNU binutils and a full rebuild may help."
-	      fi
-	      if test "$build_old_libs" = no; then
-		build_libtool_libs=module
-		build_old_libs=yes
-	      else
-		build_libtool_libs=no
-	      fi
-	    fi
-	  else
-	    deplibs="$dir/$old_library $deplibs"
-	    link_static=yes
-	  fi
-	fi # link shared/static library?
-
-	if test "$linkmode" = lib; then
-	  if test -n "$dependency_libs" &&
-	     { test "$hardcode_into_libs" != yes ||
-	       test "$build_old_libs" = yes ||
-	       test "$link_static" = yes; }; then
-	    # Extract -R from dependency_libs
-	    temp_deplibs=
-	    for libdir in $dependency_libs; do
-	      case $libdir in
-	      -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
-		   case " $xrpath " in
-		   *" $temp_xrpath "*) ;;
-		   *) xrpath="$xrpath $temp_xrpath";;
-		   esac;;
-	      *) temp_deplibs="$temp_deplibs $libdir";;
-	      esac
-	    done
-	    dependency_libs="$temp_deplibs"
-	  fi
-
-	  newlib_search_path="$newlib_search_path $absdir"
-	  # Link against this library
-	  test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
-	  # ... and its dependency_libs
-	  tmp_libs=
-	  for deplib in $dependency_libs; do
-	    newdependency_libs="$deplib $newdependency_libs"
-	    if test "X$duplicate_deps" = "Xyes" ; then
-	      case "$tmp_libs " in
-	      *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
-	      esac
-	    fi
-	    tmp_libs="$tmp_libs $deplib"
-	  done
-
-	  if test "$link_all_deplibs" != no; then
-	    # Add the search paths of all dependency libraries
-	    for deplib in $dependency_libs; do
-	      case $deplib in
-	      -L*) path="$deplib" ;;
-	      *.la)
-		dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
-		test "X$dir" = "X$deplib" && dir="."
-		# We need an absolute path.
-		case $dir in
-		[\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
-		*)
-		  absdir=`cd "$dir" && pwd`
-		  if test -z "$absdir"; then
-		    $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
-		    absdir="$dir"
-		  fi
-		  ;;
-		esac
-		if grep "^installed=no" $deplib > /dev/null; then
-		  path="$absdir/$objdir"
-		else
-		  eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
-		  if test -z "$libdir"; then
-		    $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
-		    exit $EXIT_FAILURE
-		  fi
-		  if test "$absdir" != "$libdir"; then
-		    $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
-		  fi
-		  path="$absdir"
-		fi
-		depdepl=
-		case $host in
-		*-*-darwin*)
-		  # we do not want to link against static libs,
-		  # but need to link against shared
-		  eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
-		  if test -n "$deplibrary_names" ; then
-		    for tmp in $deplibrary_names ; do
-		      depdepl=$tmp
-		    done
-		    if test -f "$path/$depdepl" ; then
-		      depdepl="$path/$depdepl"
-		    fi
-		    # do not add paths which are already there
-		    case " $newlib_search_path " in
-		    *" $path "*) ;;
-		    *) newlib_search_path="$newlib_search_path $path";;
-		    esac
-		  fi
-		  path=""
-		  ;;
-		*)
-		  path="-L$path"
-		  ;;
-		esac
-		;;
-	      -l*)
-		case $host in
-		*-*-darwin*)
-		  # Again, we only want to link against shared libraries
-		  eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
-		  for tmp in $newlib_search_path ; do
-		    if test -f "$tmp/lib$tmp_libs.dylib" ; then
-		      eval depdepl="$tmp/lib$tmp_libs.dylib"
-		      break
-		    fi
-		  done
-		  path=""
-		  ;;
-		*) continue ;;
-		esac
-		;;
-	      *) continue ;;
-	      esac
-	      case " $deplibs " in
-	      *" $path "*) ;;
-	      *) deplibs="$path $deplibs" ;;
-	      esac
-	      case " $deplibs " in
-	      *" $depdepl "*) ;;
-	      *) deplibs="$depdepl $deplibs" ;;
-	      esac
-	    done
-	  fi # link_all_deplibs != no
-	fi # linkmode = lib
-      done # for deplib in $libs
-      dependency_libs="$newdependency_libs"
-      if test "$pass" = dlpreopen; then
-	# Link the dlpreopened libraries before other libraries
-	for deplib in $save_deplibs; do
-	  deplibs="$deplib $deplibs"
-	done
-      fi
-      if test "$pass" != dlopen; then
-	if test "$pass" != conv; then
-	  # Make sure lib_search_path contains only unique directories.
-	  lib_search_path=
-	  for dir in $newlib_search_path; do
-	    case "$lib_search_path " in
-	    *" $dir "*) ;;
-	    *) lib_search_path="$lib_search_path $dir" ;;
-	    esac
-	  done
-	  newlib_search_path=
-	fi
-
-	if test "$linkmode,$pass" != "prog,link"; then
-	  vars="deplibs"
-	else
-	  vars="compile_deplibs finalize_deplibs"
-	fi
-	for var in $vars dependency_libs; do
-	  # Add libraries to $var in reverse order
-	  eval tmp_libs=\"\$$var\"
-	  new_libs=
-	  for deplib in $tmp_libs; do
-	    # FIXME: Pedantically, this is the right thing to do, so
-	    #        that some nasty dependency loop isn't accidentally
-	    #        broken:
-	    #new_libs="$deplib $new_libs"
-	    # Pragmatically, this seems to cause very few problems in
-	    # practice:
-	    case $deplib in
-	    -L*) new_libs="$deplib $new_libs" ;;
-	    -R*) ;;
-	    *)
-	      # And here is the reason: when a library appears more
-	      # than once as an explicit dependence of a library, or
-	      # is implicitly linked in more than once by the
-	      # compiler, it is considered special, and multiple
-	      # occurrences thereof are not removed.  Compare this
-	      # with having the same library being listed as a
-	      # dependency of multiple other libraries: in this case,
-	      # we know (pedantically, we assume) the library does not
-	      # need to be listed more than once, so we keep only the
-	      # last copy.  This is not always right, but it is rare
-	      # enough that we require users that really mean to play
-	      # such unportable linking tricks to link the library
-	      # using -Wl,-lname, so that libtool does not consider it
-	      # for duplicate removal.
-	      case " $specialdeplibs " in
-	      *" $deplib "*) new_libs="$deplib $new_libs" ;;
-	      *)
-		case " $new_libs " in
-		*" $deplib "*) ;;
-		*) new_libs="$deplib $new_libs" ;;
-		esac
-		;;
-	      esac
-	      ;;
-	    esac
-	  done
-	  tmp_libs=
-	  for deplib in $new_libs; do
-	    case $deplib in
-	    -L*)
-	      case " $tmp_libs " in
-	      *" $deplib "*) ;;
-	      *) tmp_libs="$tmp_libs $deplib" ;;
-	      esac
-	      ;;
-	    *) tmp_libs="$tmp_libs $deplib" ;;
-	    esac
-	  done
-	  eval $var=\"$tmp_libs\"
-	done # for var
-      fi
-      # Last step: remove runtime libs from dependency_libs
-      # (they stay in deplibs)
-      tmp_libs=
-      for i in $dependency_libs ; do
-	case " $predeps $postdeps $compiler_lib_search_path " in
-	*" $i "*)
-	  i=""
-	  ;;
-	esac
-	if test -n "$i" ; then
-	  tmp_libs="$tmp_libs $i"
-	fi
-      done
-      dependency_libs=$tmp_libs
-    done # for pass
-    if test "$linkmode" = prog; then
-      dlfiles="$newdlfiles"
-      dlprefiles="$newdlprefiles"
-    fi
-
-    case $linkmode in
-    oldlib)
-      if test -n "$deplibs"; then
-	$echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
-      fi
-
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-	$echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$rpath"; then
-	$echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$xrpath"; then
-	$echo "$modename: warning: \`-R' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$vinfo"; then
-	$echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$release"; then
-	$echo "$modename: warning: \`-release' is ignored for archives" 1>&2
-      fi
-
-      if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
-	$echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
-      fi
-
-      # Now set the variables for building old libraries.
-      build_libtool_libs=no
-      oldlibs="$output"
-      objs="$objs$old_deplibs"
-      ;;
-
-    lib)
-      # Make sure we only generate libraries of the form `libNAME.la'.
-      case $outputname in
-      lib*)
-	name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
-	eval shared_ext=\"$shrext_cmds\"
-	eval libname=\"$libname_spec\"
-	;;
-      *)
-	if test "$module" = no; then
-	  $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
-	  $echo "$help" 1>&2
-	  exit $EXIT_FAILURE
-	fi
-	if test "$need_lib_prefix" != no; then
-	  # Add the "lib" prefix for modules if required
-	  name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
-	  eval shared_ext=\"$shrext_cmds\"
-	  eval libname=\"$libname_spec\"
-	else
-	  libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
-	fi
-	;;
-      esac
-
-      if test -n "$objs"; then
-	if test "$deplibs_check_method" != pass_all; then
-	  $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
-	  exit $EXIT_FAILURE
-	else
-	  $echo
-	  $echo "*** Warning: Linking the shared library $output against the non-libtool"
-	  $echo "*** objects $objs is not portable!"
-	  libobjs="$libobjs $objs"
-	fi
-      fi
-
-      if test "$dlself" != no; then
-	$echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
-      fi
-
-      set dummy $rpath
-      if test "$#" -gt 2; then
-	$echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
-      fi
-      install_libdir="$2"
-
-      oldlibs=
-      if test -z "$rpath"; then
-	if test "$build_libtool_libs" = yes; then
-	  # Building a libtool convenience library.
-	  # Some compilers have problems with a `.al' extension so
-	  # convenience libraries should have the same extension an
-	  # archive normally would.
-	  oldlibs="$output_objdir/$libname.$libext $oldlibs"
-	  build_libtool_libs=convenience
-	  build_old_libs=yes
-	fi
-
-	if test -n "$vinfo"; then
-	  $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
-	fi
-
-	if test -n "$release"; then
-	  $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
-	fi
-      else
-
-	# Parse the version information argument.
-	save_ifs="$IFS"; IFS=':'
-	set dummy $vinfo 0 0 0
-	IFS="$save_ifs"
-
-	if test -n "$8"; then
-	  $echo "$modename: too many parameters to \`-version-info'" 1>&2
-	  $echo "$help" 1>&2
-	  exit $EXIT_FAILURE
-	fi
-
-	# convert absolute version numbers to libtool ages
-	# this retains compatibility with .la files and attempts
-	# to make the code below a bit more comprehensible
-
-	case $vinfo_number in
-	yes)
-	  number_major="$2"
-	  number_minor="$3"
-	  number_revision="$4"
-	  #
-	  # There are really only two kinds -- those that
-	  # use the current revision as the major version
-	  # and those that subtract age and use age as
-	  # a minor version.  But, then there is irix
-	  # which has an extra 1 added just for fun
-	  #
-	  case $version_type in
-	  darwin|linux|osf|windows)
-	    current=`expr $number_major + $number_minor`
-	    age="$number_minor"
-	    revision="$number_revision"
-	    ;;
-	  freebsd-aout|freebsd-elf|sunos)
-	    current="$number_major"
-	    revision="$number_minor"
-	    age="0"
-	    ;;
-	  irix|nonstopux)
-	    current=`expr $number_major + $number_minor - 1`
-	    age="$number_minor"
-	    revision="$number_minor"
-	    ;;
-	  *)
-	    $echo "$modename: unknown library version type \`$version_type'" 1>&2
-	    $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-	    exit $EXIT_FAILURE
-	    ;;
-	  esac
-	  ;;
-	no)
-	  current="$2"
-	  revision="$3"
-	  age="$4"
-	  ;;
-	esac
-
-	# Check that each of the things are valid numbers.
-	case $current in
-	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
-	*)
-	  $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
-	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit $EXIT_FAILURE
-	  ;;
-	esac
-
-	case $revision in
-	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
-	*)
-	  $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
-	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit $EXIT_FAILURE
-	  ;;
-	esac
-
-	case $age in
-	0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
-	*)
-	  $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
-	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit $EXIT_FAILURE
-	  ;;
-	esac
-
-	if test "$age" -gt "$current"; then
-	  $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
-	  $echo "$modename: \`$vinfo' is not valid version information" 1>&2
-	  exit $EXIT_FAILURE
-	fi
-
-	# Calculate the version variables.
-	major=
-	versuffix=
-	verstring=
-	case $version_type in
-	none) ;;
-
-	darwin)
-	  # Like Linux, but with the current version available in
-	  # verstring for coding it into the library header
-	  major=.`expr $current - $age`
-	  versuffix="$major.$age.$revision"
-	  # Darwin ld doesn't like 0 for these options...
-	  minor_current=`expr $current + 1`
-	  verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
-	  ;;
-
-	freebsd-aout)
-	  major=".$current"
-	  versuffix=".$current.$revision";
-	  ;;
-
-	freebsd-elf)
-	  major=".$current"
-	  versuffix=".$current";
-	  ;;
-
-	irix | nonstopux)
-	  major=`expr $current - $age + 1`
-
-	  case $version_type in
-	    nonstopux) verstring_prefix=nonstopux ;;
-	    *)         verstring_prefix=sgi ;;
-	  esac
-	  verstring="$verstring_prefix$major.$revision"
-
-	  # Add in all the interfaces that we are compatible with.
-	  loop=$revision
-	  while test "$loop" -ne 0; do
-	    iface=`expr $revision - $loop`
-	    loop=`expr $loop - 1`
-	    verstring="$verstring_prefix$major.$iface:$verstring"
-	  done
-
-	  # Before this point, $major must not contain `.'.
-	  major=.$major
-	  versuffix="$major.$revision"
-	  ;;
-
-	linux)
-	  major=.`expr $current - $age`
-	  versuffix="$major.$age.$revision"
-	  ;;
-
-	osf)
-	  major=.`expr $current - $age`
-	  versuffix=".$current.$age.$revision"
-	  verstring="$current.$age.$revision"
-
-	  # Add in all the interfaces that we are compatible with.
-	  loop=$age
-	  while test "$loop" -ne 0; do
-	    iface=`expr $current - $loop`
-	    loop=`expr $loop - 1`
-	    verstring="$verstring:${iface}.0"
-	  done
-
-	  # Make executables depend on our current version.
-	  verstring="$verstring:${current}.0"
-	  ;;
-
-	sunos)
-	  major=".$current"
-	  versuffix=".$current.$revision"
-	  ;;
-
-	windows)
-	  # Use '-' rather than '.', since we only want one
-	  # extension on DOS 8.3 filesystems.
-	  major=`expr $current - $age`
-	  versuffix="-$major"
-	  ;;
-
-	*)
-	  $echo "$modename: unknown library version type \`$version_type'" 1>&2
-	  $echo "Fatal configuration error.  See the $PACKAGE docs for more information." 1>&2
-	  exit $EXIT_FAILURE
-	  ;;
-	esac
-
-	# Clear the version info if we defaulted, and they specified a release.
-	if test -z "$vinfo" && test -n "$release"; then
-	  major=
-	  case $version_type in
-	  darwin)
-	    # we can't check for "0.0" in archive_cmds due to quoting
-	    # problems, so we reset it completely
-	    verstring=
-	    ;;
-	  *)
-	    verstring="0.0"
-	    ;;
-	  esac
-	  if test "$need_version" = no; then
-	    versuffix=
-	  else
-	    versuffix=".0.0"
-	  fi
-	fi
-
-	# Remove version info from name if versioning should be avoided
-	if test "$avoid_version" = yes && test "$need_version" = no; then
-	  major=
-	  versuffix=
-	  verstring=""
-	fi
-
-	# Check to see if the archive will have undefined symbols.
-	if test "$allow_undefined" = yes; then
-	  if test "$allow_undefined_flag" = unsupported; then
-	    $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
-	    build_libtool_libs=no
-	    build_old_libs=yes
-	  fi
-	else
-	  # Don't allow undefined symbols.
-	  allow_undefined_flag="$no_undefined_flag"
-	fi
-      fi
-
-      if test "$mode" != relink; then
-	# Remove our outputs, but don't remove object files since they
-	# may have been created when compiling PIC objects.
-	removelist=
-	tempremovelist=`$echo "$output_objdir/*"`
-	for p in $tempremovelist; do
-	  case $p in
-	    *.$objext)
-	       ;;
-	    $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
-	       if test "X$precious_files_regex" != "X"; then
-	         if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
-	         then
-		   continue
-		 fi
-	       fi
-	       removelist="$removelist $p"
-	       ;;
-	    *) ;;
-	  esac
-	done
-	if test -n "$removelist"; then
-	  $show "${rm}r $removelist"
-	  $run ${rm}r $removelist
-	fi
-      fi
-
-      # Now set the variables for building old libraries.
-      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
-	oldlibs="$oldlibs $output_objdir/$libname.$libext"
-
-	# Transform .lo files to .o files.
-	oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
-      fi
-
-      # Eliminate all temporary directories.
-      for path in $notinst_path; do
-	lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
-	deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
-	dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
-      done
-
-      if test -n "$xrpath"; then
-	# If the user specified any rpath flags, then add them.
-	temp_xrpath=
-	for libdir in $xrpath; do
-	  temp_xrpath="$temp_xrpath -R$libdir"
-	  case "$finalize_rpath " in
-	  *" $libdir "*) ;;
-	  *) finalize_rpath="$finalize_rpath $libdir" ;;
-	  esac
-	done
-	if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
-	  dependency_libs="$temp_xrpath $dependency_libs"
-	fi
-      fi
-
-      # Make sure dlfiles contains only unique files that won't be dlpreopened
-      old_dlfiles="$dlfiles"
-      dlfiles=
-      for lib in $old_dlfiles; do
-	case " $dlprefiles $dlfiles " in
-	*" $lib "*) ;;
-	*) dlfiles="$dlfiles $lib" ;;
-	esac
-      done
-
-      # Make sure dlprefiles contains only unique files
-      old_dlprefiles="$dlprefiles"
-      dlprefiles=
-      for lib in $old_dlprefiles; do
-	case "$dlprefiles " in
-	*" $lib "*) ;;
-	*) dlprefiles="$dlprefiles $lib" ;;
-	esac
-      done
-
-      if test "$build_libtool_libs" = yes; then
-	if test -n "$rpath"; then
-	  case $host in
-	  *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
-	    # these systems don't actually have a c library (as such)!
-	    ;;
-	  *-*-rhapsody* | *-*-darwin1.[012])
-	    # Rhapsody C library is in the System framework
-	    deplibs="$deplibs -framework System"
-	    ;;
-	  *-*-netbsd*)
-	    # Don't link with libc until the a.out ld.so is fixed.
-	    ;;
-	  *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
-	    # Do not include libc due to us having libc/libc_r.
-	    ;;
-	  *-*-sco3.2v5* | *-*-sco5v6*)
-	    # Causes problems with __ctype
-	    ;;
-	  *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
-	    # Compiler inserts libc in the correct place for threads to work
-	    ;;
- 	  *)
-	    # Add libc to deplibs on all other systems if necessary.
-	    if test "$build_libtool_need_lc" = "yes"; then
-	      deplibs="$deplibs -lc"
-	    fi
-	    ;;
-	  esac
-	fi
-
-	# Transform deplibs into only deplibs that can be linked in shared.
-	name_save=$name
-	libname_save=$libname
-	release_save=$release
-	versuffix_save=$versuffix
-	major_save=$major
-	# I'm not sure if I'm treating the release correctly.  I think
-	# release should show up in the -l (ie -lgmp5) so we don't want to
-	# add it in twice.  Is that correct?
-	release=""
-	versuffix=""
-	major=""
-	newdeplibs=
-	droppeddeps=no
-	case $deplibs_check_method in
-	pass_all)
-	  # Don't check for shared/static.  Everything works.
-	  # This might be a little naive.  We might want to check
-	  # whether the library exists or not.  But this is on
-	  # osf3 & osf4 and I'm not really sure... Just
-	  # implementing what was already the behavior.
-	  newdeplibs=$deplibs
-	  ;;
-	test_compile)
-	  # This code stresses the "libraries are programs" paradigm to its
-	  # limits. Maybe even breaks it.  We compile a program, linking it
-	  # against the deplibs as a proxy for the library.  Then we can check
-	  # whether they linked in statically or dynamically with ldd.
-	  $rm conftest.c
-	  cat > conftest.c <<EOF
-	  int main() { return 0; }
-EOF
-	  $rm conftest
-	  $LTCC $LTCFLAGS -o conftest conftest.c $deplibs
-	  if test "$?" -eq 0 ; then
-	    ldd_output=`ldd conftest`
-	    for i in $deplibs; do
-	      name=`expr $i : '-l\(.*\)'`
-	      # If $name is empty we are operating on a -L argument.
-              if test "$name" != "" && test "$name" -ne "0"; then
-		if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-		  case " $predeps $postdeps " in
-		  *" $i "*)
-		    newdeplibs="$newdeplibs $i"
-		    i=""
-		    ;;
-		  esac
-	        fi
-		if test -n "$i" ; then
-		  libname=`eval \\$echo \"$libname_spec\"`
-		  deplib_matches=`eval \\$echo \"$library_names_spec\"`
-		  set dummy $deplib_matches
-		  deplib_match=$2
-		  if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-		    newdeplibs="$newdeplibs $i"
-		  else
-		    droppeddeps=yes
-		    $echo
-		    $echo "*** Warning: dynamic linker does not accept needed library $i."
-		    $echo "*** I have the capability to make that library automatically link in when"
-		    $echo "*** you link to this library.  But I can only do this if you have a"
-		    $echo "*** shared version of the library, which I believe you do not have"
-		    $echo "*** because a test_compile did reveal that the linker did not use it for"
-		    $echo "*** its dynamic dependency list that programs get resolved with at runtime."
-		  fi
-		fi
-	      else
-		newdeplibs="$newdeplibs $i"
-	      fi
-	    done
-	  else
-	    # Error occurred in the first compile.  Let's try to salvage
-	    # the situation: Compile a separate program for each library.
-	    for i in $deplibs; do
-	      name=`expr $i : '-l\(.*\)'`
-	      # If $name is empty we are operating on a -L argument.
-              if test "$name" != "" && test "$name" != "0"; then
-		$rm conftest
-		$LTCC $LTCFLAGS -o conftest conftest.c $i
-		# Did it work?
-		if test "$?" -eq 0 ; then
-		  ldd_output=`ldd conftest`
-		  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-		    case " $predeps $postdeps " in
-		    *" $i "*)
-		      newdeplibs="$newdeplibs $i"
-		      i=""
-		      ;;
-		    esac
-		  fi
-		  if test -n "$i" ; then
-		    libname=`eval \\$echo \"$libname_spec\"`
-		    deplib_matches=`eval \\$echo \"$library_names_spec\"`
-		    set dummy $deplib_matches
-		    deplib_match=$2
-		    if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
-		      newdeplibs="$newdeplibs $i"
-		    else
-		      droppeddeps=yes
-		      $echo
-		      $echo "*** Warning: dynamic linker does not accept needed library $i."
-		      $echo "*** I have the capability to make that library automatically link in when"
-		      $echo "*** you link to this library.  But I can only do this if you have a"
-		      $echo "*** shared version of the library, which you do not appear to have"
-		      $echo "*** because a test_compile did reveal that the linker did not use this one"
-		      $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
-		    fi
-		  fi
-		else
-		  droppeddeps=yes
-		  $echo
-		  $echo "*** Warning!  Library $i is needed by this library but I was not able to"
-		  $echo "***  make it link in!  You will probably need to install it or some"
-		  $echo "*** library that it depends on before this library will be fully"
-		  $echo "*** functional.  Installing it before continuing would be even better."
-		fi
-	      else
-		newdeplibs="$newdeplibs $i"
-	      fi
-	    done
-	  fi
-	  ;;
-	file_magic*)
-	  set dummy $deplibs_check_method
-	  file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
-	  for a_deplib in $deplibs; do
-	    name=`expr $a_deplib : '-l\(.*\)'`
-	    # If $name is empty we are operating on a -L argument.
-            if test "$name" != "" && test  "$name" != "0"; then
-	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-		case " $predeps $postdeps " in
-		*" $a_deplib "*)
-		  newdeplibs="$newdeplibs $a_deplib"
-		  a_deplib=""
-		  ;;
-		esac
-	      fi
-	      if test -n "$a_deplib" ; then
-		libname=`eval \\$echo \"$libname_spec\"`
-		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
-		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
-		  for potent_lib in $potential_libs; do
-		      # Follow soft links.
-		      if ls -lLd "$potent_lib" 2>/dev/null \
-			 | grep " -> " >/dev/null; then
-			continue
-		      fi
-		      # The statement above tries to avoid entering an
-		      # endless loop below, in case of cyclic links.
-		      # We might still enter an endless loop, since a link
-		      # loop can be closed while we follow links,
-		      # but so what?
-		      potlib="$potent_lib"
-		      while test -h "$potlib" 2>/dev/null; do
-			potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
-			case $potliblink in
-			[\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
-			*) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
-			esac
-		      done
-		      if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
-			 | ${SED} 10q \
-			 | $EGREP "$file_magic_regex" > /dev/null; then
-			newdeplibs="$newdeplibs $a_deplib"
-			a_deplib=""
-			break 2
-		      fi
-		  done
-		done
-	      fi
-	      if test -n "$a_deplib" ; then
-		droppeddeps=yes
-		$echo
-		$echo "*** Warning: linker path does not have real file for library $a_deplib."
-		$echo "*** I have the capability to make that library automatically link in when"
-		$echo "*** you link to this library.  But I can only do this if you have a"
-		$echo "*** shared version of the library, which you do not appear to have"
-		$echo "*** because I did check the linker path looking for a file starting"
-		if test -z "$potlib" ; then
-		  $echo "*** with $libname but no candidates were found. (...for file magic test)"
-		else
-		  $echo "*** with $libname and none of the candidates passed a file format test"
-		  $echo "*** using a file magic. Last file checked: $potlib"
-		fi
-	      fi
-	    else
-	      # Add a -L argument.
-	      newdeplibs="$newdeplibs $a_deplib"
-	    fi
-	  done # Gone through all deplibs.
-	  ;;
-	match_pattern*)
-	  set dummy $deplibs_check_method
-	  match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
-	  for a_deplib in $deplibs; do
-	    name=`expr $a_deplib : '-l\(.*\)'`
-	    # If $name is empty we are operating on a -L argument.
-	    if test -n "$name" && test "$name" != "0"; then
-	      if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-		case " $predeps $postdeps " in
-		*" $a_deplib "*)
-		  newdeplibs="$newdeplibs $a_deplib"
-		  a_deplib=""
-		  ;;
-		esac
-	      fi
-	      if test -n "$a_deplib" ; then
-		libname=`eval \\$echo \"$libname_spec\"`
-		for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
-		  potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
-		  for potent_lib in $potential_libs; do
-		    potlib="$potent_lib" # see symlink-check above in file_magic test
-		    if eval $echo \"$potent_lib\" 2>/dev/null \
-		        | ${SED} 10q \
-		        | $EGREP "$match_pattern_regex" > /dev/null; then
-		      newdeplibs="$newdeplibs $a_deplib"
-		      a_deplib=""
-		      break 2
-		    fi
-		  done
-		done
-	      fi
-	      if test -n "$a_deplib" ; then
-		droppeddeps=yes
-		$echo
-		$echo "*** Warning: linker path does not have real file for library $a_deplib."
-		$echo "*** I have the capability to make that library automatically link in when"
-		$echo "*** you link to this library.  But I can only do this if you have a"
-		$echo "*** shared version of the library, which you do not appear to have"
-		$echo "*** because I did check the linker path looking for a file starting"
-		if test -z "$potlib" ; then
-		  $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
-		else
-		  $echo "*** with $libname and none of the candidates passed a file format test"
-		  $echo "*** using a regex pattern. Last file checked: $potlib"
-		fi
-	      fi
-	    else
-	      # Add a -L argument.
-	      newdeplibs="$newdeplibs $a_deplib"
-	    fi
-	  done # Gone through all deplibs.
-	  ;;
-	none | unknown | *)
-	  newdeplibs=""
-	  tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
-	    -e 's/ -[LR][^ ]*//g'`
-	  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
-	    for i in $predeps $postdeps ; do
-	      # can't use Xsed below, because $i might contain '/'
-	      tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
-	    done
-	  fi
-	  if $echo "X $tmp_deplibs" | $Xsed -e 's/[ 	]//g' \
-	    | grep . >/dev/null; then
-	    $echo
-	    if test "X$deplibs_check_method" = "Xnone"; then
-	      $echo "*** Warning: inter-library dependencies are not supported in this platform."
-	    else
-	      $echo "*** Warning: inter-library dependencies are not known to be supported."
-	    fi
-	    $echo "*** All declared inter-library dependencies are being dropped."
-	    droppeddeps=yes
-	  fi
-	  ;;
-	esac
-	versuffix=$versuffix_save
-	major=$major_save
-	release=$release_save
-	libname=$libname_save
-	name=$name_save
-
-	case $host in
-	*-*-rhapsody* | *-*-darwin1.[012])
-	  # On Rhapsody replace the C library is the System framework
-	  newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
-	  ;;
-	esac
-
-	if test "$droppeddeps" = yes; then
-	  if test "$module" = yes; then
-	    $echo
-	    $echo "*** Warning: libtool could not satisfy all declared inter-library"
-	    $echo "*** dependencies of module $libname.  Therefore, libtool will create"
-	    $echo "*** a static module, that should work as long as the dlopening"
-	    $echo "*** application is linked with the -dlopen flag."
-	    if test -z "$global_symbol_pipe"; then
-	      $echo
-	      $echo "*** However, this would only work if libtool was able to extract symbol"
-	      $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
-	      $echo "*** not find such a program.  So, this module is probably useless."
-	      $echo "*** \`nm' from GNU binutils and a full rebuild may help."
-	    fi
-	    if test "$build_old_libs" = no; then
-	      oldlibs="$output_objdir/$libname.$libext"
-	      build_libtool_libs=module
-	      build_old_libs=yes
-	    else
-	      build_libtool_libs=no
-	    fi
-	  else
-	    $echo "*** The inter-library dependencies that have been dropped here will be"
-	    $echo "*** automatically added whenever a program is linked with this library"
-	    $echo "*** or is declared to -dlopen it."
-
-	    if test "$allow_undefined" = no; then
-	      $echo
-	      $echo "*** Since this library must not contain undefined symbols,"
-	      $echo "*** because either the platform does not support them or"
-	      $echo "*** it was explicitly requested with -no-undefined,"
-	      $echo "*** libtool will only create a static version of it."
-	      if test "$build_old_libs" = no; then
-		oldlibs="$output_objdir/$libname.$libext"
-		build_libtool_libs=module
-		build_old_libs=yes
-	      else
-		build_libtool_libs=no
-	      fi
-	    fi
-	  fi
-	fi
-	# Done checking deplibs!
-	deplibs=$newdeplibs
-      fi
-
-
-      # move library search paths that coincide with paths to not yet
-      # installed libraries to the beginning of the library search list
-      new_libs=
-      for path in $notinst_path; do
-	case " $new_libs " in
-	*" -L$path/$objdir "*) ;;
-	*)
-	  case " $deplibs " in
-	  *" -L$path/$objdir "*)
-	    new_libs="$new_libs -L$path/$objdir" ;;
-	  esac
-	  ;;
-	esac
-      done
-      for deplib in $deplibs; do
-	case $deplib in
-	-L*)
-	  case " $new_libs " in
-	  *" $deplib "*) ;;
-	  *) new_libs="$new_libs $deplib" ;;
-	  esac
-	  ;;
-	*) new_libs="$new_libs $deplib" ;;
-	esac
-      done
-      deplibs="$new_libs"
-
-
-      # All the library-specific variables (install_libdir is set above).
-      library_names=
-      old_library=
-      dlname=
-
-      # Test again, we may have decided not to build it any more
-      if test "$build_libtool_libs" = yes; then
-	if test "$hardcode_into_libs" = yes; then
-	  # Hardcode the library paths
-	  hardcode_libdirs=
-	  dep_rpath=
-	  rpath="$finalize_rpath"
-	  test "$mode" != relink && rpath="$compile_rpath$rpath"
-	  for libdir in $rpath; do
-	    if test -n "$hardcode_libdir_flag_spec"; then
-	      if test -n "$hardcode_libdir_separator"; then
-		if test -z "$hardcode_libdirs"; then
-		  hardcode_libdirs="$libdir"
-		else
-		  # Just accumulate the unique libdirs.
-		  case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
-		  *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
-		    ;;
-		  *)
-		    hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
-		    ;;
-		  esac
-		fi
-	      else
-		eval flag=\"$hardcode_libdir_flag_spec\"
-		dep_rpath="$dep_rpath $flag"
-	      fi
-	    elif test -n "$runpath_var"; then
-	      case "$perm_rpath " in
-	      *" $libdir "*) ;;
-	      *) perm_rpath="$perm_rpath $libdir" ;;
-	      esac
-	    fi
-	  done
-	  # Substitute the hardcoded libdirs into the rpath.
-	  if test -n "$hardcode_libdir_separator" &&
-	     test -n "$hardcode_libdirs"; then
-	    libdir="$hardcode_libdirs"
-	    if test -n "$hardcode_libdir_flag_spec_ld"; then
-	      eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
-	    else
-	      eval dep_rpath=\"$hardcode_libdir_flag_spec\"
-	    fi
-	  fi
-	  if test -n "$runpath_var" && test -n "$perm_rpath"; then
-	    # We should set the runpath_var.
-	    rpath=
-	    for dir in $perm_rpath; do
-	      rpath="$rpath$dir:"
-	    done
-	    eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
-	  fi
-	  test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
-	fi
-
-	shlibpath="$finalize_shlibpath"
-	test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
-	if test -n "$shlibpath"; then
-	  eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
-	fi
-
-	# Get the real and link names of the library.
-	eval shared_ext=\"$shrext_cmds\"
-	eval library_names=\"$library_names_spec\"
-	set dummy $library_names
-	realname="$2"
-	shift; shift
-
-	if test -n "$soname_spec"; then
-	  eval soname=\"$soname_spec\"
-	else
-	  soname="$realname"
-	fi
-	if test -z "$dlname"; then
-	  dlname=$soname
-	fi
-
-	lib="$output_objdir/$realname"
-	linknames=
-	for link
-	do
-	  linknames="$linknames $link"
-	done
-
-	# Use standard objects if they are pic
-	test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-
-	# Prepare the list of exported symbols
-	if test -z "$export_symbols"; then
-	  if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
-	    $show "generating symbol list for \`$libname.la'"
-	    export_symbols="$output_objdir/$libname.exp"
-	    $run $rm $export_symbols
-	    cmds=$export_symbols_cmds
-	    save_ifs="$IFS"; IFS='~'
-	    for cmd in $cmds; do
-	      IFS="$save_ifs"
-	      eval cmd=\"$cmd\"
-	      if len=`expr "X$cmd" : ".*"` &&
-	       test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
-	        $show "$cmd"
-	        $run eval "$cmd" || exit $?
-	        skipped_export=false
-	      else
-	        # The command line is too long to execute in one step.
-	        $show "using reloadable object file for export list..."
-	        skipped_export=:
-		# Break out early, otherwise skipped_export may be
-		# set to false by a later but shorter cmd.
-		break
-	      fi
-	    done
-	    IFS="$save_ifs"
-	    if test -n "$export_symbols_regex"; then
-	      $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
-	      $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
-	      $show "$mv \"${export_symbols}T\" \"$export_symbols\""
-	      $run eval '$mv "${export_symbols}T" "$export_symbols"'
-	    fi
-	  fi
-	fi
-
-	if test -n "$export_symbols" && test -n "$include_expsyms"; then
-	  $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
-	fi
-
-	tmp_deplibs=
-	for test_deplib in $deplibs; do
-		case " $convenience " in
-		*" $test_deplib "*) ;;
-		*)
-			tmp_deplibs="$tmp_deplibs $test_deplib"
-			;;
-		esac
-	done
-	deplibs="$tmp_deplibs"
-
-	if test -n "$convenience"; then
-	  if test -n "$whole_archive_flag_spec"; then
-	    save_libobjs=$libobjs
-	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
-	  else
-	    gentop="$output_objdir/${outputname}x"
-	    generated="$generated $gentop"
-
-	    func_extract_archives $gentop $convenience
-	    libobjs="$libobjs $func_extract_archives_result"
-	  fi
-	fi
-	
-	if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
-	  eval flag=\"$thread_safe_flag_spec\"
-	  linker_flags="$linker_flags $flag"
-	fi
-
-	# Make a backup of the uninstalled library when relinking
-	if test "$mode" = relink; then
-	  $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
-	fi
-
-	# Do each of the archive commands.
-	if test "$module" = yes && test -n "$module_cmds" ; then
-	  if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
-	    eval test_cmds=\"$module_expsym_cmds\"
-	    cmds=$module_expsym_cmds
-	  else
-	    eval test_cmds=\"$module_cmds\"
-	    cmds=$module_cmds
-	  fi
-	else
-	if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
-	  eval test_cmds=\"$archive_expsym_cmds\"
-	  cmds=$archive_expsym_cmds
-	else
-	  eval test_cmds=\"$archive_cmds\"
-	  cmds=$archive_cmds
-	  fi
-	fi
-
-	if test "X$skipped_export" != "X:" &&
-	   len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
-	   test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
-	  :
-	else
-	  # The command line is too long to link in one step, link piecewise.
-	  $echo "creating reloadable object files..."
-
-	  # Save the value of $output and $libobjs because we want to
-	  # use them later.  If we have whole_archive_flag_spec, we
-	  # want to use save_libobjs as it was before
-	  # whole_archive_flag_spec was expanded, because we can't
-	  # assume the linker understands whole_archive_flag_spec.
-	  # This may have to be revisited, in case too many
-	  # convenience libraries get linked in and end up exceeding
-	  # the spec.
-	  if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
-	    save_libobjs=$libobjs
-	  fi
-	  save_output=$output
-	  output_la=`$echo "X$output" | $Xsed -e "$basename"`
-
-	  # Clear the reloadable object creation command queue and
-	  # initialize k to one.
-	  test_cmds=
-	  concat_cmds=
-	  objlist=
-	  delfiles=
-	  last_robj=
-	  k=1
-	  output=$output_objdir/$output_la-${k}.$objext
-	  # Loop over the list of objects to be linked.
-	  for obj in $save_libobjs
-	  do
-	    eval test_cmds=\"$reload_cmds $objlist $last_robj\"
-	    if test "X$objlist" = X ||
-	       { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
-		 test "$len" -le "$max_cmd_len"; }; then
-	      objlist="$objlist $obj"
-	    else
-	      # The command $test_cmds is almost too long, add a
-	      # command to the queue.
-	      if test "$k" -eq 1 ; then
-		# The first file doesn't have a previous command to add.
-		eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
-	      else
-		# All subsequent reloadable object files will link in
-		# the last one created.
-		eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
-	      fi
-	      last_robj=$output_objdir/$output_la-${k}.$objext
-	      k=`expr $k + 1`
-	      output=$output_objdir/$output_la-${k}.$objext
-	      objlist=$obj
-	      len=1
-	    fi
-	  done
-	  # Handle the remaining objects by creating one last
-	  # reloadable object file.  All subsequent reloadable object
-	  # files will link in the last one created.
-	  test -z "$concat_cmds" || concat_cmds=$concat_cmds~
-	  eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
-
-	  if ${skipped_export-false}; then
-	    $show "generating symbol list for \`$libname.la'"
-	    export_symbols="$output_objdir/$libname.exp"
-	    $run $rm $export_symbols
-	    libobjs=$output
-	    # Append the command to create the export file.
-	    eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
-          fi
-
-	  # Set up a command to remove the reloadable object files
-	  # after they are used.
-	  i=0
-	  while test "$i" -lt "$k"
-	  do
-	    i=`expr $i + 1`
-	    delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
-	  done
-
-	  $echo "creating a temporary reloadable object file: $output"
-
-	  # Loop through the commands generated above and execute them.
-	  save_ifs="$IFS"; IFS='~'
-	  for cmd in $concat_cmds; do
-	    IFS="$save_ifs"
-	    $show "$cmd"
-	    $run eval "$cmd" || exit $?
-	  done
-	  IFS="$save_ifs"
-
-	  libobjs=$output
-	  # Restore the value of output.
-	  output=$save_output
-
-	  if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
-	    eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
-	  fi
-	  # Expand the library linking commands again to reset the
-	  # value of $libobjs for piecewise linking.
-
-	  # Do each of the archive commands.
-	  if test "$module" = yes && test -n "$module_cmds" ; then
-	    if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
-	      cmds=$module_expsym_cmds
-	    else
-	      cmds=$module_cmds
-	    fi
-	  else
-	  if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
-	    cmds=$archive_expsym_cmds
-	  else
-	    cmds=$archive_cmds
-	    fi
-	  fi
-
-	  # Append the command to remove the reloadable object files
-	  # to the just-reset $cmds.
-	  eval cmds=\"\$cmds~\$rm $delfiles\"
-	fi
-	save_ifs="$IFS"; IFS='~'
-	for cmd in $cmds; do
-	  IFS="$save_ifs"
-	  eval cmd=\"$cmd\"
-	  $show "$cmd"
-	  $run eval "$cmd" || {
-	    lt_exit=$?
-
-	    # Restore the uninstalled library and exit
-	    if test "$mode" = relink; then
-	      $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
-	    fi
-
-	    exit $lt_exit
-	  }
-	done
-	IFS="$save_ifs"
-
-	# Restore the uninstalled library and exit
-	if test "$mode" = relink; then
-	  $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
-
-	  if test -n "$convenience"; then
-	    if test -z "$whole_archive_flag_spec"; then
-	      $show "${rm}r $gentop"
-	      $run ${rm}r "$gentop"
-	    fi
-	  fi
-
-	  exit $EXIT_SUCCESS
-	fi
-
-	# Create links to the real library.
-	for linkname in $linknames; do
-	  if test "$realname" != "$linkname"; then
-	    $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
-	    $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
-	  fi
-	done
-
-	# If -module or -export-dynamic was specified, set the dlname.
-	if test "$module" = yes || test "$export_dynamic" = yes; then
-	  # On all known operating systems, these are identical.
-	  dlname="$soname"
-	fi
-      fi
-      ;;
-
-    obj)
-      if test -n "$deplibs"; then
-	$echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
-      fi
-
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-	$echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$rpath"; then
-	$echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$xrpath"; then
-	$echo "$modename: warning: \`-R' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$vinfo"; then
-	$echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
-      fi
-
-      if test -n "$release"; then
-	$echo "$modename: warning: \`-release' is ignored for objects" 1>&2
-      fi
-
-      case $output in
-      *.lo)
-	if test -n "$objs$old_deplibs"; then
-	  $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
-	  exit $EXIT_FAILURE
-	fi
-	libobj="$output"
-	obj=`$echo "X$output" | $Xsed -e "$lo2o"`
-	;;
-      *)
-	libobj=
-	obj="$output"
-	;;
-      esac
-
-      # Delete the old objects.
-      $run $rm $obj $libobj
-
-      # Objects from convenience libraries.  This assumes
-      # single-version convenience libraries.  Whenever we create
-      # different ones for PIC/non-PIC, this we'll have to duplicate
-      # the extraction.
-      reload_conv_objs=
-      gentop=
-      # reload_cmds runs $LD directly, so let us get rid of
-      # -Wl from whole_archive_flag_spec
-      wl=
-
-      if test -n "$convenience"; then
-	if test -n "$whole_archive_flag_spec"; then
-	  eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
-	else
-	  gentop="$output_objdir/${obj}x"
-	  generated="$generated $gentop"
-
-	  func_extract_archives $gentop $convenience
-	  reload_conv_objs="$reload_objs $func_extract_archives_result"
-	fi
-      fi
-
-      # Create the old-style object.
-      reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
-
-      output="$obj"
-      cmds=$reload_cmds
-      save_ifs="$IFS"; IFS='~'
-      for cmd in $cmds; do
-	IFS="$save_ifs"
-	eval cmd=\"$cmd\"
-	$show "$cmd"
-	$run eval "$cmd" || exit $?
-      done
-      IFS="$save_ifs"
-
-      # Exit if we aren't doing a library object file.
-      if test -z "$libobj"; then
-	if test -n "$gentop"; then
-	  $show "${rm}r $gentop"
-	  $run ${rm}r $gentop
-	fi
-
-	exit $EXIT_SUCCESS
-      fi
-
-      if test "$build_libtool_libs" != yes; then
-	if test -n "$gentop"; then
-	  $show "${rm}r $gentop"
-	  $run ${rm}r $gentop
-	fi
-
-	# Create an invalid libtool object if no PIC, so that we don't
-	# accidentally link it into a program.
-	# $show "echo timestamp > $libobj"
-	# $run eval "echo timestamp > $libobj" || exit $?
-	exit $EXIT_SUCCESS
-      fi
-
-      if test -n "$pic_flag" || test "$pic_mode" != default; then
-	# Only do commands if we really have different PIC objects.
-	reload_objs="$libobjs $reload_conv_objs"
-	output="$libobj"
-	cmds=$reload_cmds
-	save_ifs="$IFS"; IFS='~'
-	for cmd in $cmds; do
-	  IFS="$save_ifs"
-	  eval cmd=\"$cmd\"
-	  $show "$cmd"
-	  $run eval "$cmd" || exit $?
-	done
-	IFS="$save_ifs"
-      fi
-
-      if test -n "$gentop"; then
-	$show "${rm}r $gentop"
-	$run ${rm}r $gentop
-      fi
-
-      exit $EXIT_SUCCESS
-      ;;
-
-    prog)
-      case $host in
-	*cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
-      esac
-      if test -n "$vinfo"; then
-	$echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
-      fi
-
-      if test -n "$release"; then
-	$echo "$modename: warning: \`-release' is ignored for programs" 1>&2
-      fi
-
-      if test "$preload" = yes; then
-	if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
-	   test "$dlopen_self_static" = unknown; then
-	  $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
-	fi
-      fi
-
-      case $host in
-      *-*-rhapsody* | *-*-darwin1.[012])
-	# On Rhapsody replace the C library is the System framework
-	compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
-	finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
-	;;
-      esac
-
-      case $host in
-      *darwin*)
-        # Don't allow lazy linking, it breaks C++ global constructors
-        if test "$tagname" = CXX ; then
-        compile_command="$compile_command ${wl}-bind_at_load"
-        finalize_command="$finalize_command ${wl}-bind_at_load"
-        fi
-        ;;
-      esac
-
-
-      # move library search paths that coincide with paths to not yet
-      # installed libraries to the beginning of the library search list
-      new_libs=
-      for path in $notinst_path; do
-	case " $new_libs " in
-	*" -L$path/$objdir "*) ;;
-	*)
-	  case " $compile_deplibs " in
-	  *" -L$path/$objdir "*)
-	    new_libs="$new_libs -L$path/$objdir" ;;
-	  esac
-	  ;;
-	esac
-      done
-      for deplib in $compile_deplibs; do
-	case $deplib in
-	-L*)
-	  case " $new_libs " in
-	  *" $deplib "*) ;;
-	  *) new_libs="$new_libs $deplib" ;;
-	  esac
-	  ;;
-	*) new_libs="$new_libs $deplib" ;;
-	esac
-      done
-      compile_deplibs="$new_libs"
-
-
-      compile_command="$compile_command $compile_deplibs"
-      finalize_command="$finalize_command $finalize_deplibs"
-
-      if test -n "$rpath$xrpath"; then
-	# If the user specified any rpath flags, then add them.
-	for libdir in $rpath $xrpath; do
-	  # This is the magic to use -rpath.
-	  case "$finalize_rpath " in
-	  *" $libdir "*) ;;
-	  *) finalize_rpath="$finalize_rpath $libdir" ;;
-	  esac
-	done
-      fi
-
-      # Now hardcode the library paths
-      rpath=
-      hardcode_libdirs=
-      for libdir in $compile_rpath $finalize_rpath; do
-	if test -n "$hardcode_libdir_flag_spec"; then
-	  if test -n "$hardcode_libdir_separator"; then
-	    if test -z "$hardcode_libdirs"; then
-	      hardcode_libdirs="$libdir"
-	    else
-	      # Just accumulate the unique libdirs.
-	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
-	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
-		;;
-	      *)
-		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
-		;;
-	      esac
-	    fi
-	  else
-	    eval flag=\"$hardcode_libdir_flag_spec\"
-	    rpath="$rpath $flag"
-	  fi
-	elif test -n "$runpath_var"; then
-	  case "$perm_rpath " in
-	  *" $libdir "*) ;;
-	  *) perm_rpath="$perm_rpath $libdir" ;;
-	  esac
-	fi
-	case $host in
-	*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
-	  testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
-	  case :$dllsearchpath: in
-	  *":$libdir:"*) ;;
-	  *) dllsearchpath="$dllsearchpath:$libdir";;
-	  esac
-	  case :$dllsearchpath: in
-	  *":$testbindir:"*) ;;
-	  *) dllsearchpath="$dllsearchpath:$testbindir";;
-	  esac
-	  ;;
-	esac
-      done
-      # Substitute the hardcoded libdirs into the rpath.
-      if test -n "$hardcode_libdir_separator" &&
-	 test -n "$hardcode_libdirs"; then
-	libdir="$hardcode_libdirs"
-	eval rpath=\" $hardcode_libdir_flag_spec\"
-      fi
-      compile_rpath="$rpath"
-
-      rpath=
-      hardcode_libdirs=
-      for libdir in $finalize_rpath; do
-	if test -n "$hardcode_libdir_flag_spec"; then
-	  if test -n "$hardcode_libdir_separator"; then
-	    if test -z "$hardcode_libdirs"; then
-	      hardcode_libdirs="$libdir"
-	    else
-	      # Just accumulate the unique libdirs.
-	      case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
-	      *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
-		;;
-	      *)
-		hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
-		;;
-	      esac
-	    fi
-	  else
-	    eval flag=\"$hardcode_libdir_flag_spec\"
-	    rpath="$rpath $flag"
-	  fi
-	elif test -n "$runpath_var"; then
-	  case "$finalize_perm_rpath " in
-	  *" $libdir "*) ;;
-	  *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
-	  esac
-	fi
-      done
-      # Substitute the hardcoded libdirs into the rpath.
-      if test -n "$hardcode_libdir_separator" &&
-	 test -n "$hardcode_libdirs"; then
-	libdir="$hardcode_libdirs"
-	eval rpath=\" $hardcode_libdir_flag_spec\"
-      fi
-      finalize_rpath="$rpath"
-
-      if test -n "$libobjs" && test "$build_old_libs" = yes; then
-	# Transform all the library objects into standard objects.
-	compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-	finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-      fi
-
-      dlsyms=
-      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
-	if test -n "$NM" && test -n "$global_symbol_pipe"; then
-	  dlsyms="${outputname}S.c"
-	else
-	  $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
-	fi
-      fi
-
-      if test -n "$dlsyms"; then
-	case $dlsyms in
-	"") ;;
-	*.c)
-	  # Discover the nlist of each of the dlfiles.
-	  nlist="$output_objdir/${outputname}.nm"
-
-	  $show "$rm $nlist ${nlist}S ${nlist}T"
-	  $run $rm "$nlist" "${nlist}S" "${nlist}T"
-
-	  # Parse the name list into a source file.
-	  $show "creating $output_objdir/$dlsyms"
-
-	  test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
-/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
-/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
-
-#ifdef __cplusplus
-extern \"C\" {
-#endif
-
-/* Prevent the only kind of declaration conflicts we can make. */
-#define lt_preloaded_symbols some_other_symbol
-
-/* External symbol declarations for the compiler. */\
-"
-
-	  if test "$dlself" = yes; then
-	    $show "generating symbol list for \`$output'"
-
-	    test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
-
-	    # Add our own program objects to the symbol list.
-	    progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
-	    for arg in $progfiles; do
-	      $show "extracting global C symbols from \`$arg'"
-	      $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
-	    done
-
-	    if test -n "$exclude_expsyms"; then
-	      $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
-	      $run eval '$mv "$nlist"T "$nlist"'
-	    fi
-
-	    if test -n "$export_symbols_regex"; then
-	      $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
-	      $run eval '$mv "$nlist"T "$nlist"'
-	    fi
-
-	    # Prepare the list of exported symbols
-	    if test -z "$export_symbols"; then
-	      export_symbols="$output_objdir/$outputname.exp"
-	      $run $rm $export_symbols
-	      $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
-              case $host in
-              *cygwin* | *mingw* )
-	        $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
-		$run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
-                ;;
-              esac
-	    else
-	      $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
-	      $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
-	      $run eval 'mv "$nlist"T "$nlist"'
-              case $host in
-              *cygwin* | *mingw* )
-	        $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
-		$run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
-                ;;
-              esac
-	    fi
-	  fi
-
-	  for arg in $dlprefiles; do
-	    $show "extracting global C symbols from \`$arg'"
-	    name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
-	    $run eval '$echo ": $name " >> "$nlist"'
-	    $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
-	  done
-
-	  if test -z "$run"; then
-	    # Make sure we have at least an empty file.
-	    test -f "$nlist" || : > "$nlist"
-
-	    if test -n "$exclude_expsyms"; then
-	      $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
-	      $mv "$nlist"T "$nlist"
-	    fi
-
-	    # Try sorting and uniquifying the output.
-	    if grep -v "^: " < "$nlist" |
-		if sort -k 3 </dev/null >/dev/null 2>&1; then
-		  sort -k 3
-		else
-		  sort +2
-		fi |
-		uniq > "$nlist"S; then
-	      :
-	    else
-	      grep -v "^: " < "$nlist" > "$nlist"S
-	    fi
-
-	    if test -f "$nlist"S; then
-	      eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
-	    else
-	      $echo '/* NONE */' >> "$output_objdir/$dlsyms"
-	    fi
-
-	    $echo >> "$output_objdir/$dlsyms" "\
-
-#undef lt_preloaded_symbols
-
-#if defined (__STDC__) && __STDC__
-# define lt_ptr void *
-#else
-# define lt_ptr char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-"
-
-	    case $host in
-	    *cygwin* | *mingw* )
-	  $echo >> "$output_objdir/$dlsyms" "\
-/* DATA imports from DLLs on WIN32 can't be const, because
-   runtime relocations are performed -- see ld's documentation
-   on pseudo-relocs */
-struct {
-"
-	      ;;
-	    * )
-	  $echo >> "$output_objdir/$dlsyms" "\
-const struct {
-"
-	      ;;
-	    esac
-
-
-	  $echo >> "$output_objdir/$dlsyms" "\
-  const char *name;
-  lt_ptr address;
-}
-lt_preloaded_symbols[] =
-{\
-"
-
-	    eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
-
-	    $echo >> "$output_objdir/$dlsyms" "\
-  {0, (lt_ptr) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
-  return lt_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif\
-"
-	  fi
-
-	  pic_flag_for_symtable=
-	  case $host in
-	  # compiling the symbol table file with pic_flag works around
-	  # a FreeBSD bug that causes programs to crash when -lm is
-	  # linked before any other PIC object.  But we must not use
-	  # pic_flag when linking with -static.  The problem exists in
-	  # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
-	  *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
-	    case "$compile_command " in
-	    *" -static "*) ;;
-	    *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
-	    esac;;
-	  *-*-hpux*)
-	    case "$compile_command " in
-	    *" -static "*) ;;
-	    *) pic_flag_for_symtable=" $pic_flag";;
-	    esac
-	  esac
-
-	  # Now compile the dynamic symbol file.
-	  $show "(cd $output_objdir && $LTCC  $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
-	  $run eval '(cd $output_objdir && $LTCC  $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
-
-	  # Clean up the generated files.
-	  $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
-	  $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
-
-	  # Transform the symbol file into the correct name.
-          case $host in
-          *cygwin* | *mingw* )
-            if test -f "$output_objdir/${outputname}.def" ; then
-              compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
-              finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"`
-            else
-              compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-              finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-             fi
-            ;;
-          * )
-            compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-            finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-            ;;
-          esac
-	  ;;
-	*)
-	  $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
-	  exit $EXIT_FAILURE
-	  ;;
-	esac
-      else
-	# We keep going just in case the user didn't refer to
-	# lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
-	# really was required.
-
-	# Nullify the symbol file.
-	compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
-	finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
-      fi
-
-      if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
-	# Replace the output file specification.
-	compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
-	link_command="$compile_command$compile_rpath"
-
-	# We have no uninstalled library dependencies, so finalize right now.
-	$show "$link_command"
-	$run eval "$link_command"
-	exit_status=$?
-
-	# Delete the generated files.
-	if test -n "$dlsyms"; then
-	  $show "$rm $output_objdir/${outputname}S.${objext}"
-	  $run $rm "$output_objdir/${outputname}S.${objext}"
-	fi
-
-	exit $exit_status
-      fi
-
-      if test -n "$shlibpath_var"; then
-	# We should set the shlibpath_var
-	rpath=
-	for dir in $temp_rpath; do
-	  case $dir in
-	  [\\/]* | [A-Za-z]:[\\/]*)
-	    # Absolute path.
-	    rpath="$rpath$dir:"
-	    ;;
-	  *)
-	    # Relative path: add a thisdir entry.
-	    rpath="$rpath\$thisdir/$dir:"
-	    ;;
-	  esac
-	done
-	temp_rpath="$rpath"
-      fi
-
-      if test -n "$compile_shlibpath$finalize_shlibpath"; then
-	compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
-      fi
-      if test -n "$finalize_shlibpath"; then
-	finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
-      fi
-
-      compile_var=
-      finalize_var=
-      if test -n "$runpath_var"; then
-	if test -n "$perm_rpath"; then
-	  # We should set the runpath_var.
-	  rpath=
-	  for dir in $perm_rpath; do
-	    rpath="$rpath$dir:"
-	  done
-	  compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
-	fi
-	if test -n "$finalize_perm_rpath"; then
-	  # We should set the runpath_var.
-	  rpath=
-	  for dir in $finalize_perm_rpath; do
-	    rpath="$rpath$dir:"
-	  done
-	  finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
-	fi
-      fi
-
-      if test "$no_install" = yes; then
-	# We don't need to create a wrapper script.
-	link_command="$compile_var$compile_command$compile_rpath"
-	# Replace the output file specification.
-	link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
-	# Delete the old output file.
-	$run $rm $output
-	# Link the executable and exit
-	$show "$link_command"
-	$run eval "$link_command" || exit $?
-	exit $EXIT_SUCCESS
-      fi
-
-      if test "$hardcode_action" = relink; then
-	# Fast installation is not supported
-	link_command="$compile_var$compile_command$compile_rpath"
-	relink_command="$finalize_var$finalize_command$finalize_rpath"
-
-	$echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
-	$echo "$modename: \`$output' will be relinked during installation" 1>&2
-      else
-	if test "$fast_install" != no; then
-	  link_command="$finalize_var$compile_command$finalize_rpath"
-	  if test "$fast_install" = yes; then
-	    relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
-	  else
-	    # fast_install is set to needless
-	    relink_command=
-	  fi
-	else
-	  link_command="$compile_var$compile_command$compile_rpath"
-	  relink_command="$finalize_var$finalize_command$finalize_rpath"
-	fi
-      fi
-
-      # Replace the output file specification.
-      link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
-
-      # Delete the old output files.
-      $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
-
-      $show "$link_command"
-      $run eval "$link_command" || exit $?
-
-      # Now create the wrapper script.
-      $show "creating $output"
-
-      # Quote the relink command for shipping.
-      if test -n "$relink_command"; then
-	# Preserve any variables that may affect compiler behavior
-	for var in $variables_saved_for_relink; do
-	  if eval test -z \"\${$var+set}\"; then
-	    relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
-	  elif eval var_value=\$$var; test -z "$var_value"; then
-	    relink_command="$var=; export $var; $relink_command"
-	  else
-	    var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
-	    relink_command="$var=\"$var_value\"; export $var; $relink_command"
-	  fi
-	done
-	relink_command="(cd `pwd`; $relink_command)"
-	relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
-      fi
-
-      # Quote $echo for shipping.
-      if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
-	case $progpath in
-	[\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
-	*) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
-	esac
-	qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
-      else
-	qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
-      fi
-
-      # Only actually do things if our run command is non-null.
-      if test -z "$run"; then
-	# win32 will think the script is a binary if it has
-	# a .exe suffix, so we strip it off here.
-	case $output in
-	  *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
-	esac
-	# test for cygwin because mv fails w/o .exe extensions
-	case $host in
-	  *cygwin*)
-	    exeext=.exe
-	    outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
-	  *) exeext= ;;
-	esac
-	case $host in
-	  *cygwin* | *mingw* )
-            output_name=`basename $output`
-            output_path=`dirname $output`
-            cwrappersource="$output_path/$objdir/lt-$output_name.c"
-            cwrapper="$output_path/$output_name.exe"
-            $rm $cwrappersource $cwrapper
-            trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
-
-	    cat > $cwrappersource <<EOF
-
-/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
-   Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-
-   The $output program cannot be directly executed until all the libtool
-   libraries that it depends on are installed.
-
-   This wrapper executable should never be moved out of the build directory.
-   If it is, it will not operate correctly.
-
-   Currently, it simply execs the wrapper *script* "/bin/sh $output",
-   but could eventually absorb all of the scripts functionality and
-   exec $objdir/$outputname directly.
-*/
-EOF
-	    cat >> $cwrappersource<<"EOF"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/stat.h>
-
-#if defined(PATH_MAX)
-# define LT_PATHMAX PATH_MAX
-#elif defined(MAXPATHLEN)
-# define LT_PATHMAX MAXPATHLEN
-#else
-# define LT_PATHMAX 1024
-#endif
-
-#ifndef DIR_SEPARATOR
-# define DIR_SEPARATOR '/'
-# define PATH_SEPARATOR ':'
-#endif
-
-#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
-  defined (__OS2__)
-# define HAVE_DOS_BASED_FILE_SYSTEM
-# ifndef DIR_SEPARATOR_2
-#  define DIR_SEPARATOR_2 '\\'
-# endif
-# ifndef PATH_SEPARATOR_2
-#  define PATH_SEPARATOR_2 ';'
-# endif
-#endif
-
-#ifndef DIR_SEPARATOR_2
-# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
-#else /* DIR_SEPARATOR_2 */
-# define IS_DIR_SEPARATOR(ch) \
-        (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
-#endif /* DIR_SEPARATOR_2 */
-
-#ifndef PATH_SEPARATOR_2
-# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
-#else /* PATH_SEPARATOR_2 */
-# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
-#endif /* PATH_SEPARATOR_2 */
-
-#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
-#define XFREE(stale) do { \
-  if (stale) { free ((void *) stale); stale = 0; } \
-} while (0)
-
-/* -DDEBUG is fairly common in CFLAGS.  */
-#undef DEBUG
-#if defined DEBUGWRAPPER
-# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
-#else
-# define DEBUG(format, ...)
-#endif
-
-const char *program_name = NULL;
-
-void * xmalloc (size_t num);
-char * xstrdup (const char *string);
-const char * base_name (const char *name);
-char * find_executable(const char *wrapper);
-int    check_executable(const char *path);
-char * strendzap(char *str, const char *pat);
-void lt_fatal (const char *message, ...);
-
-int
-main (int argc, char *argv[])
-{
-  char **newargz;
-  int i;
-
-  program_name = (char *) xstrdup (base_name (argv[0]));
-  DEBUG("(main) argv[0]      : %s\n",argv[0]);
-  DEBUG("(main) program_name : %s\n",program_name);
-  newargz = XMALLOC(char *, argc+2);
-EOF
-
-            cat >> $cwrappersource <<EOF
-  newargz[0] = (char *) xstrdup("$SHELL");
-EOF
-
-            cat >> $cwrappersource <<"EOF"
-  newargz[1] = find_executable(argv[0]);
-  if (newargz[1] == NULL)
-    lt_fatal("Couldn't find %s", argv[0]);
-  DEBUG("(main) found exe at : %s\n",newargz[1]);
-  /* we know the script has the same name, without the .exe */
-  /* so make sure newargz[1] doesn't end in .exe */
-  strendzap(newargz[1],".exe");
-  for (i = 1; i < argc; i++)
-    newargz[i+1] = xstrdup(argv[i]);
-  newargz[argc+1] = NULL;
-
-  for (i=0; i<argc+1; i++)
-  {
-    DEBUG("(main) newargz[%d]   : %s\n",i,newargz[i]);
-    ;
-  }
-
-EOF
-
-            case $host_os in
-              mingw*)
-                cat >> $cwrappersource <<EOF
-  execv("$SHELL",(char const **)newargz);
-EOF
-              ;;
-              *)
-                cat >> $cwrappersource <<EOF
-  execv("$SHELL",newargz);
-EOF
-              ;;
-            esac
-
-            cat >> $cwrappersource <<"EOF"
-  return 127;
-}
-
-void *
-xmalloc (size_t num)
-{
-  void * p = (void *) malloc (num);
-  if (!p)
-    lt_fatal ("Memory exhausted");
-
-  return p;
-}
-
-char *
-xstrdup (const char *string)
-{
-  return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
-;
-}
-
-const char *
-base_name (const char *name)
-{
-  const char *base;
-
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
-  /* Skip over the disk name in MSDOS pathnames. */
-  if (isalpha ((unsigned char)name[0]) && name[1] == ':')
-    name += 2;
-#endif
-
-  for (base = name; *name; name++)
-    if (IS_DIR_SEPARATOR (*name))
-      base = name + 1;
-  return base;
-}
-
-int
-check_executable(const char * path)
-{
-  struct stat st;
-
-  DEBUG("(check_executable)  : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
-  if ((!path) || (!*path))
-    return 0;
-
-  if ((stat (path, &st) >= 0) &&
-      (
-        /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
-#if defined (S_IXOTH)
-       ((st.st_mode & S_IXOTH) == S_IXOTH) ||
-#endif
-#if defined (S_IXGRP)
-       ((st.st_mode & S_IXGRP) == S_IXGRP) ||
-#endif
-       ((st.st_mode & S_IXUSR) == S_IXUSR))
-      )
-    return 1;
-  else
-    return 0;
-}
-
-/* Searches for the full path of the wrapper.  Returns
-   newly allocated full path name if found, NULL otherwise */
-char *
-find_executable (const char* wrapper)
-{
-  int has_slash = 0;
-  const char* p;
-  const char* p_next;
-  /* static buffer for getcwd */
-  char tmp[LT_PATHMAX + 1];
-  int tmp_len;
-  char* concat_name;
-
-  DEBUG("(find_executable)  : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
-
-  if ((wrapper == NULL) || (*wrapper == '\0'))
-    return NULL;
-
-  /* Absolute path? */
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
-  if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
-  {
-    concat_name = xstrdup (wrapper);
-    if (check_executable(concat_name))
-      return concat_name;
-    XFREE(concat_name);
-  }
-  else
-  {
-#endif
-    if (IS_DIR_SEPARATOR (wrapper[0]))
-    {
-      concat_name = xstrdup (wrapper);
-      if (check_executable(concat_name))
-        return concat_name;
-      XFREE(concat_name);
-    }
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
-  }
-#endif
-
-  for (p = wrapper; *p; p++)
-    if (*p == '/')
-    {
-      has_slash = 1;
-      break;
-    }
-  if (!has_slash)
-  {
-    /* no slashes; search PATH */
-    const char* path = getenv ("PATH");
-    if (path != NULL)
-    {
-      for (p = path; *p; p = p_next)
-      {
-        const char* q;
-        size_t p_len;
-        for (q = p; *q; q++)
-          if (IS_PATH_SEPARATOR(*q))
-            break;
-        p_len = q - p;
-        p_next = (*q == '\0' ? q : q + 1);
-        if (p_len == 0)
-        {
-          /* empty path: current directory */
-          if (getcwd (tmp, LT_PATHMAX) == NULL)
-            lt_fatal ("getcwd failed");
-          tmp_len = strlen(tmp);
-          concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
-          memcpy (concat_name, tmp, tmp_len);
-          concat_name[tmp_len] = '/';
-          strcpy (concat_name + tmp_len + 1, wrapper);
-        }
-        else
-        {
-          concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
-          memcpy (concat_name, p, p_len);
-          concat_name[p_len] = '/';
-          strcpy (concat_name + p_len + 1, wrapper);
-        }
-        if (check_executable(concat_name))
-          return concat_name;
-        XFREE(concat_name);
-      }
-    }
-    /* not found in PATH; assume curdir */
-  }
-  /* Relative path | not found in path: prepend cwd */
-  if (getcwd (tmp, LT_PATHMAX) == NULL)
-    lt_fatal ("getcwd failed");
-  tmp_len = strlen(tmp);
-  concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
-  memcpy (concat_name, tmp, tmp_len);
-  concat_name[tmp_len] = '/';
-  strcpy (concat_name + tmp_len + 1, wrapper);
-
-  if (check_executable(concat_name))
-    return concat_name;
-  XFREE(concat_name);
-  return NULL;
-}
-
-char *
-strendzap(char *str, const char *pat)
-{
-  size_t len, patlen;
-
-  assert(str != NULL);
-  assert(pat != NULL);
-
-  len = strlen(str);
-  patlen = strlen(pat);
-
-  if (patlen <= len)
-  {
-    str += len - patlen;
-    if (strcmp(str, pat) == 0)
-      *str = '\0';
-  }
-  return str;
-}
-
-static void
-lt_error_core (int exit_status, const char * mode,
-          const char * message, va_list ap)
-{
-  fprintf (stderr, "%s: %s: ", program_name, mode);
-  vfprintf (stderr, message, ap);
-  fprintf (stderr, ".\n");
-
-  if (exit_status >= 0)
-    exit (exit_status);
-}
-
-void
-lt_fatal (const char *message, ...)
-{
-  va_list ap;
-  va_start (ap, message);
-  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
-  va_end (ap);
-}
-EOF
-          # we should really use a build-platform specific compiler
-          # here, but OTOH, the wrappers (shell script and this C one)
-          # are only useful if you want to execute the "real" binary.
-          # Since the "real" binary is built for $host, then this
-          # wrapper might as well be built for $host, too.
-          $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
-          ;;
-        esac
-        $rm $output
-        trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
-
-	$echo > $output "\
-#! $SHELL
-
-# $output - temporary wrapper script for $objdir/$outputname
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# The $output program cannot be directly executed until all the libtool
-# libraries that it depends on are installed.
-#
-# This wrapper script should never be moved out of the build directory.
-# If it is, it will not operate correctly.
-
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='${SED} -e 1s/^X//'
-sed_quote_subst='$sed_quote_subst'
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-relink_command=\"$relink_command\"
-
-# This environment variable determines our operation mode.
-if test \"\$libtool_install_magic\" = \"$magic\"; then
-  # install mode needs the following variable:
-  notinst_deplibs='$notinst_deplibs'
-else
-  # When we are sourced in execute mode, \$file and \$echo are already set.
-  if test \"\$libtool_execute_magic\" != \"$magic\"; then
-    echo=\"$qecho\"
-    file=\"\$0\"
-    # Make sure echo works.
-    if test \"X\$1\" = X--no-reexec; then
-      # Discard the --no-reexec flag, and continue.
-      shift
-    elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
-      # Yippee, \$echo works!
-      :
-    else
-      # Restart under the correct shell, and then maybe \$echo will work.
-      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
-    fi
-  fi\
-"
-	$echo >> $output "\
-
-  # Find the directory that this script lives in.
-  thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
-  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
-
-  # Follow symbolic links until we get to the real thisdir.
-  file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
-  while test -n \"\$file\"; do
-    destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
-
-    # If there was a directory component, then change thisdir.
-    if test \"x\$destdir\" != \"x\$file\"; then
-      case \"\$destdir\" in
-      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
-      *) thisdir=\"\$thisdir/\$destdir\" ;;
-      esac
-    fi
-
-    file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
-    file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
-  done
-
-  # Try to get the absolute directory name.
-  absdir=\`cd \"\$thisdir\" && pwd\`
-  test -n \"\$absdir\" && thisdir=\"\$absdir\"
-"
-
-	if test "$fast_install" = yes; then
-	  $echo >> $output "\
-  program=lt-'$outputname'$exeext
-  progdir=\"\$thisdir/$objdir\"
-
-  if test ! -f \"\$progdir/\$program\" || \\
-     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
-       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
-
-    file=\"\$\$-\$program\"
-
-    if test ! -d \"\$progdir\"; then
-      $mkdir \"\$progdir\"
-    else
-      $rm \"\$progdir/\$file\"
-    fi"
-
-	  $echo >> $output "\
-
-    # relink executable if necessary
-    if test -n \"\$relink_command\"; then
-      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
-      else
-	$echo \"\$relink_command_output\" >&2
-	$rm \"\$progdir/\$file\"
-	exit $EXIT_FAILURE
-      fi
-    fi
-
-    $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
-    { $rm \"\$progdir/\$program\";
-      $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
-    $rm \"\$progdir/\$file\"
-  fi"
-	else
-	  $echo >> $output "\
-  program='$outputname'
-  progdir=\"\$thisdir/$objdir\"
-"
-	fi
-
-	$echo >> $output "\
-
-  if test -f \"\$progdir/\$program\"; then"
-
-	# Export our shlibpath_var if we have one.
-	if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
-	  $echo >> $output "\
-    # Add our own library path to $shlibpath_var
-    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
-
-    # Some systems cannot cope with colon-terminated $shlibpath_var
-    # The second colon is a workaround for a bug in BeOS R4 sed
-    $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
-
-    export $shlibpath_var
-"
-	fi
-
-	# fixup the dll searchpath if we need to.
-	if test -n "$dllsearchpath"; then
-	  $echo >> $output "\
-    # Add the dll search path components to the executable PATH
-    PATH=$dllsearchpath:\$PATH
-"
-	fi
-
-	$echo >> $output "\
-    if test \"\$libtool_execute_magic\" != \"$magic\"; then
-      # Run the actual program with our arguments.
-"
-	case $host in
-	# Backslashes separate directories on plain windows
-	*-*-mingw | *-*-os2*)
-	  $echo >> $output "\
-      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
-"
-	  ;;
-
-	*)
-	  $echo >> $output "\
-      exec \"\$progdir/\$program\" \${1+\"\$@\"}
-"
-	  ;;
-	esac
-	$echo >> $output "\
-      \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
-      exit $EXIT_FAILURE
-    fi
-  else
-    # The program doesn't exist.
-    \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
-    \$echo \"This script is just a wrapper for \$program.\" 1>&2
-    $echo \"See the $PACKAGE documentation for more information.\" 1>&2
-    exit $EXIT_FAILURE
-  fi
-fi\
-"
-	chmod +x $output
-      fi
-      exit $EXIT_SUCCESS
-      ;;
-    esac
-
-    # See if we need to build an old-fashioned archive.
-    for oldlib in $oldlibs; do
-
-      if test "$build_libtool_libs" = convenience; then
-	oldobjs="$libobjs_save"
-	addlibs="$convenience"
-	build_libtool_libs=no
-      else
-	if test "$build_libtool_libs" = module; then
-	  oldobjs="$libobjs_save"
-	  build_libtool_libs=no
-	else
-	  oldobjs="$old_deplibs $non_pic_objects"
-	fi
-	addlibs="$old_convenience"
-      fi
-
-      if test -n "$addlibs"; then
-	gentop="$output_objdir/${outputname}x"
-	generated="$generated $gentop"
-
-	func_extract_archives $gentop $addlibs
-	oldobjs="$oldobjs $func_extract_archives_result"
-      fi
-
-      # Do each command in the archive commands.
-      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
-       cmds=$old_archive_from_new_cmds
-      else
-	# POSIX demands no paths to be encoded in archives.  We have
-	# to avoid creating archives with duplicate basenames if we
-	# might have to extract them afterwards, e.g., when creating a
-	# static archive out of a convenience library, or when linking
-	# the entirety of a libtool archive into another (currently
-	# not supported by libtool).
-	if (for obj in $oldobjs
-	    do
-	      $echo "X$obj" | $Xsed -e 's%^.*/%%'
-	    done | sort | sort -uc >/dev/null 2>&1); then
-	  :
-	else
-	  $echo "copying selected object files to avoid basename conflicts..."
-
-	  if test -z "$gentop"; then
-	    gentop="$output_objdir/${outputname}x"
-	    generated="$generated $gentop"
-
-	    $show "${rm}r $gentop"
-	    $run ${rm}r "$gentop"
-	    $show "$mkdir $gentop"
-	    $run $mkdir "$gentop"
-	    exit_status=$?
-	    if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
-	      exit $exit_status
-	    fi
-	  fi
-
-	  save_oldobjs=$oldobjs
-	  oldobjs=
-	  counter=1
-	  for obj in $save_oldobjs
-	  do
-	    objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
-	    case " $oldobjs " in
-	    " ") oldobjs=$obj ;;
-	    *[\ /]"$objbase "*)
-	      while :; do
-		# Make sure we don't pick an alternate name that also
-		# overlaps.
-		newobj=lt$counter-$objbase
-		counter=`expr $counter + 1`
-		case " $oldobjs " in
-		*[\ /]"$newobj "*) ;;
-		*) if test ! -f "$gentop/$newobj"; then break; fi ;;
-		esac
-	      done
-	      $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
-	      $run ln "$obj" "$gentop/$newobj" ||
-	      $run cp "$obj" "$gentop/$newobj"
-	      oldobjs="$oldobjs $gentop/$newobj"
-	      ;;
-	    *) oldobjs="$oldobjs $obj" ;;
-	    esac
-	  done
-	fi
-
-	eval cmds=\"$old_archive_cmds\"
-
-	if len=`expr "X$cmds" : ".*"` &&
-	     test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
-	  cmds=$old_archive_cmds
-	else
-	  # the command line is too long to link in one step, link in parts
-	  $echo "using piecewise archive linking..."
-	  save_RANLIB=$RANLIB
-	  RANLIB=:
-	  objlist=
-	  concat_cmds=
-	  save_oldobjs=$oldobjs
-
-	  # Is there a better way of finding the last object in the list?
-	  for obj in $save_oldobjs
-	  do
-	    last_oldobj=$obj
-	  done
-	  for obj in $save_oldobjs
-	  do
-	    oldobjs="$objlist $obj"
-	    objlist="$objlist $obj"
-	    eval test_cmds=\"$old_archive_cmds\"
-	    if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
-	       test "$len" -le "$max_cmd_len"; then
-	      :
-	    else
-	      # the above command should be used before it gets too long
-	      oldobjs=$objlist
-	      if test "$obj" = "$last_oldobj" ; then
-	        RANLIB=$save_RANLIB
-	      fi
-	      test -z "$concat_cmds" || concat_cmds=$concat_cmds~
-	      eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
-	      objlist=
-	    fi
-	  done
-	  RANLIB=$save_RANLIB
-	  oldobjs=$objlist
-	  if test "X$oldobjs" = "X" ; then
-	    eval cmds=\"\$concat_cmds\"
-	  else
-	    eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
-	  fi
-	fi
-      fi
-      save_ifs="$IFS"; IFS='~'
-      for cmd in $cmds; do
-        eval cmd=\"$cmd\"
-	IFS="$save_ifs"
-	$show "$cmd"
-	$run eval "$cmd" || exit $?
-      done
-      IFS="$save_ifs"
-    done
-
-    if test -n "$generated"; then
-      $show "${rm}r$generated"
-      $run ${rm}r$generated
-    fi
-
-    # Now create the libtool archive.
-    case $output in
-    *.la)
-      old_library=
-      test "$build_old_libs" = yes && old_library="$libname.$libext"
-      $show "creating $output"
-
-      # Preserve any variables that may affect compiler behavior
-      for var in $variables_saved_for_relink; do
-	if eval test -z \"\${$var+set}\"; then
-	  relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
-	elif eval var_value=\$$var; test -z "$var_value"; then
-	  relink_command="$var=; export $var; $relink_command"
-	else
-	  var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
-	  relink_command="$var=\"$var_value\"; export $var; $relink_command"
-	fi
-      done
-      # Quote the link command for shipping.
-      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
-      relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
-      if test "$hardcode_automatic" = yes ; then
-	relink_command=
-      fi
-
-
-      # Only create the output if not a dry run.
-      if test -z "$run"; then
-	for installed in no yes; do
-	  if test "$installed" = yes; then
-	    if test -z "$install_libdir"; then
-	      break
-	    fi
-	    output="$output_objdir/$outputname"i
-	    # Replace all uninstalled libtool libraries with the installed ones
-	    newdependency_libs=
-	    for deplib in $dependency_libs; do
-	      case $deplib in
-	      *.la)
-		name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
-		eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
-		if test -z "$libdir"; then
-		  $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
-		  exit $EXIT_FAILURE
-		fi
-		newdependency_libs="$newdependency_libs $libdir/$name"
-		;;
-	      *) newdependency_libs="$newdependency_libs $deplib" ;;
-	      esac
-	    done
-	    dependency_libs="$newdependency_libs"
-	    newdlfiles=
-	    for lib in $dlfiles; do
-	      name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
-	      eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
-	      if test -z "$libdir"; then
-		$echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-		exit $EXIT_FAILURE
-	      fi
-	      newdlfiles="$newdlfiles $libdir/$name"
-	    done
-	    dlfiles="$newdlfiles"
-	    newdlprefiles=
-	    for lib in $dlprefiles; do
-	      name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
-	      eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
-	      if test -z "$libdir"; then
-		$echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-		exit $EXIT_FAILURE
-	      fi
-	      newdlprefiles="$newdlprefiles $libdir/$name"
-	    done
-	    dlprefiles="$newdlprefiles"
-	  else
-	    newdlfiles=
-	    for lib in $dlfiles; do
-	      case $lib in
-		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
-		*) abs=`pwd`"/$lib" ;;
-	      esac
-	      newdlfiles="$newdlfiles $abs"
-	    done
-	    dlfiles="$newdlfiles"
-	    newdlprefiles=
-	    for lib in $dlprefiles; do
-	      case $lib in
-		[\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
-		*) abs=`pwd`"/$lib" ;;
-	      esac
-	      newdlprefiles="$newdlprefiles $abs"
-	    done
-	    dlprefiles="$newdlprefiles"
-	  fi
-	  $rm $output
-	  # place dlname in correct position for cygwin
-	  tdlname=$dlname
-	  case $host,$output,$installed,$module,$dlname in
-	    *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
-	  esac
-	  $echo > $output "\
-# $outputname - a libtool library file
-# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
-#
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# The name that we can dlopen(3).
-dlname='$tdlname'
-
-# Names of this library.
-library_names='$library_names'
-
-# The name of the static archive.
-old_library='$old_library'
-
-# Libraries that this one depends upon.
-dependency_libs='$dependency_libs'
-
-# Version information for $libname.
-current=$current
-age=$age
-revision=$revision
-
-# Is this an already installed library?
-installed=$installed
-
-# Should we warn about portability when linking against -modules?
-shouldnotlink=$module
-
-# Files to dlopen/dlpreopen
-dlopen='$dlfiles'
-dlpreopen='$dlprefiles'
-
-# Directory that this library needs to be installed in:
-libdir='$install_libdir'"
-	  if test "$installed" = no && test "$need_relink" = yes; then
-	    $echo >> $output "\
-relink_command=\"$relink_command\""
-	  fi
-	done
-      fi
-
-      # Do a symbolic link so that the libtool archive can be found in
-      # LD_LIBRARY_PATH before the program is installed.
-      $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
-      $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
-      ;;
-    esac
-    exit $EXIT_SUCCESS
-    ;;
-
-  # libtool install mode
-  install)
-    modename="$modename: install"
-
-    # There may be an optional sh(1) argument at the beginning of
-    # install_prog (especially on Windows NT).
-    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
-       # Allow the use of GNU shtool's install command.
-       $echo "X$nonopt" | grep shtool > /dev/null; then
-      # Aesthetically quote it.
-      arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
-      case $arg in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	arg="\"$arg\""
-	;;
-      esac
-      install_prog="$arg "
-      arg="$1"
-      shift
-    else
-      install_prog=
-      arg=$nonopt
-    fi
-
-    # The real first argument should be the name of the installation program.
-    # Aesthetically quote it.
-    arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-    case $arg in
-    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-      arg="\"$arg\""
-      ;;
-    esac
-    install_prog="$install_prog$arg"
-
-    # We need to accept at least all the BSD install flags.
-    dest=
-    files=
-    opts=
-    prev=
-    install_type=
-    isdir=no
-    stripme=
-    for arg
-    do
-      if test -n "$dest"; then
-	files="$files $dest"
-	dest=$arg
-	continue
-      fi
-
-      case $arg in
-      -d) isdir=yes ;;
-      -f) 
-      	case " $install_prog " in
-	*[\\\ /]cp\ *) ;;
-	*) prev=$arg ;;
-	esac
-	;;
-      -g | -m | -o) prev=$arg ;;
-      -s)
-	stripme=" -s"
-	continue
-	;;
-      -*)
-	;;
-      *)
-	# If the previous option needed an argument, then skip it.
-	if test -n "$prev"; then
-	  prev=
-	else
-	  dest=$arg
-	  continue
-	fi
-	;;
-      esac
-
-      # Aesthetically quote the argument.
-      arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
-      case $arg in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \	]*|*]*|"")
-	arg="\"$arg\""
-	;;
-      esac
-      install_prog="$install_prog $arg"
-    done
-
-    if test -z "$install_prog"; then
-      $echo "$modename: you must specify an install program" 1>&2
-      $echo "$help" 1>&2
-      exit $EXIT_FAILURE
-    fi
-
-    if test -n "$prev"; then
-      $echo "$modename: the \`$prev' option requires an argument" 1>&2
-      $echo "$help" 1>&2
-      exit $EXIT_FAILURE
-    fi
-
-    if test -z "$files"; then
-      if test -z "$dest"; then
-	$echo "$modename: no file or destination specified" 1>&2
-      else
-	$echo "$modename: you must specify a destination" 1>&2
-      fi
-      $echo "$help" 1>&2
-      exit $EXIT_FAILURE
-    fi
-
-    # Strip any trailing slash from the destination.
-    dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
-
-    # Check to see that the destination is a directory.
-    test -d "$dest" && isdir=yes
-    if test "$isdir" = yes; then
-      destdir="$dest"
-      destname=
-    else
-      destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
-      test "X$destdir" = "X$dest" && destdir=.
-      destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
-
-      # Not a directory, so check to see that there is only one file specified.
-      set dummy $files
-      if test "$#" -gt 2; then
-	$echo "$modename: \`$dest' is not a directory" 1>&2
-	$echo "$help" 1>&2
-	exit $EXIT_FAILURE
-      fi
-    fi
-    case $destdir in
-    [\\/]* | [A-Za-z]:[\\/]*) ;;
-    *)
-      for file in $files; do
-	case $file in
-	*.lo) ;;
-	*)
-	  $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
-	  $echo "$help" 1>&2
-	  exit $EXIT_FAILURE
-	  ;;
-	esac
-      done
-      ;;
-    esac
-
-    # This variable tells wrapper scripts just to set variables rather
-    # than running their programs.
-    libtool_install_magic="$magic"
-
-    staticlibs=
-    future_libdirs=
-    current_libdirs=
-    for file in $files; do
-
-      # Do each installation.
-      case $file in
-      *.$libext)
-	# Do the static libraries later.
-	staticlibs="$staticlibs $file"
-	;;
-
-      *.la)
-	# Check to see that this really is a libtool archive.
-	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-	else
-	  $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
-	  $echo "$help" 1>&2
-	  exit $EXIT_FAILURE
-	fi
-
-	library_names=
-	old_library=
-	relink_command=
-	# If there is no directory component, then add one.
-	case $file in
-	*/* | *\\*) . $file ;;
-	*) . ./$file ;;
-	esac
-
-	# Add the libdir to current_libdirs if it is the destination.
-	if test "X$destdir" = "X$libdir"; then
-	  case "$current_libdirs " in
-	  *" $libdir "*) ;;
-	  *) current_libdirs="$current_libdirs $libdir" ;;
-	  esac
-	else
-	  # Note the libdir as a future libdir.
-	  case "$future_libdirs " in
-	  *" $libdir "*) ;;
-	  *) future_libdirs="$future_libdirs $libdir" ;;
-	  esac
-	fi
-
-	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
-	test "X$dir" = "X$file/" && dir=
-	dir="$dir$objdir"
-
-	if test -n "$relink_command"; then
-	  # Determine the prefix the user has applied to our future dir.
-	  inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
-
-	  # Don't allow the user to place us outside of our expected
-	  # location b/c this prevents finding dependent libraries that
-	  # are installed to the same prefix.
-	  # At present, this check doesn't affect windows .dll's that
-	  # are installed into $libdir/../bin (currently, that works fine)
-	  # but it's something to keep an eye on.
-	  if test "$inst_prefix_dir" = "$destdir"; then
-	    $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
-	    exit $EXIT_FAILURE
-	  fi
-
-	  if test -n "$inst_prefix_dir"; then
-	    # Stick the inst_prefix_dir data into the link command.
-	    relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
-	  else
-	    relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
-	  fi
-
-	  $echo "$modename: warning: relinking \`$file'" 1>&2
-	  $show "$relink_command"
-	  if $run eval "$relink_command"; then :
-	  else
-	    $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
-	    exit $EXIT_FAILURE
-	  fi
-	fi
-
-	# See the names of the shared library.
-	set dummy $library_names
-	if test -n "$2"; then
-	  realname="$2"
-	  shift
-	  shift
-
-	  srcname="$realname"
-	  test -n "$relink_command" && srcname="$realname"T
-
-	  # Install the shared library and build the symlinks.
-	  $show "$install_prog $dir/$srcname $destdir/$realname"
-	  $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
-	  if test -n "$stripme" && test -n "$striplib"; then
-	    $show "$striplib $destdir/$realname"
-	    $run eval "$striplib $destdir/$realname" || exit $?
-	  fi
-
-	  if test "$#" -gt 0; then
-	    # Delete the old symlinks, and create new ones.
-	    # Try `ln -sf' first, because the `ln' binary might depend on
-	    # the symlink we replace!  Solaris /bin/ln does not understand -f,
-	    # so we also need to try rm && ln -s.
-	    for linkname
-	    do
-	      if test "$linkname" != "$realname"; then
-                $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
-                $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
-	      fi
-	    done
-	  fi
-
-	  # Do each command in the postinstall commands.
-	  lib="$destdir/$realname"
-	  cmds=$postinstall_cmds
-	  save_ifs="$IFS"; IFS='~'
-	  for cmd in $cmds; do
-	    IFS="$save_ifs"
-	    eval cmd=\"$cmd\"
-	    $show "$cmd"
-	    $run eval "$cmd" || {
-	      lt_exit=$?
-
-	      # Restore the uninstalled library and exit
-	      if test "$mode" = relink; then
-		$run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
-	      fi
-
-	      exit $lt_exit
-	    }
-	  done
-	  IFS="$save_ifs"
-	fi
-
-	# Install the pseudo-library for information purposes.
-	name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-	instname="$dir/$name"i
-	$show "$install_prog $instname $destdir/$name"
-	$run eval "$install_prog $instname $destdir/$name" || exit $?
-
-	# Maybe install the static library, too.
-	test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
-	;;
-
-      *.lo)
-	# Install (i.e. copy) a libtool object.
-
-	# Figure out destination file name, if it wasn't already specified.
-	if test -n "$destname"; then
-	  destfile="$destdir/$destname"
-	else
-	  destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-	  destfile="$destdir/$destfile"
-	fi
-
-	# Deduce the name of the destination old-style object file.
-	case $destfile in
-	*.lo)
-	  staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
-	  ;;
-	*.$objext)
-	  staticdest="$destfile"
-	  destfile=
-	  ;;
-	*)
-	  $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
-	  $echo "$help" 1>&2
-	  exit $EXIT_FAILURE
-	  ;;
-	esac
-
-	# Install the libtool object if requested.
-	if test -n "$destfile"; then
-	  $show "$install_prog $file $destfile"
-	  $run eval "$install_prog $file $destfile" || exit $?
-	fi
-
-	# Install the old object if enabled.
-	if test "$build_old_libs" = yes; then
-	  # Deduce the name of the old-style object file.
-	  staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
-
-	  $show "$install_prog $staticobj $staticdest"
-	  $run eval "$install_prog \$staticobj \$staticdest" || exit $?
-	fi
-	exit $EXIT_SUCCESS
-	;;
-
-      *)
-	# Figure out destination file name, if it wasn't already specified.
-	if test -n "$destname"; then
-	  destfile="$destdir/$destname"
-	else
-	  destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-	  destfile="$destdir/$destfile"
-	fi
-
-	# If the file is missing, and there is a .exe on the end, strip it
-	# because it is most likely a libtool script we actually want to
-	# install
-	stripped_ext=""
-	case $file in
-	  *.exe)
-	    if test ! -f "$file"; then
-	      file=`$echo $file|${SED} 's,.exe$,,'`
-	      stripped_ext=".exe"
-	    fi
-	    ;;
-	esac
-
-	# Do a test to see if this is really a libtool program.
-	case $host in
-	*cygwin*|*mingw*)
-	    wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
-	    ;;
-	*)
-	    wrapper=$file
-	    ;;
-	esac
-	if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
-	  notinst_deplibs=
-	  relink_command=
-
-	  # Note that it is not necessary on cygwin/mingw to append a dot to
-	  # foo even if both foo and FILE.exe exist: automatic-append-.exe
-	  # behavior happens only for exec(3), not for open(2)!  Also, sourcing
-	  # `FILE.' does not work on cygwin managed mounts.
-	  #
-	  # If there is no directory component, then add one.
-	  case $wrapper in
-	  */* | *\\*) . ${wrapper} ;;
-	  *) . ./${wrapper} ;;
-	  esac
-
-	  # Check the variables that should have been set.
-	  if test -z "$notinst_deplibs"; then
-	    $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
-	    exit $EXIT_FAILURE
-	  fi
-
-	  finalize=yes
-	  for lib in $notinst_deplibs; do
-	    # Check to see that each library is installed.
-	    libdir=
-	    if test -f "$lib"; then
-	      # If there is no directory component, then add one.
-	      case $lib in
-	      */* | *\\*) . $lib ;;
-	      *) . ./$lib ;;
-	      esac
-	    fi
-	    libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
-	    if test -n "$libdir" && test ! -f "$libfile"; then
-	      $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
-	      finalize=no
-	    fi
-	  done
-
-	  relink_command=
-	  # Note that it is not necessary on cygwin/mingw to append a dot to
-	  # foo even if both foo and FILE.exe exist: automatic-append-.exe
-	  # behavior happens only for exec(3), not for open(2)!  Also, sourcing
-	  # `FILE.' does not work on cygwin managed mounts.
-	  #
-	  # If there is no directory component, then add one.
-	  case $wrapper in
-	  */* | *\\*) . ${wrapper} ;;
-	  *) . ./${wrapper} ;;
-	  esac
-
-	  outputname=
-	  if test "$fast_install" = no && test -n "$relink_command"; then
-	    if test "$finalize" = yes && test -z "$run"; then
-	      tmpdir=`func_mktempdir`
-	      file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
-	      outputname="$tmpdir/$file"
-	      # Replace the output file specification.
-	      relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
-
-	      $show "$relink_command"
-	      if $run eval "$relink_command"; then :
-	      else
-		$echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
-		${rm}r "$tmpdir"
-		continue
-	      fi
-	      file="$outputname"
-	    else
-	      $echo "$modename: warning: cannot relink \`$file'" 1>&2
-	    fi
-	  else
-	    # Install the binary that we compiled earlier.
-	    file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
-	  fi
-	fi
-
-	# remove .exe since cygwin /usr/bin/install will append another
-	# one anyway 
-	case $install_prog,$host in
-	*/usr/bin/install*,*cygwin*)
-	  case $file:$destfile in
-	  *.exe:*.exe)
-	    # this is ok
-	    ;;
-	  *.exe:*)
-	    destfile=$destfile.exe
-	    ;;
-	  *:*.exe)
-	    destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
-	    ;;
-	  esac
-	  ;;
-	esac
-	$show "$install_prog$stripme $file $destfile"
-	$run eval "$install_prog\$stripme \$file \$destfile" || exit $?
-	test -n "$outputname" && ${rm}r "$tmpdir"
-	;;
-      esac
-    done
-
-    for file in $staticlibs; do
-      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-
-      # Set up the ranlib parameters.
-      oldlib="$destdir/$name"
-
-      $show "$install_prog $file $oldlib"
-      $run eval "$install_prog \$file \$oldlib" || exit $?
-
-      if test -n "$stripme" && test -n "$old_striplib"; then
-	$show "$old_striplib $oldlib"
-	$run eval "$old_striplib $oldlib" || exit $?
-      fi
-
-      # Do each command in the postinstall commands.
-      cmds=$old_postinstall_cmds
-      save_ifs="$IFS"; IFS='~'
-      for cmd in $cmds; do
-	IFS="$save_ifs"
-	eval cmd=\"$cmd\"
-	$show "$cmd"
-	$run eval "$cmd" || exit $?
-      done
-      IFS="$save_ifs"
-    done
-
-    if test -n "$future_libdirs"; then
-      $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
-    fi
-
-    if test -n "$current_libdirs"; then
-      # Maybe just do a dry run.
-      test -n "$run" && current_libdirs=" -n$current_libdirs"
-      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
-    else
-      exit $EXIT_SUCCESS
-    fi
-    ;;
-
-  # libtool finish mode
-  finish)
-    modename="$modename: finish"
-    libdirs="$nonopt"
-    admincmds=
-
-    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
-      for dir
-      do
-	libdirs="$libdirs $dir"
-      done
-
-      for libdir in $libdirs; do
-	if test -n "$finish_cmds"; then
-	  # Do each command in the finish commands.
-	  cmds=$finish_cmds
-	  save_ifs="$IFS"; IFS='~'
-	  for cmd in $cmds; do
-	    IFS="$save_ifs"
-	    eval cmd=\"$cmd\"
-	    $show "$cmd"
-	    $run eval "$cmd" || admincmds="$admincmds
-       $cmd"
-	  done
-	  IFS="$save_ifs"
-	fi
-	if test -n "$finish_eval"; then
-	  # Do the single finish_eval.
-	  eval cmds=\"$finish_eval\"
-	  $run eval "$cmds" || admincmds="$admincmds
-       $cmds"
-	fi
-      done
-    fi
-
-    # Exit here if they wanted silent mode.
-    test "$show" = : && exit $EXIT_SUCCESS
-
-    $echo "X----------------------------------------------------------------------" | $Xsed
-    $echo "Libraries have been installed in:"
-    for libdir in $libdirs; do
-      $echo "   $libdir"
-    done
-    $echo
-    $echo "If you ever happen to want to link against installed libraries"
-    $echo "in a given directory, LIBDIR, you must either use libtool, and"
-    $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
-    $echo "flag during linking and do at least one of the following:"
-    if test -n "$shlibpath_var"; then
-      $echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
-      $echo "     during execution"
-    fi
-    if test -n "$runpath_var"; then
-      $echo "   - add LIBDIR to the \`$runpath_var' environment variable"
-      $echo "     during linking"
-    fi
-    if test -n "$hardcode_libdir_flag_spec"; then
-      libdir=LIBDIR
-      eval flag=\"$hardcode_libdir_flag_spec\"
-
-      $echo "   - use the \`$flag' linker flag"
-    fi
-    if test -n "$admincmds"; then
-      $echo "   - have your system administrator run these commands:$admincmds"
-    fi
-    if test -f /etc/ld.so.conf; then
-      $echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
-    fi
-    $echo
-    $echo "See any operating system documentation about shared libraries for"
-    $echo "more information, such as the ld(1) and ld.so(8) manual pages."
-    $echo "X----------------------------------------------------------------------" | $Xsed
-    exit $EXIT_SUCCESS
-    ;;
-
-  # libtool execute mode
-  execute)
-    modename="$modename: execute"
-
-    # The first argument is the command name.
-    cmd="$nonopt"
-    if test -z "$cmd"; then
-      $echo "$modename: you must specify a COMMAND" 1>&2
-      $echo "$help"
-      exit $EXIT_FAILURE
-    fi
-
-    # Handle -dlopen flags immediately.
-    for file in $execute_dlfiles; do
-      if test ! -f "$file"; then
-	$echo "$modename: \`$file' is not a file" 1>&2
-	$echo "$help" 1>&2
-	exit $EXIT_FAILURE
-      fi
-
-      dir=
-      case $file in
-      *.la)
-	# Check to see that this really is a libtool archive.
-	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
-	else
-	  $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
-	  $echo "$help" 1>&2
-	  exit $EXIT_FAILURE
-	fi
-
-	# Read the libtool library.
-	dlname=
-	library_names=
-
-	# If there is no directory component, then add one.
-	case $file in
-	*/* | *\\*) . $file ;;
-	*) . ./$file ;;
-	esac
-
-	# Skip this library if it cannot be dlopened.
-	if test -z "$dlname"; then
-	  # Warn if it was a shared library.
-	  test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
-	  continue
-	fi
-
-	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
-	test "X$dir" = "X$file" && dir=.
-
-	if test -f "$dir/$objdir/$dlname"; then
-	  dir="$dir/$objdir"
-	else
-	  $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
-	  exit $EXIT_FAILURE
-	fi
-	;;
-
-      *.lo)
-	# Just add the directory containing the .lo file.
-	dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
-	test "X$dir" = "X$file" && dir=.
-	;;
-
-      *)
-	$echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
-	continue
-	;;
-      esac
-
-      # Get the absolute pathname.
-      absdir=`cd "$dir" && pwd`
-      test -n "$absdir" && dir="$absdir"
-
-      # Now add the directory to shlibpath_var.
-      if eval "test -z \"\$$shlibpath_var\""; then
-	eval "$shlibpath_var=\"\$dir\""
-      else
-	eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
-      fi
-    done
-
-    # This variable tells wrapper scripts just to set shlibpath_var
-    # rather than running their programs.
-    libtool_execute_magic="$magic"
-
-    # Check if any of the arguments is a wrapper script.
-    args=
-    for file
-    do
-      case $file in
-      -*) ;;
-      *)
-	# Do a test to see if this is really a libtool program.
-	if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-	  # If there is no directory component, then add one.
-	  case $file in
-	  */* | *\\*) . $file ;;
-	  *) . ./$file ;;
-	  esac
-
-	  # Transform arg to wrapped name.
-	  file="$progdir/$program"
-	fi
-	;;
-      esac
-      # Quote arguments (to preserve shell metacharacters).
-      file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
-      args="$args \"$file\""
-    done
-
-    if test -z "$run"; then
-      if test -n "$shlibpath_var"; then
-	# Export the shlibpath_var.
-	eval "export $shlibpath_var"
-      fi
-
-      # Restore saved environment variables
-      if test "${save_LC_ALL+set}" = set; then
-	LC_ALL="$save_LC_ALL"; export LC_ALL
-      fi
-      if test "${save_LANG+set}" = set; then
-	LANG="$save_LANG"; export LANG
-      fi
-
-      # Now prepare to actually exec the command.
-      exec_cmd="\$cmd$args"
-    else
-      # Display what would be done.
-      if test -n "$shlibpath_var"; then
-	eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
-	$echo "export $shlibpath_var"
-      fi
-      $echo "$cmd$args"
-      exit $EXIT_SUCCESS
-    fi
-    ;;
-
-  # libtool clean and uninstall mode
-  clean | uninstall)
-    modename="$modename: $mode"
-    rm="$nonopt"
-    files=
-    rmforce=
-    exit_status=0
-
-    # This variable tells wrapper scripts just to set variables rather
-    # than running their programs.
-    libtool_install_magic="$magic"
-
-    for arg
-    do
-      case $arg in
-      -f) rm="$rm $arg"; rmforce=yes ;;
-      -*) rm="$rm $arg" ;;
-      *) files="$files $arg" ;;
-      esac
-    done
-
-    if test -z "$rm"; then
-      $echo "$modename: you must specify an RM program" 1>&2
-      $echo "$help" 1>&2
-      exit $EXIT_FAILURE
-    fi
-
-    rmdirs=
-
-    origobjdir="$objdir"
-    for file in $files; do
-      dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
-      if test "X$dir" = "X$file"; then
-	dir=.
-	objdir="$origobjdir"
-      else
-	objdir="$dir/$origobjdir"
-      fi
-      name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
-      test "$mode" = uninstall && objdir="$dir"
-
-      # Remember objdir for removal later, being careful to avoid duplicates
-      if test "$mode" = clean; then
-	case " $rmdirs " in
-	  *" $objdir "*) ;;
-	  *) rmdirs="$rmdirs $objdir" ;;
-	esac
-      fi
-
-      # Don't error if the file doesn't exist and rm -f was used.
-      if (test -L "$file") >/dev/null 2>&1 \
-	|| (test -h "$file") >/dev/null 2>&1 \
-	|| test -f "$file"; then
-	:
-      elif test -d "$file"; then
-	exit_status=1
-	continue
-      elif test "$rmforce" = yes; then
-	continue
-      fi
-
-      rmfiles="$file"
-
-      case $name in
-      *.la)
-	# Possibly a libtool archive, so verify it.
-	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-	  . $dir/$name
-
-	  # Delete the libtool libraries and symlinks.
-	  for n in $library_names; do
-	    rmfiles="$rmfiles $objdir/$n"
-	  done
-	  test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
-
-	  case "$mode" in
-	  clean)
-	    case "  $library_names " in
-	    # "  " in the beginning catches empty $dlname
-	    *" $dlname "*) ;;
-	    *) rmfiles="$rmfiles $objdir/$dlname" ;;
-	    esac
-	     test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
-	    ;;
-	  uninstall)
-	    if test -n "$library_names"; then
-	      # Do each command in the postuninstall commands.
-	      cmds=$postuninstall_cmds
-	      save_ifs="$IFS"; IFS='~'
-	      for cmd in $cmds; do
-		IFS="$save_ifs"
-		eval cmd=\"$cmd\"
-		$show "$cmd"
-		$run eval "$cmd"
-		if test "$?" -ne 0 && test "$rmforce" != yes; then
-		  exit_status=1
-		fi
-	      done
-	      IFS="$save_ifs"
-	    fi
-
-	    if test -n "$old_library"; then
-	      # Do each command in the old_postuninstall commands.
-	      cmds=$old_postuninstall_cmds
-	      save_ifs="$IFS"; IFS='~'
-	      for cmd in $cmds; do
-		IFS="$save_ifs"
-		eval cmd=\"$cmd\"
-		$show "$cmd"
-		$run eval "$cmd"
-		if test "$?" -ne 0 && test "$rmforce" != yes; then
-		  exit_status=1
-		fi
-	      done
-	      IFS="$save_ifs"
-	    fi
-	    # FIXME: should reinstall the best remaining shared library.
-	    ;;
-	  esac
-	fi
-	;;
-
-      *.lo)
-	# Possibly a libtool object, so verify it.
-	if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-
-	  # Read the .lo file
-	  . $dir/$name
-
-	  # Add PIC object to the list of files to remove.
-	  if test -n "$pic_object" \
-	     && test "$pic_object" != none; then
-	    rmfiles="$rmfiles $dir/$pic_object"
-	  fi
-
-	  # Add non-PIC object to the list of files to remove.
-	  if test -n "$non_pic_object" \
-	     && test "$non_pic_object" != none; then
-	    rmfiles="$rmfiles $dir/$non_pic_object"
-	  fi
-	fi
-	;;
-
-      *)
-	if test "$mode" = clean ; then
-	  noexename=$name
-	  case $file in
-	  *.exe)
-	    file=`$echo $file|${SED} 's,.exe$,,'`
-	    noexename=`$echo $name|${SED} 's,.exe$,,'`
-	    # $file with .exe has already been added to rmfiles,
-	    # add $file without .exe
-	    rmfiles="$rmfiles $file"
-	    ;;
-	  esac
-	  # Do a test to see if this is a libtool program.
-	  if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
-	    relink_command=
-	    . $dir/$noexename
-
-	    # note $name still contains .exe if it was in $file originally
-	    # as does the version of $file that was added into $rmfiles
-	    rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
-	    if test "$fast_install" = yes && test -n "$relink_command"; then
-	      rmfiles="$rmfiles $objdir/lt-$name"
-	    fi
-	    if test "X$noexename" != "X$name" ; then
-	      rmfiles="$rmfiles $objdir/lt-${noexename}.c"
-	    fi
-	  fi
-	fi
-	;;
-      esac
-      $show "$rm $rmfiles"
-      $run $rm $rmfiles || exit_status=1
-    done
-    objdir="$origobjdir"
-
-    # Try to remove the ${objdir}s in the directories where we deleted files
-    for dir in $rmdirs; do
-      if test -d "$dir"; then
-	$show "rmdir $dir"
-	$run rmdir $dir >/dev/null 2>&1
-      fi
-    done
-
-    exit $exit_status
-    ;;
-
-  "")
-    $echo "$modename: you must specify a MODE" 1>&2
-    $echo "$generic_help" 1>&2
-    exit $EXIT_FAILURE
-    ;;
-  esac
-
-  if test -z "$exec_cmd"; then
-    $echo "$modename: invalid operation mode \`$mode'" 1>&2
-    $echo "$generic_help" 1>&2
-    exit $EXIT_FAILURE
-  fi
-fi # test -z "$show_help"
-
-if test -n "$exec_cmd"; then
-  eval exec $exec_cmd
-  exit $EXIT_FAILURE
-fi
-
-# We need to display help for each of the modes.
-case $mode in
-"") $echo \
-"Usage: $modename [OPTION]... [MODE-ARG]...
-
-Provide generalized library-building support services.
-
-    --config          show all configuration variables
-    --debug           enable verbose shell tracing
--n, --dry-run         display commands without modifying any files
-    --features        display basic configuration information and exit
-    --finish          same as \`--mode=finish'
-    --help            display this help message and exit
-    --mode=MODE       use operation mode MODE [default=inferred from MODE-ARGS]
-    --quiet           same as \`--silent'
-    --silent          don't print informational messages
-    --tag=TAG         use configuration variables from tag TAG
-    --version         print version information
-
-MODE must be one of the following:
-
-      clean           remove files from the build directory
-      compile         compile a source file into a libtool object
-      execute         automatically set library path, then run a program
-      finish          complete the installation of libtool libraries
-      install         install libraries or executables
-      link            create a library or an executable
-      uninstall       remove libraries from an installed directory
-
-MODE-ARGS vary depending on the MODE.  Try \`$modename --help --mode=MODE' for
-a more detailed description of MODE.
-
-Report bugs to <bug-libtool@gnu.org>."
-  exit $EXIT_SUCCESS
-  ;;
-
-clean)
-  $echo \
-"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
-
-Remove files from the build directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, object or program, all the files associated
-with it are deleted. Otherwise, only FILE itself is deleted using RM."
-  ;;
-
-compile)
-  $echo \
-"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
-
-Compile a source file into a libtool library object.
-
-This mode accepts the following additional options:
-
-  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
-  -prefer-pic       try to building PIC objects only
-  -prefer-non-pic   try to building non-PIC objects only
-  -static           always build a \`.o' file suitable for static linking
-
-COMPILE-COMMAND is a command to be used in creating a \`standard' object file
-from the given SOURCEFILE.
-
-The output file name is determined by removing the directory component from
-SOURCEFILE, then substituting the C source code suffix \`.c' with the
-library object suffix, \`.lo'."
-  ;;
-
-execute)
-  $echo \
-"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
-
-Automatically set library path, then run a program.
-
-This mode accepts the following additional options:
-
-  -dlopen FILE      add the directory containing FILE to the library path
-
-This mode sets the library path environment variable according to \`-dlopen'
-flags.
-
-If any of the ARGS are libtool executable wrappers, then they are translated
-into their corresponding uninstalled binary, and any of their required library
-directories are added to the library path.
-
-Then, COMMAND is executed, with ARGS as arguments."
-  ;;
-
-finish)
-  $echo \
-"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
-
-Complete the installation of libtool libraries.
-
-Each LIBDIR is a directory that contains libtool libraries.
-
-The commands that this mode executes may require superuser privileges.  Use
-the \`--dry-run' option if you just want to see what would be executed."
-  ;;
-
-install)
-  $echo \
-"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
-
-Install executables or libraries.
-
-INSTALL-COMMAND is the installation command.  The first component should be
-either the \`install' or \`cp' program.
-
-The rest of the components are interpreted as arguments to that command (only
-BSD-compatible install options are recognized)."
-  ;;
-
-link)
-  $echo \
-"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
-
-Link object files or libraries together to form another library, or to
-create an executable program.
-
-LINK-COMMAND is a command using the C compiler that you would use to create
-a program from several object files.
-
-The following components of LINK-COMMAND are treated specially:
-
-  -all-static       do not do any dynamic linking at all
-  -avoid-version    do not add a version suffix if possible
-  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
-  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
-  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
-  -export-symbols SYMFILE
-		    try to export only the symbols listed in SYMFILE
-  -export-symbols-regex REGEX
-		    try to export only the symbols matching REGEX
-  -LLIBDIR          search LIBDIR for required installed libraries
-  -lNAME            OUTPUT-FILE requires the installed library libNAME
-  -module           build a library that can dlopened
-  -no-fast-install  disable the fast-install mode
-  -no-install       link a not-installable executable
-  -no-undefined     declare that a library does not refer to external symbols
-  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
-  -objectlist FILE  Use a list of object files found in FILE to specify objects
-  -precious-files-regex REGEX
-                    don't remove output files matching REGEX
-  -release RELEASE  specify package release information
-  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
-  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
-  -static           do not do any dynamic linking of libtool libraries
-  -version-info CURRENT[:REVISION[:AGE]]
-		    specify library version info [each variable defaults to 0]
-
-All other options (arguments beginning with \`-') are ignored.
-
-Every other argument is treated as a filename.  Files ending in \`.la' are
-treated as uninstalled libtool libraries, other files are standard or library
-object files.
-
-If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
-only library objects (\`.lo' files) may be specified, and \`-rpath' is
-required, except when creating a convenience library.
-
-If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
-using \`ar' and \`ranlib', or on Windows using \`lib'.
-
-If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
-is created, otherwise an executable program is created."
-  ;;
-
-uninstall)
-  $echo \
-"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
-
-Remove libraries from an installation directory.
-
-RM is the name of the program to use to delete files associated with each FILE
-(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
-to RM.
-
-If FILE is a libtool library, all the files associated with it are deleted.
-Otherwise, only FILE itself is deleted using RM."
-  ;;
-
-*)
-  $echo "$modename: invalid operation mode \`$mode'" 1>&2
-  $echo "$help" 1>&2
-  exit $EXIT_FAILURE
-  ;;
-esac
-
-$echo
-$echo "Try \`$modename --help' for more information about other modes."
-
-exit $?
-
-# The TAGs below are defined such that we never get into a situation
-# in which we disable both kinds of libraries.  Given conflicting
-# choices, we go for a static library, that is the most portable,
-# since we can't tell whether shared libraries were disabled because
-# the user asked for that or because the platform doesn't support
-# them.  This is particularly important on AIX, because we don't
-# support having both static and shared libraries enabled at the same
-# time on that platform, so we default to a shared-only configuration.
-# If a disable-shared tag is given, we'll fallback to a static-only
-# configuration.  But we'll never go from static-only to shared-only.
-
-# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
-disable_libs=shared
-# ### END LIBTOOL TAG CONFIG: disable-shared
-
-# ### BEGIN LIBTOOL TAG CONFIG: disable-static
-disable_libs=static
-# ### END LIBTOOL TAG CONFIG: disable-static
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
Index: _lib/mpn_pylong.c
===================================================================
--- c_lib/mpn_pylong.c	(revision 6011)
+++ 	(revision )
@@ -1,253 +1,0 @@
-/* mpn <-> pylong conversion and "pythonhash" for mpn
- *
- * Author:  Gonzalo TornarÃ­a <tornaria@math.utexas.edu>
- * Date:    March 2006
- * License: GPL v2
- *
- * the code to change the base to 2^SHIFT is based on the function
- * mpn_get_str from GNU MP, but the new bugs are mine
- *
- * this is free software: if it breaks, you get to keep all the pieces
- */
-
-#include "mpn_pylong.h"
-
-/* This code assumes that SHIFT < GMP_NUMB_BITS */
-#if SHIFT >= GMP_NUMB_BITS
-#error "Python limb larger than GMP limb !!!"
-#endif
-
-/* Use these "portable" (I hope) sizebits functions
- * We could implement this in terms of count_leading_zeros from GMP,
- * but it is not exported !
- */
-static const
-unsigned char
-__sizebits_tab[128] =
-{
-  0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-};
-
-#if GMP_LIMB_BITS > 64
-#error "word size > 64 unsupported"
-#endif
-
-static inline
-unsigned long
-mpn_sizebits(mp_ptr up, mp_size_t un) {
-  unsigned long cnt;
-  mp_limb_t x;
-  if (un==0) return 0;
-  cnt = (un - 1) * GMP_NUMB_BITS;
-  x = up[un - 1];
-#if GMP_LIMB_BITS > 32
-  if ((x >> 32) != 0) { x >>= 32; cnt += 32; }
-#endif
-#if GMP_LIMB_BITS > 16
-  if ((x >> 16) != 0) { x >>= 16; cnt += 16; }
-#endif
-#if GMP_LIMB_BITS > 8
-  if ((x >>  8) != 0) { x >>=  8; cnt += 8; }
-#endif
-  return cnt + ((x & 0x80) ? 8 : __sizebits_tab[x]);
-}
-
-static inline
-unsigned long
-pylong_sizebits(digit *digits, py_size_t size) {
-  unsigned long cnt;
-  digit x;
-  if (size==0) return 0;
-  cnt = (size - 1) * SHIFT;
-  x = digits[size - 1];
-#if SHIFT > 32
-  if ((x >> 32) != 0) { x >>= 32; cnt += 32; }
-#endif
-#if SHIFT > 16
-  if ((x >> 16) != 0) { x >>= 16; cnt += 16; }
-#endif
-#if SHIFT > 8
-  if ((x >>  8) != 0) { x >>=  8; cnt += 8; }
-#endif
-  return cnt + ((x & 0x80) ? 8 : __sizebits_tab[x]);
-}
-
-
-/* mpn -> pylong conversion */
-
-int
-mpn_pylong_size (mp_ptr up, mp_size_t un)
-{
-  return (mpn_sizebits(up, un) + SHIFT - 1) / SHIFT;
-}
-
-/* this is based from GMP code in mpn/get_str.c */
-
-/* Assume digits points to a chunk of size size
- * where size >= mpn_pylong_size(up, un)
- */
-void
-mpn_get_pylong (digit *digits, py_size_t size, mp_ptr up, mp_size_t un)
-{
-  mp_limb_t n1, n0;
-  mp_size_t i;
-  int bit_pos;
-  /* point past the allocated chunk */
-  digit * s = digits + size;
-
-  /* input length 0 is special ! */
-  if (un == 0) {
-    while (size) digits[--size]=0;
-    return;
-  }
-
-  i = un - 1;
-  n1 = up[i];
-  bit_pos = size * SHIFT - i * GMP_NUMB_BITS;
-
-  for (;;)
-    {
-      bit_pos -= SHIFT;
-      while (bit_pos >= 0)
-        {
-          *--s = (n1 >> bit_pos) & MASK;
-          bit_pos -= SHIFT;
-        }
-      if (i == 0)
-        break;
-      n0 = (n1 << -bit_pos) & MASK;
-      n1 = up[--i];
-      bit_pos += GMP_NUMB_BITS;
-      *--s = n0 | (n1 >> bit_pos);
-    }
-}
-
-/* pylong -> mpn conversion */
-
-mp_size_t
-mpn_size_from_pylong (digit *digits, py_size_t size)
-{
-  return (pylong_sizebits(digits, size) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
-}
-
-void
-mpn_set_pylong (mp_ptr up, mp_size_t un, digit *digits, py_size_t size)
-{
-  mp_limb_t n1, d;
-  mp_size_t i;
-  int bit_pos;
-  /* point past the allocated chunk */
-  digit * s = digits + size;
-
-  /* input length 0 is special ! */
-  if (size == 0) {
-    while (un) up[--un]=0;
-    return;
-  }
-
-  i = un - 1;
-  n1 = 0;
-  bit_pos = size * SHIFT - i * GMP_NUMB_BITS;
-
-  for (;;)
-    {
-      bit_pos -= SHIFT;
-      while (bit_pos >= 0)
-        {
-          d = (mp_limb_t) *--s;
-          n1 |= (d << bit_pos) & GMP_NUMB_MASK;
-          bit_pos -= SHIFT;
-        }
-      if (i == 0)
-        break;
-      d = (mp_limb_t) *--s;
-      /* add some high bits of d; maybe none if bit_pos=-SHIFT */
-      up[i--] = n1 | (d & MASK) >> -bit_pos;
-      bit_pos += GMP_NUMB_BITS;
-      n1 = (d << bit_pos) & GMP_NUMB_MASK;
-    }
-  up[0] = n1;
-}
-
-
-/************************************************************/
-
-/* Hashing functions */
-
-#define LONG_BIT_SHIFT  (8*sizeof(long) - SHIFT)
-
-/*
- * for an mpz, this number has to be multiplied by the sign
- * also remember to catch -1 and map it to -2 !
- */
-long
-mpn_pythonhash (mp_ptr up, mp_size_t un)
-{
-  mp_limb_t n1, n0;
-  mp_size_t i;
-  int bit_pos;
-  long x = 0;
-
-  /* input length 0 is special ! */
-  if (un == 0) return 0;
-
-  i = un - 1;
-  n1 = up[i];
-  {
-    unsigned long bits;
-    bits = mpn_sizebits(up, un) + SHIFT - 1;
-    bits -= bits % SHIFT;
-    /* position of the MSW in base 2^SHIFT, counted from the MSW in
-     * the GMP representation (in base 2^GMP_NUMB_BITS)
-     */
-    bit_pos = bits - i * GMP_NUMB_BITS;
-  }
-
-  for (;;)
-    {
-      while (bit_pos >= 0)
-        {
-          /* Force a native long #-bits (32 or 64) circular shift */
-          x = ((x << SHIFT) & ~MASK) | ((x >> LONG_BIT_SHIFT) & MASK);
-          x += (n1 >> bit_pos) & MASK;
-          bit_pos -= SHIFT;
-        }
-      i--;
-      if (i < 0)
-        break;
-      n0 = (n1 << -bit_pos) & MASK;
-      n1 = up[i];
-      bit_pos += GMP_NUMB_BITS;
-      /* Force a native long #-bits (32 or 64) circular shift */
-      x = ((x << SHIFT) & ~MASK) | ((x >> LONG_BIT_SHIFT) & MASK);
-      x += n0 | (n1 >> bit_pos);
-      bit_pos -= SHIFT;
-    }
-
-  return x;
-}
-
-#if 0
-/* This is a *very* bad hash...
- * If we decide to give up pylong compatibility, we should research to
- * find a decent (but fast) hash
- *
- * Some pointers to start:
- * <http://www.isthe.com/chongo/tech/comp/fnv/>
- * <http://www.azillionmonkeys.com/qed/hash.html>
- * <http://burtleburtle.net/bob/hash/doobs.html>
- */
-long
-mpn_fasthash (mp_ptr up, mp_size_t un)
-{
-  long x=0;
-  int i=un;
-  while (i)
-    x^=up[--i];
-  return x;
-}
-
-#endif
Index: _lib/mpn_pylong.h
===================================================================
--- c_lib/mpn_pylong.h	(revision 6011)
+++ 	(revision )
@@ -1,49 +1,0 @@
-#ifndef MPN_PYLONG_H
-#define MPN_PYLONG_H
-
-#include <Python.h>
-#include <gmp.h>
-
-/************************************************************/
-
-/* Python internals for pylong */
-
-#include <longintrepr.h>
-typedef int py_size_t; /* what python uses for ob_size */
-
-/************************************************************/
-
-/* mpn -> pylong conversion */
-
-int mpn_pylong_size (mp_ptr up, mp_size_t un);
-
-/* Assume digits points to a chunk of size size
- * where size >= mpn_pylong_size(up, un)
- */
-void mpn_get_pylong (digit *digits, py_size_t size, mp_ptr up, mp_size_t un);
-
-/************************************************************/
-
-/* pylong -> mpn conversion */
-
-mp_size_t mpn_size_from_pylong (digit *digits, py_size_t size);
-
-/* Assume up points to a chunk of size un
- * where un >= mpn_size_from_pylong(digits, size)
- */
-void mpn_set_pylong (mp_ptr up, mp_size_t un, digit *digits, py_size_t size);
-
-/************************************************************/
-
-/* Python hashing */
-
-/*
- * for an mpz, this number has to be multiplied by the sign
- * also remember to catch -1 and map it to -2 !
- */
-
-long mpn_pythonhash (mp_ptr up, mp_size_t un);
-
-/************************************************************/
-
-#endif
Index: _lib/mpz_pylong.c
===================================================================
--- c_lib/mpz_pylong.c	(revision 6052)
+++ 	(revision )
@@ -1,81 +1,0 @@
-/* mpz <-> pylong conversion and "pythonhash" for mpz
- *
- * Author:  Gonzalo TornarÃ­a <tornaria@math.utexas.edu>
- * Date:    March 2006
- * License: GPL v2
- *
- * this is free software: if it breaks, you get to keep all the pieces
-
-AUTHORS:
-  -- David Harvey (2007-08-18): added mpz_get_pyintlong function
-
- */
-
-#include "mpn_pylong.h"
-#include "mpz_pylong.h"
-
-/* mpz python hash */
-long
-mpz_pythonhash (mpz_srcptr z)
-{
-  long x = mpn_pythonhash(z->_mp_d, abs(z->_mp_size));
-  if (z->_mp_size < 0)
-    x = -x;
-  if (x == -1)
-    x = -2;
-  return x;
-}
-
-/* mpz -> pylong conversion */
-PyObject *
-mpz_get_pylong(mpz_srcptr z)
-{
-  py_size_t size = mpn_pylong_size(z->_mp_d, abs(z->_mp_size));
-  PyLongObject *l = PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size);
-
-  if (l != NULL)
-  {
-    mpn_get_pylong(l->ob_digit, size, z->_mp_d, abs(z->_mp_size));
-    if (z->_mp_size < 0)
-      l->ob_size = -(l->ob_size);
-  }
-
-  return (PyObject *) l;
-}
-
-/* mpz -> pyint/pylong conversion; if the value fits in a python int, it
-returns a python int (optimised for that pathway), otherwise returns
-a python long */
-PyObject *
-mpz_get_pyintlong(mpz_srcptr z)
-{
-  if (mpz_fits_slong_p(z))
-     return PyInt_FromLong(mpz_get_si(z));
-
-  return mpz_get_pylong(z);
-}
-
-/* pylong -> mpz conversion */
-int
-mpz_set_pylong(mpz_ptr z, PyObject * ll)
-{
-  register PyLongObject * l = (PyLongObject *) ll;
-  mp_size_t size;
-  int i;
-
-  if (l==NULL || !PyLong_Check(l)) {
-    PyErr_BadInternalCall();
-    return -1;
-  }
-  
-  size = mpn_size_from_pylong(l->ob_digit, abs(l->ob_size));
-
-  if (z->_mp_alloc < size)
-    _mpz_realloc (z, size);
-
-  mpn_set_pylong(z->_mp_d, size, l->ob_digit, abs(l->ob_size));
-  z->_mp_size = l->ob_size < 0 ? -size : size;
-
-  return size;
-}
-
Index: _lib/mpz_pylong.h
===================================================================
--- c_lib/mpz_pylong.h	(revision 6052)
+++ 	(revision )
@@ -1,19 +1,0 @@
-#ifndef MPZ_PYLONG_H
-#define MPZ_PYLONG_H
-
-#include <Python.h>
-#include <gmp.h>
-
-/* mpz -> pylong conversion */
-PyObject * mpz_get_pylong(mpz_srcptr z);
-
-/* mpz -> pyint/pylong conversion */
-PyObject * mpz_get_pyintlong(mpz_srcptr z);
-
-/* pylong -> mpz conversion */
-int mpz_set_pylong(mpz_ptr z, PyObject * ll);
-
-/* mpz python hash */
-long mpz_pythonhash (mpz_srcptr z);
-
-#endif
Index: _lib/ntl_wrap.cpp
===================================================================
--- c_lib/ntl_wrap.cpp	(revision 6016)
+++ 	(revision )
@@ -1,1686 +1,0 @@
-#include <iostream>
-#include <sstream>
-using namespace std;
-
-#include "ntl_wrap.h"
-#include <NTL/mat_poly_ZZ.h>
-#include <NTL/LLL.h>
-
-void del_charstar(char* a) {
-  delete a;
-}
-
-//////// ZZ //////////
-
-ZZ* new_ZZ() {
-  return new ZZ();
-}
-
-void del_ZZ(ZZ* n) {
-  delete n;
-}
-
-ZZ* str_to_ZZ(const char* s) {
-  istringstream out;
-  out.str( s );// = new istringstream(s);
-  ZZ* y = new ZZ();
-  out >> *y;
-  //delete out;
-  return y;
-}
-
-/* Todo: could call into the Python C library to do this
-   more efficiently, and return a Python string or int directly. 
-   This would also vastly reduce the chances of an accidental 
-   memory leak.  
-   Drawback: Then this wouldn't be a pure C library interface anymore.  */
-char* ZZ_to_str(const ZZ* x) 
-{
-  ostringstream instore;
-  instore << (*x);
-  int n = strlen(instore.str().data());
-  char* buf = (char*)malloc(n+1);
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-/* Return value is only valid if the result should fit into an int.
-   AUTHOR: David Harvey (2008-06-08) */
-int ZZ_to_int(const ZZ* x)
-{
-  return to_int(*x);
-}
-
-/* Returns a *new* ZZ object.
-   AUTHOR: David Harvey (2008-06-08) */
-struct ZZ* int_to_ZZ(int value)
-{
-  ZZ* output = new ZZ();
-  conv(*output, value);
-  return output;
-}
-
-/* Copies the ZZ into the mpz_t
-   Assumes output has been mpz_init'd.
-   AUTHOR: David Harvey
-           Joel B. Mohler moved the ZZX_getitem_as_mpz code out to this function (2007-03-13) */
-void ZZ_to_mpz(mpz_t* output, const struct ZZ* x)
-{
-    unsigned char stack_bytes[4096];
-    int use_heap;
-    unsigned long size = NumBytes(*x);
-    use_heap = (size > sizeof(stack_bytes));
-    unsigned char* bytes = use_heap ? (unsigned char*) malloc(size) : stack_bytes;
-    BytesFromZZ(bytes, *x, size);
-    mpz_import(*output, size, -1, 1, 0, 0, bytes);
-    if (sign(*x) < 0)
-        mpz_neg(*output, *output);
-    if (use_heap)
-        free(bytes);
-}
-
-// Ok, I know that this is obvious
-// I just wanted to document the appearance of the magic number 8 in the code below
-#define bits_in_byte        8
-
-/* Copies the mpz_t into the ZZ
-   AUTHOR: Joel B. Mohler (2007-03-15) */
-void mpz_to_ZZ(struct ZZ* output, const mpz_t* x)
-{
-    unsigned char stack_bytes[4096];
-    int use_heap;
-    size_t size = (mpz_sizeinbase(*x, 2) + bits_in_byte-1) / bits_in_byte;
-    use_heap = (size > sizeof(stack_bytes));
-    void* bytes = use_heap ? malloc(size) : stack_bytes;
-    size_t words_written;
-    mpz_export(bytes, &words_written, -1, 1, 0, 0, *x);
-    clear(*output);
-    ZZFromBytes(*output, (unsigned char *)bytes, words_written);
-    if (mpz_sgn(*x) < 0)
-        NTL::negate(*output, *output);
-    if (use_heap)
-        free(bytes);
-}
-
-/* Sets given ZZ to value
-   AUTHOR: David Harvey (2008-06-08) */
-void ZZ_set_from_int(ZZ* x, int value)
-{
-  conv(*x, value);
-}
-
-struct ZZ* ZZ_mul(const struct ZZ* x, const struct ZZ* y)
-{
-  ZZ *z = new ZZ();
-  mul(*z, *x, *y);
-  return z;
-}
-
-struct ZZ* ZZ_add(const struct ZZ* x, const struct ZZ* y)
-{
-  ZZ *z = new ZZ();
-  add(*z, *x, *y);
-  return z;
-}
-
-struct ZZ* ZZ_sub(const struct ZZ* x, const struct ZZ* y)
-{
-  ZZ *z = new ZZ();
-  sub(*z, *x, *y);
-  return z;
-}
-
-struct ZZ* ZZ_pow(const struct ZZ* x, long e) 
-{
-  ZZ *z = new ZZ();
-  power(*z, *x, e);
-  return z;
-}
-
-int ZZ_equal(struct ZZ* x, struct ZZ* y)
-{
-  return (*x) == (*y);
-}
-
-int ZZ_is_one(struct ZZ* x)
-{
-  return IsOne(*x);
-}
-
-int ZZ_is_zero(struct ZZ* x)
-{
-  return IsZero(*x);
-}
-
-struct ZZ* ZZ_neg(struct ZZ* x)
-{
-  return new ZZ(-(*x));
-}
-
-struct ZZ* ZZ_copy(struct ZZ* x)
-{
-  ZZ *z = new ZZ(*x);
-  return z;
-}
-
-/*Random-number generation */
-
-void setSeed(const struct ZZ* n)
-{
-  SetSeed(*n);
-}
- 
-struct ZZ* ZZ_randomBnd(const struct ZZ* n)
-{ 
-  ZZ *z = new ZZ();
-  RandomBnd(*z,*n);
-  return z;
-}
-
-struct ZZ* ZZ_randomBits(long n)
-{ 
-  ZZ *z = new ZZ();
-  RandomBits(*z,n);
-  return z;
-}
-
-//////// ZZ_p //////////
-
-ZZ_p* new_ZZ_p() {
-  return new ZZ_p();
-}
-
-void del_ZZ_p(ZZ_p* n) {
-  delete n;
-}
-
-ZZ_p* str_to_ZZ_p(const char* s) {
-  istringstream *out = new istringstream(s);
-  ZZ_p* y = new ZZ_p();
-  *out >> *y;
-  delete out;
-  return y;
-}
-
-/* Todo: could call into the Python C library to do this
-   more efficiently, and return a Python string or int directly. 
-   This would reduce the chances of an accidental memory leak.  
-   Drawback: Then this wouldn't be a pure C library interface anymore.  */
-char* ZZ_p_to_str(const ZZ_p* x) 
-{
-  ostringstream instore;
-  instore << (*x);
-  int n = strlen(instore.str().data());
-  char* buf = new char[n+1];
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-/* Return value is only valid if the result should fit into an int.
-   AUTHOR: David Harvey (2008-06-08) */
-int ZZ_p_to_int(const ZZ_p* x)
-{
-  return ZZ_to_int(&rep(*x));
-}
-
-/* Returns a *new* ZZ_p object.
-   AUTHOR: David Harvey (2008-06-08) */
-struct ZZ_p* int_to_ZZ_p(int value)
-{
-  ZZ_p* output = new ZZ_p();
-  conv(*output, value);
-  return output;
-}
-
-/* Sets given ZZ_p to value
-   AUTHOR: David Harvey (2008-06-08) */
-void ZZ_p_set_from_int(ZZ_p* x, int value)
-{
-  conv(*x, value);
-}
-
-void ZZ_p_modulus(struct ZZ* mod, const struct ZZ_p* x)
-{
-	(*mod) = x->modulus();
-}
-
-struct ZZ_p* ZZ_p_mul(const struct ZZ_p* x, const struct ZZ_p* y)
-{
-  ZZ_p *z = new ZZ_p();
-  mul(*z, *x, *y);
-  return z;
-}
-
-struct ZZ_p* ZZ_p_add(const struct ZZ_p* x, const struct ZZ_p* y)
-{
-  ZZ_p *z = new ZZ_p();
-  add(*z, *x, *y);
-  return z;
-}
-
-struct ZZ_p* ZZ_p_sub(const struct ZZ_p* x, const struct ZZ_p* y)
-{
-  ZZ_p *z = new ZZ_p();
-  sub(*z, *x, *y);
-  return z;
-}
-
-struct ZZ_p* ZZ_p_pow(const struct ZZ_p* x, long e) 
-{
-  ZZ_p *z = new ZZ_p();
-  power(*z, *x, e);
-  return z;
-}
-
-int ZZ_p_is_one(struct ZZ_p* x)
-{
-  return IsOne(*x);
-}
-
-int ZZ_p_is_zero(struct ZZ_p* x)
-{
-  return IsZero(*x);
-}
-
-
-void ntl_ZZ_set_modulus(ZZ* x)
-{
-  ZZ_p::init(*x);
-}
-
-int ZZ_p_eq( ZZ_p* x,  ZZ_p* y)
-{
-  return (*x) == (*y);
-}
-
-ZZ_p* ZZ_p_inv(ZZ_p* x)
-{
-  ZZ_p *z = new ZZ_p();
-  inv(*z, *x);
-  return z;
-}
-
-ZZ_p* ZZ_p_random(void)
-{
-  ZZ_p *z = new ZZ_p();
-  random(*z);
-  return z;
-}
-
-struct ZZ_p* ZZ_p_neg(struct ZZ_p* x)
-{
-  return new ZZ_p(-(*x));
-}
-
-
-
-///////////////////////////////////////////////
-//////// ZZX //////////
-///////////////////////////////////////////////
-
-struct ZZX* ZZX_init()
-{
-  return new ZZX();
-}
-
-ZZX* str_to_ZZX(const char* s) {
-  istringstream *out = new istringstream(s);
-  ZZX* x = new ZZX();
-  *out >> *x;
-  delete out;
-  return x;
-}
-
-char* ZZX_repr(struct ZZX* x)
-{
-  ostringstream instore;
-  instore << (*x);
-  int n = strlen(instore.str().data());
-  char* buf = new char[n+1];
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-void ZZX_dealloc(struct ZZX* x) {
-  delete x;
-}
-
-struct ZZX* ZZX_copy(struct ZZX* x) {
-  return new ZZX(*x);
-}
-
-void ZZX_setitem(struct ZZX* x, long i, const char* a)
-{
-  ZZ* b = str_to_ZZ(a);
-  SetCoeff(*x, i, *b);
-  free(b);
-}
-
-/* Sets ith coefficient of x to value.
-   AUTHOR: David Harvey (2006-06-08) */
-void ZZX_setitem_from_int(struct ZZX* x, long i, int value)
-{
-  SetCoeff(*x, i, value);
-}
-
-char* ZZX_getitem(struct ZZX* x, long i)
-{
-  ZZ c = coeff(*x, i);
-  return ZZ_to_str(&c);
-}
-
-/* Returns ith coefficient of x.
-   Return value is only valid if the result should fit into an int.
-   AUTHOR: David Harvey (2006-06-08) */
-int ZZX_getitem_as_int(struct ZZX* x, long i)
-{
-  return ZZ_to_int(&coeff(*x, i));
-}
-
-/* Copies ith coefficient of x to output.
-   Assumes output has been mpz_init'd.
-   AUTHOR: David Harvey (2007-02) */
-void ZZX_getitem_as_mpz(mpz_t* output, struct ZZX* x, long i)
-{
-    const ZZ& z = coeff(*x, i);
-    ZZ_to_mpz(output, &z);
-}
-
-struct ZZX* ZZX_add(struct ZZX* x, struct ZZX* y)
-{
-  ZZX *z = new ZZX();
-  add(*z, *x, *y);
-  return z;
-}
-
-struct ZZX* ZZX_sub(struct ZZX* x, struct ZZX* y)
-{
-  ZZX *z = new ZZX();
-  sub(*z, *x, *y);
-  return z;
-}
-
-struct ZZX* ZZX_mul(struct ZZX* x, struct ZZX* y)
-{
-  ZZX *z = new ZZX();
-  mul(*z, *x, *y);
-  return z;
-}
-
-
-struct ZZX* ZZX_div(struct ZZX* x, struct ZZX* y, int* divisible)
-{
-  struct ZZX* z = new ZZX();
-  *divisible = divide(*z, *x, *y);
-  return z;
-}
-
-
-struct ZZX* ZZX_mod(struct ZZX* x, struct ZZX* y)
-{
-  struct ZZX* z = new ZZX();
-  rem(*z, *x, *y);
-  return z;
-}
-
-
-
-void ZZX_quo_rem(struct ZZX* x, struct ZZX* other, struct ZZX** r, struct ZZX** q)
-{
-  struct ZZX *qq = new ZZX(), *rr = new ZZX();
-  DivRem(*qq, *rr, *x, *other);
-  *r = rr; *q = qq;
-}
-
-
-struct ZZX* ZZX_square(struct ZZX* x)
-{
-  struct ZZX* s = new ZZX();
-  sqr(*s, *x);
-  return s;
-}
-
-
-int ZZX_equal(struct ZZX* x, struct ZZX* y)
-{
-  return (*x) == (*y);
-}
-
-
-int ZZX_is_zero(struct ZZX* x)
-{
-  return IsZero(*x);
-}
-
-
-int ZZX_is_one(struct ZZX* x)
-{
-  return IsOne(*x);
-}
-
-
-int ZZX_is_monic(struct ZZX* x)
-{
-  IsOne(LeadCoeff(*x));
-}
-
-
-struct ZZX* ZZX_neg(struct ZZX* x)
-{
-  struct ZZX* y = new ZZX();
-  *y = -*x;
-  return y;
-}
-
-
-struct ZZX* ZZX_left_shift(struct ZZX* x, long n)
-{
-  struct ZZX* y = new ZZX();
-  LeftShift(*y, *x, n);
-  return y;
-}
-
-
-struct ZZX* ZZX_right_shift(struct ZZX* x, long n)
-{
-  struct ZZX* y = new ZZX();
-  RightShift(*y, *x, n);
-  return y;
-}
-
-
-char* ZZX_content(struct ZZX* x)
-{
-  struct ZZ c;
-  content(c, *x);
-  return ZZ_to_str(&c);
-}
-
-
-struct ZZX* ZZX_primitive_part(struct ZZX* x)
-{
-  struct ZZX* p = new ZZX();
-  PrimitivePart(*p, *x);
-  return p;
-}
-
-
-void ZZX_pseudo_quo_rem(struct ZZX* x, struct ZZX* y, struct ZZX** r, struct ZZX** q)
-{
-  *r = new ZZX();
-  *q = new ZZX();
-  PseudoDivRem(**q, **r, *x, *y);
-}
-
-
-struct ZZX* ZZX_gcd(struct ZZX* x, struct ZZX* y)
-{
-  struct ZZX* g = new ZZX();
-  GCD(*g, *x, *y);
-  return g;
-}
-
-
-void ZZX_xgcd(struct ZZX* x, struct ZZX* y, struct ZZ** r, struct ZZX** s, \
-	      struct ZZX** t, int proof)
-{
-  *r = new ZZ();
-  *s = new ZZX();
-  *t = new ZZX();
-  XGCD(**r, **s, **t, *x, *y, proof);
-}
-
-
-long ZZX_degree(struct ZZX* x)
-{
-  return deg(*x);
-}
-
-
-struct ZZ* ZZX_leading_coefficient(struct ZZX* x)
-{
-  return new ZZ(LeadCoeff(*x));
-}
-
-
-char* ZZX_constant_term(struct ZZX* x)
-{
-  return ZZ_to_str(&ConstTerm(*x));
-}
-
-
-void ZZX_set_x(struct ZZX* x)
-{
-  SetX(*x);
-}
-
-
-int ZZX_is_x(struct ZZX* x)
-{
-  return IsX(*x);
-}
-
-
-struct ZZX* ZZX_derivative(struct ZZX* x)
-{
-  ZZX* d = new ZZX();
-  diff(*d, *x);
-  return d;
-}
-
-
-struct ZZX* ZZX_reverse(struct ZZX* x)
-{
-  ZZX* r = new ZZX();
-  reverse(*r, *x);
-  return r;
-}
-
-struct ZZX* ZZX_reverse_hi(struct ZZX* x, int hi)
-{
-  ZZX* r = new ZZX();
-  reverse(*r, *x, hi);
-  return r;
-}
-
-
-struct ZZX* ZZX_truncate(struct ZZX* x, long m)
-{
-  ZZX* t = new ZZX();
-  trunc(*t, *x, m);
-  return t;
-}
-
-
-struct ZZX* ZZX_multiply_and_truncate(struct ZZX* x, struct ZZX* y, long m)
-{
-  ZZX* t = new ZZX();
-  MulTrunc(*t, *x, *y, m);
-  return t;
-}
-
-
-struct ZZX* ZZX_square_and_truncate(struct ZZX* x, long m)
-{
-  ZZX* t = new ZZX();
-  SqrTrunc(*t, *x, m);
-  return t;
-}
-
-
-struct ZZX* ZZX_invert_and_truncate(struct ZZX* x, long m)
-{
-  ZZX* t = new ZZX();
-  InvTrunc(*t, *x, m);
-  return t;
-}
-
-
-struct ZZX* ZZX_multiply_mod(struct ZZX* x, struct ZZX* y,  struct ZZX* modulus)
-{
-  ZZX* p = new ZZX();
-  MulMod(*p, *x, *y, *modulus);
-  return p;
-}
-
-
-struct ZZ* ZZX_trace_mod(struct ZZX* x, struct ZZX* y)
-{
-  ZZ* p = new ZZ();
-  TraceMod(*p, *x, *y);
-  return p;
-}
-
-
-char* ZZX_trace_list(struct ZZX* x)
-{
-  vec_ZZ v;
-  TraceVec(v, *x);
-  ostringstream instore;
-  instore << v;
-  int n = strlen(instore.str().data());
-  char* buf = new char[n+1];
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-
-struct ZZ* ZZX_resultant(struct ZZX* x, struct ZZX* y, int proof)
-{
-  ZZ* res = new ZZ();
-  resultant(*res, *x, *y, proof);
-  return res;
-}
-
-
-struct ZZ* ZZX_norm_mod(struct ZZX* x, struct ZZX* y, int proof)
-{
-  ZZ* res = new ZZ();
-  NormMod(*res, *x, *y, proof);
-  return res;
-}
-
-
-struct ZZ* ZZX_discriminant(struct ZZX* x, int proof)
-{
-  ZZ* d = new ZZ();
-  discriminant(*d, *x, proof);
-  return d;
-}
-
-
-struct ZZX* ZZX_charpoly_mod(struct ZZX* x, struct ZZX* y, int proof)
-{
-  ZZX* f = new ZZX();
-  CharPolyMod(*f, *x, *y, proof);
-  return f;
-}
-
-
-struct ZZX* ZZX_minpoly_mod(struct ZZX* x, struct ZZX* y)
-{
-  ZZX* f = new ZZX();
-  MinPolyMod(*f, *x, *y);
-  return f;
-}
-
-
-void ZZX_clear(struct ZZX* x)
-{
-  clear(*x);
-}
-
-
-void ZZX_preallocate_space(struct ZZX* x, long n)
-{
-  x->SetMaxLength(n);
-}
-
-/*
-EXTERN struct ZZ* ZZX_polyeval(struct ZZX* f, struct ZZ* a)
-{
-  ZZ* b = new ZZ();
-  *b = PolyEval(*f, *a);
-  return b;
-}
-*/
-
-void ZZX_square_free_decomposition(struct ZZX*** v, long** e, long* n, struct ZZX* x)
-{
-  vec_pair_ZZX_long factors;
-  SquareFreeDecomp(factors, *x);
-  *n = factors.length();
-  *v = (ZZX**) malloc(sizeof(ZZX*) * (*n));
-  *e = (long*) malloc(sizeof(long) * (*n));
-  for (long i = 0; i < (*n); i++) {
-    (*v)[i] = new ZZX(factors[i].a);
-    (*e)[i] = factors[i].b;
-  }
-}
-
-///////////////////////////////////////////////
-//////// ZZ_pX //////////
-///////////////////////////////////////////////
-struct ZZ_pX* ZZ_pX_init()
-{
-  return new ZZ_pX();
-}
-
-ZZ_pX* str_to_ZZ_pX(const char* s) {
-  istringstream *out = new istringstream(s);
-  ZZ_pX* x = new ZZ_pX();
-  *out >> *x;
-  delete out;
-  return x;
-}
-
-char* ZZ_pX_repr(struct ZZ_pX* x)
-{
-  ostringstream instore;
-  instore << (*x);
-  int n = strlen(instore.str().data());
-  char* buf = new char[n+1];
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-void ZZ_pX_dealloc(struct ZZ_pX* x) {
-  delete x;
-}
-
-struct ZZ_pX* ZZ_pX_copy(struct ZZ_pX* x) {
-  return new ZZ_pX(*x);
-}
-
-void ZZ_pX_setitem(struct ZZ_pX* x, long i, const char* a)
-{
-  ZZ_p* b = str_to_ZZ_p(a);
-  SetCoeff(*x, i, *b);
-  free(b);
-}
-
-/* Sets ith coefficient of x to value.
-   AUTHOR: David Harvey (2008-06-08) */
-void ZZ_pX_setitem_from_int(struct ZZ_pX* x, long i, int value)
-{
-  SetCoeff(*x, i, value);
-}
-
-char* ZZ_pX_getitem(struct ZZ_pX* x, long i)
-{
-  ZZ_p c = coeff(*x, i);
-  return ZZ_p_to_str(&c);
-}
-
-/* Returns ith coefficient of x.
-   Return value is only valid if the result should fit into an int.
-   AUTHOR: David Harvey (2008-06-08) */
-int ZZ_pX_getitem_as_int(struct ZZ_pX* x, long i)
-{
-    return ZZ_to_int(&rep(coeff(*x, i)));
-}
-
-struct ZZ_pX* ZZ_pX_add(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  ZZ_pX *z = new ZZ_pX();
-  add(*z, *x, *y);
-  return z;
-}
-
-struct ZZ_pX* ZZ_pX_sub(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  ZZ_pX *z = new ZZ_pX();
-  sub(*z, *x, *y);
-  return z;
-}
-
-struct ZZ_pX* ZZ_pX_mul(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  ZZ_pX *z = new ZZ_pX();
-  mul(*z, *x, *y);
-  return z;
-}
-
-
-struct ZZ_pX* ZZ_pX_div(struct ZZ_pX* x, struct ZZ_pX* y, int* divisible)
-{
-  struct ZZ_pX* z = new ZZ_pX();
-  *divisible = divide(*z, *x, *y);
-  return z;
-}
-
-
-struct ZZ_pX* ZZ_pX_mod(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  struct ZZ_pX* z = new ZZ_pX();
-  rem(*z, *x, *y);
-  return z;
-}
-
-
-
-void ZZ_pX_quo_rem(struct ZZ_pX* x, struct ZZ_pX* y, struct ZZ_pX** r, struct ZZ_pX** q)
-{
-  *r = new ZZ_pX();
-  *q = new ZZ_pX();
-  DivRem(**q, **r, *x, *y);
-}
-
-
-struct ZZ_pX* ZZ_pX_square(struct ZZ_pX* x)
-{
-  struct ZZ_pX* s = new ZZ_pX();
-  sqr(*s, *x);
-  return s;
-}
-
-
-int ZZ_pX_equal(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  return (*x) == (*y);
-}
-
-
-int ZZ_pX_is_zero(struct ZZ_pX* x)
-{
-  return IsZero(*x);
-}
-
-
-int ZZ_pX_is_one(struct ZZ_pX* x)
-{
-  return IsOne(*x);
-}
-
-
-int ZZ_pX_is_monic(struct ZZ_pX* x)
-{
-  IsOne(LeadCoeff(*x));
-}
-
-
-struct ZZ_pX* ZZ_pX_neg(struct ZZ_pX* x)
-{
-  struct ZZ_pX* y = new ZZ_pX();
-  *y = -*x;
-  return y;
-}
-
-
-struct ZZ_pX* ZZ_pX_left_shift(struct ZZ_pX* x, long n)
-{
-  struct ZZ_pX* y = new ZZ_pX();
-  LeftShift(*y, *x, n);
-  return y;
-}
-
-
-struct ZZ_pX* ZZ_pX_right_shift(struct ZZ_pX* x, long n)
-{
-  struct ZZ_pX* y = new ZZ_pX();
-  RightShift(*y, *x, n);
-  return y;
-}
-
-
-
-struct ZZ_pX* ZZ_pX_gcd(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  struct ZZ_pX* g = new ZZ_pX();
-  GCD(*g, *x, *y);
-  return g;
-}
-
-
-void ZZ_pX_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b)
-{
-  *d = new ZZ_pX();
-  *s = new ZZ_pX();
-  *t = new ZZ_pX();
-  XGCD(**d, **s, **t, *a, *b);
-}
-
-void ZZ_pX_plain_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b)
-{
-  *d = new ZZ_pX();
-  *s = new ZZ_pX();
-  *t = new ZZ_pX();
-  PlainXGCD(**d, **s, **t, *a, *b);
-}
-
-long ZZ_pX_degree(struct ZZ_pX* x)
-{
-  return deg(*x);
-}
-
-
-ZZ_p* ZZ_pX_leading_coefficient(struct ZZ_pX* x)
-{
-  return new ZZ_p(LeadCoeff(*x));
-}
-
-
-char* ZZ_pX_constant_term(struct ZZ_pX* x)
-{
-  return ZZ_p_to_str(&ConstTerm(*x));
-}
-
-
-void ZZ_pX_set_x(struct ZZ_pX* x)
-{
-  SetX(*x);
-}
-
-
-int ZZ_pX_is_x(struct ZZ_pX* x)
-{
-  return IsX(*x);
-}
-
-
-struct ZZ_pX* ZZ_pX_derivative(struct ZZ_pX* x)
-{
-  ZZ_pX* d = new ZZ_pX();
-  diff(*d, *x);
-  return d;
-}
-
-
-struct ZZ_pX* ZZ_pX_reverse(struct ZZ_pX* x)
-{
-  ZZ_pX* r = new ZZ_pX();
-  reverse(*r, *x);
-  return r;
-}
-
-struct ZZ_pX* ZZ_pX_reverse_hi(struct ZZ_pX* x, int hi)
-{
-  ZZ_pX* r = new ZZ_pX();
-  reverse(*r, *x, hi);
-  return r;
-}
-
-
-struct ZZ_pX* ZZ_pX_truncate(struct ZZ_pX* x, long m)
-{
-  ZZ_pX* t = new ZZ_pX();
-  trunc(*t, *x, m);
-  return t;
-}
-
-
-struct ZZ_pX* ZZ_pX_multiply_and_truncate(struct ZZ_pX* x, struct ZZ_pX* y, long m)
-{
-  ZZ_pX* t = new ZZ_pX();
-  MulTrunc(*t, *x, *y, m);
-  return t;
-}
-
-
-struct ZZ_pX* ZZ_pX_square_and_truncate(struct ZZ_pX* x, long m)
-{
-  ZZ_pX* t = new ZZ_pX();
-  SqrTrunc(*t, *x, m);
-  return t;
-}
-
-
-struct ZZ_pX* ZZ_pX_invert_and_truncate(struct ZZ_pX* x, long m)
-{
-  ZZ_pX* t = new ZZ_pX();
-  InvTrunc(*t, *x, m);
-  return t;
-}
-
-
-struct ZZ_pX* ZZ_pX_multiply_mod(struct ZZ_pX* x, struct ZZ_pX* y,  struct ZZ_pX* modulus)
-{
-  ZZ_pX* p = new ZZ_pX();
-  MulMod(*p, *x, *y, *modulus);
-  return p;
-}
-
-
-struct ZZ_p* ZZ_pX_trace_mod(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  ZZ_p* p = new ZZ_p();
-  TraceMod(*p, *x, *y);
-  return p;
-}
-
-
-char* ZZ_pX_trace_list(struct ZZ_pX* x)
-{
-  vec_ZZ_p v;
-  TraceVec(v, *x);
-  ostringstream instore;
-  instore << v;
-  int n = strlen(instore.str().data());
-  char* buf = new char[n+1];
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-
-struct ZZ_p* ZZ_pX_resultant(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  ZZ_p* res = new ZZ_p();
-  resultant(*res, *x, *y);
-  return res;
-}
-
-
-struct ZZ_p* ZZ_pX_norm_mod(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  ZZ_p* res = new ZZ_p();
-  NormMod(*res, *x, *y);
-  return res;
-}
-
-
-
-struct ZZ_pX* ZZ_pX_charpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  ZZ_pX* f = new ZZ_pX();
-  CharPolyMod(*f, *x, *y);
-  return f;
-}
-
-
-struct ZZ_pX* ZZ_pX_minpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y)
-{
-  ZZ_pX* f = new ZZ_pX();
-  MinPolyMod(*f, *x, *y);
-  return f;
-}
-
-
-void ZZ_pX_clear(struct ZZ_pX* x)
-{
-  clear(*x);
-}
-
-
-void ZZ_pX_preallocate_space(struct ZZ_pX* x, long n)
-{
-  x->SetMaxLength(n);
-}
-
-
-void ZZ_pX_factor(struct ZZ_pX*** v, long** e, long* n, struct ZZ_pX* x, long verbose)
-{
-  long i;
-  vec_pair_ZZ_pX_long factors;
-  berlekamp(factors, *x, verbose);
-  *n = factors.length();
-  *v = (ZZ_pX**) malloc(sizeof(ZZ_pX*) * (*n));
-  *e = (long*) malloc(sizeof(long)*(*n));
-  for (i=0; i<(*n); i++) {
-    (*v)[i] = new ZZ_pX(factors[i].a);
-    (*e)[i] = factors[i].b;
-  }
-}
-
-void ZZ_pX_linear_roots(struct ZZ_p*** v, long* n, struct ZZ_pX* f)
-{
-  long i;
-  printf("1\n");
-  vec_ZZ_p w;
-  FindRoots(w, *f);
-  printf("2\n");
-  *n = w.length();
-  printf("3 %s\n",*n);
-  (*v) = (ZZ_p**) malloc(sizeof(ZZ_p*)*(*n));
-  for (i=0; i<(*n); i++) {
-    (*v)[i] = new ZZ_p(w[i]);
-  }
-}
-
-
-
-//////// mat_ZZ //////////
-
-void mat_ZZ_SetDims(struct mat_ZZ* mZZ, long nrows, long ncols){
-  mZZ->SetDims(nrows, ncols);
-}
-
-mat_ZZ* new_mat_ZZ(long nrows, long ncols) {
-  mat_ZZ* x = new mat_ZZ;
-  x->SetDims(nrows, ncols);
-  return x;
-}
-
-void del_mat_ZZ(mat_ZZ* x) {
-  delete x;
-}
-
-char* mat_ZZ_to_str(mat_ZZ* x) 
-{
-  ostringstream instore;
-  instore << (*x);
-  int n = strlen(instore.str().data());
-  char* buf = new char[n+1];
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-struct mat_ZZ* mat_ZZ_mul(const struct mat_ZZ* x, const struct mat_ZZ* y)
-{
-  mat_ZZ *z = new mat_ZZ();
-  mul(*z, *x, *y);
-  return z;
-}
-
-struct mat_ZZ* mat_ZZ_add(const struct mat_ZZ* x, const struct mat_ZZ* y)
-{
-  mat_ZZ *z = new mat_ZZ();
-  add(*z, *x, *y);
-  return z;
-}
-
-struct mat_ZZ* mat_ZZ_sub(const struct mat_ZZ* x, const struct mat_ZZ* y)
-{
-  mat_ZZ *z = new mat_ZZ();
-  sub(*z, *x, *y);
-  return z;
-}
-
-struct mat_ZZ* mat_ZZ_pow(const struct mat_ZZ* x, long e) 
-{
-  mat_ZZ *z = new mat_ZZ();
-  power(*z, *x, e);
-  return z;
-}
-
-long mat_ZZ_nrows(const struct mat_ZZ* x)
-{
-  return x->NumRows();
-}
-
-
-long mat_ZZ_ncols(const struct mat_ZZ* x)
-{
-  return x->NumCols();
-}
-
-void mat_ZZ_setitem(struct mat_ZZ* x, int i, int j, const struct ZZ* z)
-{
-  (*x)[i][j] = *z;
-  
-}
-
-struct ZZ* mat_ZZ_getitem(const struct mat_ZZ* x, int i, int j)
-{
-  return new ZZ((*x)(i,j));
-}
-
-struct ZZ* mat_ZZ_determinant(const struct mat_ZZ* x, long deterministic)
-{
-  ZZ* d = new ZZ();
-  determinant(*d, *x, deterministic);
-  return d;
-}
-
-struct mat_ZZ* mat_ZZ_HNF(const struct mat_ZZ* A, const struct ZZ* D)
-{
-  struct mat_ZZ* W = new mat_ZZ();
-  HNF(*W, *A, *D);
-  return W;
-}
-
-long mat_ZZ_LLL(struct ZZ **det, struct mat_ZZ *x, long a, long b, long verbose)
-{
-  *det = new ZZ();
-  return LLL(**det,*x,a,b,verbose);
-}
-
-long mat_ZZ_LLL_U(struct ZZ **det, struct mat_ZZ *x, struct mat_ZZ *U, long a, long b, long verbose)
-{
-  *det = new ZZ();
-  return LLL(**det,*x,*U,a,b,verbose);
-}
-
-
-struct ZZX* mat_ZZ_charpoly(const struct mat_ZZ* A)
-{
-  ZZX* f = new ZZX();
-  CharPoly(*f, *A);
-  return f;
-}
-
-
-
-/** 
- * GF2X
- *
- * @author Martin Albrecht <malb@informatik.uni-bremen.de>
- *
- * @versions 2006-01 malb
- *           initial version (based on code by William Stein)
- */
-GF2X* new_GF2X() {
-  return new GF2X();
-}
-
-void del_GF2X(GF2X* n) {
-  delete n;
-}
-
-GF2X* str_to_GF2X(const char* s) {
-  istringstream *out = new istringstream(s);
-  GF2X* y = new GF2X();
-  *out >> *y;
-  delete out;
-  return y;
-}
-
-/* Todo: could call into the Python C library to do this
-   more efficiently, and return a Python string or int directly. 
-   This would also vastly reduce the chances of an accidental 
-   memory leak.  
-   Drawback: Then this wouldn't be a pure C library interface anymore.  */
-char* GF2X_to_str(const GF2X* x) 
-{
-  ostringstream instore;
-  instore << (*x);
-  int n = strlen(instore.str().data());
-  char* buf = new char[n+1];
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-
-struct GF2X* GF2X_mul(const struct GF2X* x, const struct GF2X* y)
-{
-  GF2X *z = new GF2X();
-  mul(*z, *x, *y);
-  return z;
-}
-
-struct GF2X* GF2X_add(const struct GF2X* x, const struct GF2X* y)
-{
-  GF2X *z = new GF2X();
-  add(*z, *x, *y);
-  return z;
-}
-
-struct GF2X* GF2X_sub(const struct GF2X* x, const struct GF2X* y)
-{
-  GF2X *z = new GF2X();
-  sub(*z, *x, *y);
-  return z;
-}
-
-struct GF2X* GF2X_pow(const struct GF2X* x, long e) 
-{
-  GF2X *z = new GF2X();
-  power(*z, *x, e);
-  return z;
-}
-
-int GF2X_eq( const struct GF2X* x, const struct GF2X* y)
-{
-  return (*x) == (*y);
-}
-
-int GF2X_is_one(struct GF2X* x)
-{
-  return IsOne(*x);
-}
-
-int GF2X_is_zero(struct GF2X* x)
-{
-  return IsZero(*x);
-}
-
-struct GF2X* GF2X_neg(struct GF2X* x)
-{
-  return new GF2X(-(*x));
-}
-
-struct GF2X* GF2X_copy(struct GF2X* x)
-{
-  GF2X *z = new GF2X(*x);
-  return z;
-}
-
-long GF2X_deg(struct GF2X* x)
-{
-  return deg(*x);
-}
-
-void GF2X_hex(long h)
-{
-  GF2X::HexOutput=h;
-}
-
-char *GF2X_to_bin(const struct GF2X* x) 
-{
-  long hex;
-  char *buf;
-  hex = GF2X::HexOutput;
-  GF2X::HexOutput=0;
-  buf = GF2X_to_str(x);
-  GF2X::HexOutput=hex;
-  return buf;
-}
-
-char *GF2X_to_hex(const struct GF2X* x)
-{
-  long hex;
-  char *buf;
-  hex = GF2X::HexOutput;
-  GF2X::HexOutput=1;
-  buf = GF2X_to_str(x);
-  GF2X::HexOutput=hex;
-  return buf;
-}
-
-
-
-/** 
- * GF2E
- *
- * @author Martin Albrecht <malb@informatik.uni-bremen.de>
- *
- * @versions 2006-01 malb
- *           initial version (based on code by William Stein)
- */
-
-
-void ntl_GF2E_set_modulus(GF2X* x)
-{
-  GF2E::init(*x);
-}
-
-
-GF2E* new_GF2E() {
-  return new GF2E();
-}
-
-void del_GF2E(GF2E* n) {
-  delete n;
-}
-
-GF2E* str_to_GF2E(const char* s) {
-  istringstream *out = new istringstream(s);
-  GF2E* y = new GF2E();
-  *out >> *y;
-  delete out;
-  return y;
-}
-
-/* Todo: could call into the Python C library to do this
-   more efficiently, and return a Python string or int directly. 
-   This would also vastly reduce the chances of an accidental 
-   memory leak.  
-   Drawback: Then this wouldn't be a pure C library interface anymore.  */
-char* GF2E_to_str(const GF2E* x) 
-{
-  ostringstream instore;
-  instore << (*x);
-  int n = strlen(instore.str().data());
-  char* buf = new char[n+1];
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-
-struct GF2E* GF2E_mul(const struct GF2E* x, const struct GF2E* y)
-{
-  GF2E *z = new GF2E();
-  mul(*z, *x, *y);
-  return z;
-}
-
-struct GF2E* GF2E_add(const struct GF2E* x, const struct GF2E* y)
-{
-  GF2E *z = new GF2E();
-  add(*z, *x, *y);
-  return z;
-}
-
-struct GF2E* GF2E_sub(const struct GF2E* x, const struct GF2E* y)
-{
-  GF2E *z = new GF2E();
-  sub(*z, *x, *y);
-  return z;
-}
-
-struct GF2E* GF2E_pow(const struct GF2E* x, long e) 
-{
-  GF2E *z = new GF2E();
-  power(*z, *x, e);
-  return z;
-}
-
-int GF2E_eq( const struct GF2E* x, const struct GF2E* y)
-{
-  return (*x) == (*y);
-}
-
-
-int GF2E_is_one(struct GF2E* x)
-{
-  return IsOne(*x);
-}
-
-int GF2E_is_zero(struct GF2E* x)
-{
-  return IsZero(*x);
-}
-
-struct GF2E* GF2E_neg(struct GF2E* x)
-{
-  return new GF2E(-(*x));
-}
-
-struct GF2E* GF2E_copy(struct GF2E* x)
-{
-  GF2E *z = new GF2E(*x);
-  return z;
-}
-
-long GF2E_trace(struct GF2E* x)
-{
-  return rep(trace(*x));
-}
-
-
-long GF2E_degree()
-{
-  return GF2E::degree();
-}
-
-const struct GF2X* GF2E_modulus()
-{
-  GF2XModulus mod = GF2E::modulus();
-  GF2X *z = new GF2X(mod.val());
-  return z;
-}
-
-struct GF2E *GF2E_random(void)
-{
-  GF2E *z = new GF2E();
-  random(*z);
-  return z;
-}
-
-const struct GF2X *GF2E_ntl_GF2X(struct GF2E *x) {
-  GF2X *r = new GF2X(rep(*x));
-  return r;
-}
-
-
-/** 
- * GF2EX
- *
- * @author Martin Albrecht <malb@informatik.uni-bremen.de>
- *
- * @versions 2006-01 malb
- *           initial version (based on code by William Stein)
- */
-
-
-GF2EX* new_GF2EX() {
-  return new GF2EX();
-}
-
-void del_GF2EX(GF2EX* n) {
-  delete n;
-}
-
-GF2EX* str_to_GF2EX(const char* s) {
-  istringstream *out = new istringstream(s);
-  GF2EX* y = new GF2EX();
-  *out >> *y;
-  delete out;
-  return y;
-}
-
-/* Todo: could call into the Python C library to do this
-   more efficiently, and return a Python string or int directly. 
-   This would also vastly reduce the chances of an accidental 
-   memory leak.  
-   Drawback: Then this wouldn't be a pure C library interface anymore.  */
-char* GF2EX_to_str(const GF2EX* x) 
-{
-  ostringstream instore;
-  instore << (*x);
-  int n = strlen(instore.str().data());
-  char* buf = new char[n+1];
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-
-struct GF2EX* GF2EX_mul(const struct GF2EX* x, const struct GF2EX* y)
-{
-  GF2EX *z = new GF2EX();
-  mul(*z, *x, *y);
-  return z;
-}
-
-struct GF2EX* GF2EX_add(const struct GF2EX* x, const struct GF2EX* y)
-{
-  GF2EX *z = new GF2EX();
-  add(*z, *x, *y);
-  return z;
-}
-
-struct GF2EX* GF2EX_sub(const struct GF2EX* x, const struct GF2EX* y)
-{
-  GF2EX *z = new GF2EX();
-  sub(*z, *x, *y);
-  return z;
-}
-
-struct GF2EX* GF2EX_pow(const struct GF2EX* x, long e) 
-{
-  GF2EX *z = new GF2EX();
-  power(*z, *x, e);
-  return z;
-}
-
-int GF2EX_is_one(struct GF2EX* x)
-{
-  return IsOne(*x);
-}
-
-int GF2EX_is_zero(struct GF2EX* x)
-{
-  return IsZero(*x);
-}
-
-struct GF2EX* GF2EX_neg(struct GF2EX* x)
-{
-  return new GF2EX(-(*x));
-}
-
-struct GF2EX* GF2EX_copy(struct GF2EX* x)
-{
-  GF2EX *z = new GF2EX(*x);
-  return z;
-}
-
-
-/** 
- * mat_GF2E
- *
- * @author Martin Albrecht <malb@informatik.uni-bremen.de>
- *
- * @versions 2006-01 malb
- *           initial version (based on code by William Stein)
- */
-
-
-
-mat_GF2E* new_mat_GF2E(long nrows, long ncols) {
-  mat_GF2E* x = new mat_GF2E;
-  x->SetDims(nrows, ncols);
-  return x;
-}
-
-void del_mat_GF2E(mat_GF2E* x) {
-  delete x;
-}
-
-char* mat_GF2E_to_str(mat_GF2E* x) 
-{
-  ostringstream instore;
-  instore << (*x);
-  int n = strlen(instore.str().data());
-  char* buf = new char[n+1];
-  strcpy(buf, instore.str().data());
-  return buf;
-}
-
-struct mat_GF2E* mat_GF2E_mul(const struct mat_GF2E* x, const struct mat_GF2E* y)
-{
-  mat_GF2E *z = new mat_GF2E();
-  mul(*z, *x, *y);
-  return z;
-}
-
-struct mat_GF2E* mat_GF2E_add(const struct mat_GF2E* x, const struct mat_GF2E* y)
-{
-  mat_GF2E *z = new mat_GF2E();
-  add(*z, *x, *y);
-  return z;
-}
-
-struct mat_GF2E* mat_GF2E_sub(const struct mat_GF2E* x, const struct mat_GF2E* y)
-{
-  mat_GF2E *z = new mat_GF2E();
-  sub(*z, *x, *y);
-  return z;
-}
-
-struct mat_GF2E* mat_GF2E_pow(const struct mat_GF2E* x, long e) 
-{
-  mat_GF2E *z = new mat_GF2E();
-  power(*z, *x, e);
-  return z;
-}
-
-long mat_GF2E_nrows(const struct mat_GF2E* x)
-{
-  return x->NumRows();
-}
-
-
-long mat_GF2E_ncols(const struct mat_GF2E* x)
-{
-  return x->NumCols();
-}
-
-void mat_GF2E_setitem(struct mat_GF2E* x, int i, int j, const struct GF2E* z)
-{
-  (*x)[i][j] = *z;
-}
-
-struct GF2E* mat_GF2E_getitem(const struct mat_GF2E* x, int i, int j)
-{
-  return new GF2E((*x)(i,j));
-}
- 
-struct GF2E* mat_GF2E_determinant(const struct mat_GF2E* x)
-{
-  GF2E* d = new GF2E();
-  determinant(*d, *x);
-  return d;
-}
-
-long mat_GF2E_gauss(struct mat_GF2E *x, long w)
-{
-  if(w==0) {
-    return gauss(*x);
-  } else {
-    return gauss(*x, w);
-  }
-}
-
-long mat_GF2E_is_zero(struct mat_GF2E *x) {
-  return IsZero(*x);
-}
-
-struct mat_GF2E* mat_GF2E_transpose(const struct mat_GF2E* x) {
-  mat_GF2E *y = new mat_GF2E();
-  transpose(*y,*x);
-  return y;
-}
-
-ZZ_pContext* ZZ_pContext_new(ZZ *p)
-{
-	return new ZZ_pContext(*p);
-}
-
-ZZ_pContext* ZZ_pContext_construct(void *mem, ZZ *p)
-{
-	return new(mem) ZZ_pContext(*p);
-}
-
-void ZZ_pContext_restore(ZZ_pContext *ctx)
-{
-	ctx->restore();
-}
Index: _lib/ntl_wrap.h
===================================================================
--- c_lib/ntl_wrap.h	(revision 6239)
+++ 	(revision )
@@ -1,374 +1,0 @@
-#ifdef __cplusplus
-#include <NTL/ZZ.h>
-#include <NTL/ZZX.h>
-#include <NTL/ZZ_pXFactoring.h>
-#include <NTL/ZZXFactoring.h>
-#include <NTL/mat_ZZ.h>
-#include <NTL/mat_poly_ZZ.h>
-#include <NTL/GF2E.h>
-#include <NTL/GF2X.h>
-#include <NTL/GF2EX.h>
-#include <NTL/mat_GF2E.h>
-#include <NTL/HNF.h>
-#include <gmp.h>
-using namespace NTL;
-#endif
-
-#ifdef __cplusplus
-#define EXTERN extern "C"
-#else 
-#define EXTERN
-#endif
-
-#include "ccobject.h"
-
-EXTERN void del_charstar(char*);
-
-
-////////  ZZ //////////
-
-#ifndef __cplusplus
-struct ZZ;
-#endif
-
-EXTERN struct ZZ* new_ZZ(void);
-EXTERN void del_ZZ(struct ZZ* x);
-EXTERN struct ZZ* str_to_ZZ(const char* s);
-EXTERN char* ZZ_to_str(const struct ZZ* x);
-EXTERN int ZZ_to_int(const struct ZZ* x);
-EXTERN struct ZZ* int_to_ZZ(int value);
-EXTERN void ZZ_to_mpz(mpz_t* output, const struct ZZ* x);
-EXTERN void mpz_to_ZZ(struct ZZ *output, const mpz_t* x);
-EXTERN void ZZ_set_from_int(struct ZZ* x, int value);
-EXTERN struct ZZ* ZZ_add(const struct ZZ* x, const struct ZZ* y);
-EXTERN struct ZZ* ZZ_sub(const struct ZZ* x, const struct ZZ* y);
-EXTERN struct ZZ* ZZ_mul(const struct ZZ* x, const struct ZZ* y);
-EXTERN struct ZZ* ZZ_pow(const struct ZZ* x, long e);
-EXTERN int ZZ_equal(struct ZZ* x, struct ZZ* y);
-EXTERN int ZZ_is_zero(struct ZZ*x );
-EXTERN int ZZ_is_one(struct ZZ*x );
-EXTERN struct ZZ* ZZ_neg(struct ZZ* x);
-EXTERN struct ZZ* ZZ_copy(struct ZZ* x);
-/*Random-number generation */
-EXTERN void setSeed(const struct ZZ* n);
-EXTERN struct ZZ* ZZ_randomBnd(const struct ZZ* x);
-EXTERN struct ZZ* ZZ_randomBits(long n);
-
-
-////////  ZZ_p //////////
-
-#ifndef __cplusplus
-struct ZZ_p;
-#endif
-
-EXTERN struct ZZ_p* new_ZZ_p(void);
-EXTERN void del_ZZ_p(struct ZZ_p* x);
-EXTERN struct ZZ_p* str_to_ZZ_p(const char* s);
-EXTERN char* ZZ_p_to_str(const struct ZZ_p* x);
-EXTERN int ZZ_p_to_int(const struct ZZ_p* x);
-EXTERN struct ZZ_p* int_to_ZZ_p(int value);
-EXTERN void ZZ_p_set_from_int(struct ZZ_p* x, int value);
-EXTERN struct ZZ_p* ZZ_p_add(const struct ZZ_p* x, const struct ZZ_p* y);
-EXTERN struct ZZ_p* ZZ_p_sub(const struct ZZ_p* x, const struct ZZ_p* y);
-EXTERN struct ZZ_p* ZZ_p_mul(const struct ZZ_p* x, const struct ZZ_p* y);
-EXTERN struct ZZ_p* ZZ_p_pow(const struct ZZ_p* x, long e);
-EXTERN int ZZ_p_is_zero(struct ZZ_p*x );
-EXTERN int ZZ_p_is_one(struct ZZ_p*x );
-EXTERN void ntl_ZZ_set_modulus(struct ZZ* x);
-EXTERN int ZZ_p_eq(struct ZZ_p* x, struct ZZ_p* y);
-EXTERN struct ZZ_p* ZZ_p_inv(struct ZZ_p* x);
-EXTERN struct ZZ_p* ZZ_p_neg(struct ZZ_p* x);
-EXTERN struct ZZ_p* ZZ_p_random(void);
-EXTERN void ZZ_p_modulus(struct ZZ* mod, const struct ZZ_p* x);
-
-
-EXTERN struct ZZ_pContext* ZZ_pContext_new(struct ZZ* p);
-EXTERN struct ZZ_pContext* ZZ_pContext_construct(void* mem, struct ZZ* p);
-EXTERN void ZZ_pContext_restore(struct ZZ_pContext* ctx);
-
-//////// ZZX //////////
-#ifndef __cplusplus
-struct ZZX;
-#endif
-
-EXTERN struct ZZX* ZZX_init();
-EXTERN struct ZZX* str_to_ZZX(const char* s);
-EXTERN char* ZZX_repr(struct ZZX* x);
-EXTERN void ZZX_dealloc(struct ZZX* x);
-EXTERN struct ZZX* ZZX_copy(struct ZZX* x);
-EXTERN void ZZX_setitem(struct ZZX* x, long i, const char* a);
-EXTERN void ZZX_setitem_from_int(struct ZZX* x, long i, int value);
-EXTERN char* ZZX_getitem(struct ZZX* x, long i);  
-EXTERN int ZZX_getitem_as_int(struct ZZX* x, long i);
-EXTERN void ZZX_getitem_as_mpz(mpz_t* output, struct ZZX* x, long i);
-EXTERN struct ZZX* ZZX_add(struct ZZX* x, struct ZZX* y);
-EXTERN struct ZZX* ZZX_sub(struct ZZX* x, struct ZZX* y);
-EXTERN struct ZZX* ZZX_mul(struct ZZX* x, struct ZZX* y);
-EXTERN struct ZZX* ZZX_div(struct ZZX* x, struct ZZX* y, int* divisible);
-EXTERN struct ZZX* ZZX_mod(struct ZZX* x, struct ZZX* y);
-EXTERN void ZZX_quo_rem(struct ZZX* x, struct ZZX* other, struct ZZX** r, struct ZZX** q);
-EXTERN struct ZZX* ZZX_square(struct ZZX* x);
-EXTERN int ZZX_equal(struct ZZX* x, struct ZZX* y);
-EXTERN int ZZX_is_zero(struct ZZX* x);
-EXTERN int ZZX_is_one(struct ZZX* x);
-EXTERN int ZZX_is_monic(struct ZZX* x);
-EXTERN struct ZZX* ZZX_neg(struct ZZX* x);
-EXTERN struct ZZX* ZZX_left_shift(struct ZZX* x, long n);
-EXTERN struct ZZX* ZZX_right_shift(struct ZZX* x, long n);
-EXTERN char* ZZX_content(struct ZZX* x);
-EXTERN struct ZZX* ZZX_primitive_part(struct ZZX* x);
-EXTERN void ZZX_pseudo_quo_rem(struct ZZX* x, struct ZZX* y, struct ZZX** r, struct ZZX** q);
-EXTERN struct ZZX* ZZX_gcd(struct ZZX* x, struct ZZX* y);
-EXTERN void ZZX_xgcd(struct ZZX* x, struct ZZX* y, struct ZZ** r, struct ZZX** s, struct ZZX** t, int proof);
-EXTERN long ZZX_degree(struct ZZX* x);
-EXTERN struct ZZ* ZZX_leading_coefficient(struct ZZX* x);
-EXTERN char* ZZX_constant_term(struct ZZX* x);
-EXTERN void ZZX_set_x(struct ZZX* x);
-EXTERN int ZZX_is_x(struct ZZX* x);
-EXTERN struct ZZX* ZZX_derivative(struct ZZX* x);
-EXTERN struct ZZX* ZZX_reverse(struct ZZX* x);
-EXTERN struct ZZX* ZZX_reverse_hi(struct ZZX* x, int hi);
-EXTERN struct ZZX* ZZX_truncate(struct ZZX* x, long m);
-EXTERN struct ZZX* ZZX_multiply_and_truncate(struct ZZX* x, struct ZZX* y, long m);
-EXTERN struct ZZX* ZZX_square_and_truncate(struct ZZX* x, long m);
-EXTERN struct ZZX* ZZX_invert_and_truncate(struct ZZX* x, long m);
-EXTERN struct ZZX* ZZX_multiply_mod(struct ZZX* x, struct ZZX* y,  struct ZZX* modulus);
-EXTERN struct ZZ* ZZX_trace_mod(struct ZZX* x, struct ZZX* y);
-/* EXTERN struct ZZ* ZZX_polyeval(struct ZZX* f, struct ZZ* a); */
-EXTERN char* ZZX_trace_list(struct ZZX* x);
-EXTERN struct ZZ* ZZX_resultant(struct ZZX* x, struct ZZX* y, int proof);
-EXTERN struct ZZ* ZZX_norm_mod(struct ZZX* x, struct ZZX* y, int proof);
-EXTERN struct ZZ* ZZX_discriminant(struct ZZX* x, int proof);
-EXTERN struct ZZX* ZZX_charpoly_mod(struct ZZX* x, struct ZZX* y, int proof);
-EXTERN struct ZZX* ZZX_minpoly_mod(struct ZZX* x, struct ZZX* y);
-EXTERN void ZZX_clear(struct ZZX* x);
-EXTERN void ZZX_preallocate_space(struct ZZX* x, long n);
-
-//////// ZZXFactoring //////////
-
-// OUTPUT: v -- pointer to list of n ZZX elements (the squarefree factors)
-//         e -- point to list of e longs (the exponents)
-//         n -- length of above two lists
-//  The lists v and e are mallocd, and must be freed by the calling code.
-EXTERN void ZZX_square_free_decomposition(struct ZZX*** v, long** e, long* n, struct ZZX* x);
-
-
-//////// ZZ_pX //////////
-#ifndef __cplusplus
-struct ZZ_pX;
-#endif
-
-EXTERN struct ZZ_pX* ZZ_pX_init();
-EXTERN struct ZZ_pX* str_to_ZZ_pX(const char* s);
-EXTERN char* ZZ_pX_repr(struct ZZ_pX* x);
-EXTERN void ZZ_pX_dealloc(struct ZZ_pX* x);
-EXTERN struct ZZ_pX* ZZ_pX_copy(struct ZZ_pX* x);
-EXTERN void ZZ_pX_setitem(struct ZZ_pX* x, long i, const char* a);
-EXTERN void ZZ_pX_setitem_from_int(struct ZZ_pX* x, long i, int value);
-EXTERN char* ZZ_pX_getitem(struct ZZ_pX* x, long i);  
-EXTERN int ZZ_pX_getitem_as_int(struct ZZ_pX* x, long i);
-EXTERN struct ZZ_pX* ZZ_pX_add(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN struct ZZ_pX* ZZ_pX_sub(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN struct ZZ_pX* ZZ_pX_mul(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN struct ZZ_pX* ZZ_pX_div(struct ZZ_pX* x, struct ZZ_pX* y, int* divisible);
-EXTERN struct ZZ_pX* ZZ_pX_mod(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN void ZZ_pX_quo_rem(struct ZZ_pX* x, struct ZZ_pX* other, struct ZZ_pX** r, struct ZZ_pX** q);
-EXTERN struct ZZ_pX* ZZ_pX_square(struct ZZ_pX* x);
-EXTERN int ZZ_pX_equal(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN int ZZ_pX_is_zero(struct ZZ_pX* x);
-EXTERN int ZZ_pX_is_one(struct ZZ_pX* x);
-EXTERN int ZZ_pX_is_monic(struct ZZ_pX* x);
-EXTERN struct ZZ_pX* ZZ_pX_neg(struct ZZ_pX* x);
-EXTERN struct ZZ_pX* ZZ_pX_left_shift(struct ZZ_pX* x, long n);
-EXTERN struct ZZ_pX* ZZ_pX_right_shift(struct ZZ_pX* x, long n);
-EXTERN void ZZ_pX_quo_rem(struct ZZ_pX* x, struct ZZ_pX* y, struct ZZ_pX** r, struct ZZ_pX** q);
-EXTERN struct ZZ_pX* ZZ_pX_gcd(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN void ZZ_pX_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b);
-EXTERN void ZZ_pX_plain_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b);
-EXTERN long ZZ_pX_degree(struct ZZ_pX* x);
-EXTERN struct ZZ_p* ZZ_pX_leading_coefficient(struct ZZ_pX* x);
-EXTERN char* ZZ_pX_constant_term(struct ZZ_pX* x);
-EXTERN void ZZ_pX_set_x(struct ZZ_pX* x);
-EXTERN int ZZ_pX_is_x(struct ZZ_pX* x);
-EXTERN struct ZZ_pX* ZZ_pX_derivative(struct ZZ_pX* x);
-EXTERN struct ZZ_pX* ZZ_pX_reverse(struct ZZ_pX* x);
-EXTERN struct ZZ_pX* ZZ_pX_reverse_hi(struct ZZ_pX* x, int hi);
-EXTERN struct ZZ_pX* ZZ_pX_truncate(struct ZZ_pX* x, long m);
-EXTERN struct ZZ_pX* ZZ_pX_multiply_and_truncate(struct ZZ_pX* x, struct ZZ_pX* y, long m);
-EXTERN struct ZZ_pX* ZZ_pX_square_and_truncate(struct ZZ_pX* x, long m);
-EXTERN struct ZZ_pX* ZZ_pX_invert_and_truncate(struct ZZ_pX* x, long m);
-EXTERN struct ZZ_pX* ZZ_pX_multiply_mod(struct ZZ_pX* x, struct ZZ_pX* y,  struct ZZ_pX* modulus);
-EXTERN struct ZZ_p* ZZ_pX_trace_mod(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN char* ZZ_pX_trace_list(struct ZZ_pX* x);
-EXTERN struct ZZ_p* ZZ_pX_resultant(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN struct ZZ_p* ZZ_pX_norm_mod(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN struct ZZ_pX* ZZ_pX_charpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN struct ZZ_pX* ZZ_pX_minpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y);
-EXTERN void ZZ_pX_clear(struct ZZ_pX* x);
-EXTERN void ZZ_pX_preallocate_space(struct ZZ_pX* x, long n);
-
-// Factoring elements of ZZ_pX:
-// OUTPUT: v -- pointer to list of n ZZ_pX elements (the irred factors)
-//         e -- point to list of e longs (the exponents)
-//         n -- length of above two lists
-//  The lists v and e are mallocd, and must be freed by the calling code.
-EXTERN void ZZ_pX_factor(struct ZZ_pX*** v, long** e, long* n, struct ZZ_pX* x, long verbose);
-EXTERN void ZZ_pX_linear_roots(struct ZZ_p*** v, long* n, struct ZZ_pX* f);
-
-
-
-//////// mat_ZZ //////////
-
-#ifndef __cplusplus
-struct mat_ZZ;
-#endif
-
-EXTERN void mat_ZZ_SetDims(struct mat_ZZ* mZZ, long nrows, long ncols);
-EXTERN struct mat_ZZ* new_mat_ZZ(long nrows, long ncols);
-EXTERN void del_mat_ZZ(struct mat_ZZ* x);
-EXTERN char* mat_ZZ_to_str(struct mat_ZZ* x);
-EXTERN struct mat_ZZ* mat_ZZ_add(const struct mat_ZZ* x, const struct mat_ZZ* y);
-EXTERN struct mat_ZZ* mat_ZZ_sub(const struct mat_ZZ* x, const struct mat_ZZ* y);
-EXTERN struct mat_ZZ* mat_ZZ_mul(const struct mat_ZZ* x, const struct mat_ZZ* y);
-EXTERN struct mat_ZZ* mat_ZZ_pow(const struct mat_ZZ* x, long e);
-EXTERN long mat_ZZ_nrows(const struct mat_ZZ* x);
-EXTERN long mat_ZZ_ncols(const struct mat_ZZ* x);
-EXTERN void mat_ZZ_setitem(struct mat_ZZ* x, int i, int j, const struct ZZ* z);
-EXTERN struct ZZ* mat_ZZ_getitem(const struct mat_ZZ* x, int i, int j);
-EXTERN struct ZZ* mat_ZZ_determinant(const struct mat_ZZ* x, long deterministic);
-EXTERN struct mat_ZZ* mat_ZZ_HNF(const struct mat_ZZ* A, const struct ZZ* D);
-EXTERN struct ZZX* mat_ZZ_charpoly(const struct mat_ZZ* A);
-EXTERN long mat_ZZ_LLL(struct ZZ **det, struct mat_ZZ *x, long a, long b, long verbose);
-EXTERN long mat_ZZ_LLL_U(struct ZZ **det, struct mat_ZZ *x, struct mat_ZZ *U, long a, long b, long verbose);
-
-/* //////// ZZ_p ////////// */
-/* #ifndef __cplusplus */
-/* struct ZZ_p; */
-/* #endif */
-
-/* EXTERN void ZZ_p_set_modulus(const struct ZZ* p); */
-/* EXTERN struct ZZ_p* new_ZZ_p(void); */
-/* EXTERN struct ZZ_p* str_to_ZZ_p(const char* s); */
-/* EXTERN void del_ZZ_p(struct ZZ_p* x); */
-/* EXTERN char* ZZ_p_to_str(const struct ZZ_p* x); */
-/* EXTERN struct ZZ_p* ZZ_p_add(const struct ZZ_p* x, const struct ZZ_p* y); */
-/* EXTERN struct ZZ_p* ZZ_p_sub(const struct ZZ_p* x, const struct ZZ_p* y); */
-/* EXTERN struct ZZ_p* ZZ_p_mul(const struct ZZ_p* x, const struct ZZ_p* y); */
-/* EXTERN struct ZZ_p* ZZ_p_pow(const struct ZZ_p* x, long e); */
-/* EXTERN int ZZ_p_is_zero(struct ZZ_p*x ); */
-/* EXTERN int ZZ_p_is_one(struct ZZ_p*x ); */
-
-
-//////// ZZ_pE //////////
-#ifndef __cplusplus
-struct ZZ_pE;
-#endif
-
-// EXTERN struct ZZ_pE* new_ZZ_pE
-
-
-
-//////// ZZ_pEX //////////
-
-//#ifndef __cplusplus
-//struct ZZ_pEX;
-//#endif
-
-//EXTERN struct ZZ_pEX* new_ZZ_pEX
-
-/////// GF2X ////////////////
-#ifndef __cplusplus
-struct GF2X;
-#endif
-
-EXTERN struct GF2X* new_GF2X(void);
-EXTERN void del_GF2X(struct GF2X* x);
-EXTERN struct GF2X* str_to_GF2X(const char* s);
-EXTERN char* GF2X_to_str(const struct GF2X* x);
-EXTERN struct GF2X* GF2X_add(const struct GF2X* x, const struct GF2X* y);
-EXTERN struct GF2X* GF2X_sub(const struct GF2X* x, const struct GF2X* y);
-EXTERN struct GF2X* GF2X_mul(const struct GF2X* x, const struct GF2X* y);
-EXTERN struct GF2X* GF2X_pow(const struct GF2X* x, long e);
-EXTERN int GF2X_eq(const struct GF2X* x, const struct GF2X* y);
-EXTERN int GF2X_is_zero(struct GF2X*x );
-EXTERN int GF2X_is_one(struct GF2X*x );
-EXTERN struct GF2X* GF2X_neg(struct GF2X* x);
-EXTERN struct GF2X* GF2X_copy(struct GF2X* x);
-EXTERN long GF2X_deg(struct GF2X* x);
-EXTERN void GF2X_hex(long h);
-EXTERN char *GF2X_to_bin(const struct GF2X* x);
-EXTERN char *GF2X_to_hex(const struct GF2X* x);
-
-
-/////// GF2E ////////////////
-
-#ifndef __cplusplus
-struct GF2E;
-#endif
-
-EXTERN struct GF2E* new_GF2E(void);
-EXTERN void del_GF2E(struct GF2E* x);
-EXTERN struct GF2E* str_to_GF2E(const char* s);
-EXTERN char *GF2E_to_str(const struct GF2E* x);
-EXTERN struct GF2E* GF2E_add(const struct GF2E* x, const struct GF2E* y);
-EXTERN struct GF2E* GF2E_sub(const struct GF2E* x, const struct GF2E* y);
-EXTERN struct GF2E* GF2E_mul(const struct GF2E* x, const struct GF2E* y);
-EXTERN struct GF2E* GF2E_pow(const struct GF2E* x, long e);
-EXTERN int GF2E_eq(const struct GF2E* x, const struct GF2E* y);
-EXTERN int GF2E_is_zero(struct GF2E*x );
-EXTERN int GF2E_is_one(struct GF2E*x );
-EXTERN struct GF2E* GF2E_neg(struct GF2E* x);
-EXTERN struct GF2E* GF2E_copy(struct GF2E* x);
-EXTERN void ntl_GF2E_set_modulus(struct GF2X* x);
-EXTERN long GF2E_degree();
-EXTERN const struct GF2X *GF2E_modulus();
-EXTERN struct GF2E *GF2E_random(void);
-EXTERN long GF2E_trace(struct GF2E *x);
-EXTERN const struct GF2X *GF2E_ntl_GF2X(struct GF2E *x);
-
-#ifndef __cplusplus
-struct GF2EX;
-#endif
-
-EXTERN struct GF2EX* new_GF2EX(void);
-EXTERN void del_GF2EX(struct GF2EX* x);
-EXTERN struct GF2EX* str_to_GF2EX(const char* s);
-EXTERN char* GF2EX_to_str(const struct GF2EX* x);
-EXTERN struct GF2EX* GF2EX_add(const struct GF2EX* x, const struct GF2EX* y);
-EXTERN struct GF2EX* GF2EX_sub(const struct GF2EX* x, const struct GF2EX* y);
-EXTERN struct GF2EX* GF2EX_mul(const struct GF2EX* x, const struct GF2EX* y);
-EXTERN struct GF2EX* GF2EX_pow(const struct GF2EX* x, long e);
-EXTERN int GF2EX_is_zero(struct GF2EX*x );
-EXTERN int GF2EX_is_one(struct GF2EX*x );
-EXTERN struct GF2EX* GF2EX_neg(struct GF2EX* x);
-EXTERN struct GF2EX* GF2EX_copy(struct GF2EX* x);
-
-
-//////// mat_GF2E //////////
-
-#ifndef __cplusplus
-struct mat_GF2E;
-#endif
-
-void mat_GF2E_SetDims(struct mat_GF2E* mGF2E, long nrows, long ncols);
-EXTERN struct mat_GF2E* new_mat_GF2E(long nrows, long ncols);
-EXTERN void del_mat_GF2E(struct mat_GF2E* x);
-EXTERN char* mat_GF2E_to_str(struct mat_GF2E* x);
-EXTERN struct mat_GF2E* mat_GF2E_add(const struct mat_GF2E* x, const struct mat_GF2E* y);
-EXTERN struct mat_GF2E* mat_GF2E_sub(const struct mat_GF2E* x, const struct mat_GF2E* y);
-EXTERN struct mat_GF2E* mat_GF2E_mul(const struct mat_GF2E* x, const struct mat_GF2E* y);
-EXTERN struct mat_GF2E* mat_GF2E_pow(const struct mat_GF2E* x, long e);
-EXTERN long mat_GF2E_nrows(const struct mat_GF2E* x);
-EXTERN long mat_GF2E_ncols(const struct mat_GF2E* x);
-EXTERN void mat_GF2E_setitem(struct mat_GF2E* x, int i, int j, const struct GF2E* z);
-EXTERN struct GF2E* mat_GF2E_getitem(const struct mat_GF2E* x, int i, int j);
-EXTERN struct GF2E* mat_GF2E_determinant(const struct mat_GF2E* x);
-EXTERN long mat_GF2E_gauss(struct mat_GF2E *x, long w);
-EXTERN long mat_GF2E_is_zero(struct mat_GF2E *x);
-EXTERN struct mat_GF2E* mat_GF2E_transpose(const struct mat_GF2E* x);
-
-
-
-//EXTERN struct mat_GF2E* mat_GF2E_HNF(const struct mat_GF2E* A, const struct GF2E* D);
-//EXTERN struct GF2EX* mat_GF2E_charpoly(const struct mat_GF2E* A);
- 
Index: c_lib/src/ZZ_pylong.cpp
===================================================================
--- c_lib/src/ZZ_pylong.cpp	(revision 6597)
+++ c_lib/src/ZZ_pylong.cpp	(revision 6597)
@@ -0,0 +1,43 @@
+/*****************************************************************************
+#       Copyright (C) 2007 William Stein <wstein@gmail.com>
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************/
+
+/*  Author:  Joel B. Mohler <joel@kiwistrawberry.us>
+			 2007-06-17                                                      */
+
+#include "ZZ_pylong.h"
+#include "ntl_wrap.h"
+extern "C" {
+    #include "mpz_pylong.h"
+}
+
+using namespace NTL;
+
+/* ZZ -> pylong conversion */
+PyObject * ZZ_get_pylong(ZZ &z)
+{
+    mpz_t temp;
+    mpz_init(temp);
+    ZZ_to_mpz( &temp, &z );
+    return mpz_get_pylong( temp );
+}
+
+/* pylong -> ZZ conversion */
+int ZZ_set_pylong(ZZ &z, PyObject * ll)
+{
+    mpz_t temp;
+    mpz_init(temp);
+    mpz_set_pylong( temp, ll );
+    mpz_to_ZZ( &z, &temp );
+}
Index: c_lib/src/convert.c
===================================================================
--- c_lib/src/convert.c	(revision 6884)
+++ c_lib/src/convert.c	(revision 6884)
@@ -0,0 +1,46 @@
+/*
+
+  convert.c
+  2007 Aug 19
+  Author: Craig Citro
+
+  C code behind conversions to and from pari types.
+
+  Currently implemented:
+    Integer <--> t_INT
+
+*/
+
+#include "convert.h"
+
+void t_INT_to_ZZ ( mpz_t value, GEN g )
+{
+  long limbs = 0;
+
+  limbs = lgefint(g) - 2;
+  
+  mpz_realloc2( value, limbs );
+  mpz_import( value, limbs, -1, sizeof(long), 0, 0, int_LSW(g) );
+  
+  if ( signe(g) == -1 )
+    mpz_neg( value, value );
+
+  return;
+}
+
+void ZZ_to_t_INT ( GEN *g, mpz_t value ) 
+{
+  long limbs = 0;
+
+  limbs = mpz_size( value );
+
+  *g = cgetg( limbs+2, t_INT );
+  settyp( *g, t_INT );
+  setlgefint( *g, limbs+2 );
+  setsigne( *g, mpz_sgn(value) );
+
+  mpz_export( int_LSW(*g), NULL, -1, sizeof(long), 0, 0, value );
+
+  return; 
+}
+
Index: c_lib/src/gmp_globals.c
===================================================================
--- c_lib/src/gmp_globals.c	(revision 7015)
+++ c_lib/src/gmp_globals.c	(revision 7015)
@@ -0,0 +1,50 @@
+#include "gmp_globals.h"
+
+mpz_t u, v, q, u0, u1, u2, v0, v1, v2, t0, t1, t2, x, y, ssqr, m2;
+//changed sqr to ssqr due to a collision with ntl
+mpq_t tmp;
+
+mpz_t a1, a2, mod1, mod2, g, s, t, xx;
+
+mpz_t crtrr_a, crtrr_mod;
+
+mpz_t rand_val, rand_n, rand_n1;
+
+gmp_randstate_t rand_state;
+
+void init_mpz_globals() {
+  mpz_init(u);  mpz_init(v); mpz_init(q);
+  mpz_init(u0); mpz_init(u1); mpz_init(u2);
+  mpz_init(v0); mpz_init(v1); mpz_init(v2);
+  mpz_init(t0); mpz_init(t1); mpz_init(t2);
+  mpz_init(x);  mpz_init(y);
+  mpz_init(ssqr);  mpz_init(m2);
+  mpq_init(tmp);
+
+  mpz_init(a1); mpz_init(a2); mpz_init(mod1); mpz_init(mod2);
+  mpz_init(g); mpz_init(s); mpz_init(t); mpz_init(xx);
+
+  mpz_init(crtrr_a); mpz_init(crtrr_mod);
+
+  mpz_init(rand_val); mpz_init(rand_n); mpz_init(rand_n1);
+
+  gmp_randinit_default(rand_state);
+}
+
+void clear_mpz_globals() {
+  mpz_clear(u);  mpz_clear(v); mpz_clear(q);
+  mpz_clear(u0); mpz_clear(u1); mpz_clear(u2);
+  mpz_clear(v0); mpz_clear(v1); mpz_clear(v2);
+  mpz_clear(t0); mpz_clear(t1); mpz_clear(t2);
+  mpz_clear(x);  mpz_clear(y);
+  mpz_clear(ssqr);  mpz_clear(m2);
+  mpq_clear(tmp);
+
+  mpz_clear(a1); mpz_clear(a2); mpz_clear(mod1); mpz_clear(mod2);
+  mpz_clear(g); mpz_clear(s); mpz_clear(t); mpz_clear(xx);
+
+  mpz_clear(crtrr_a); mpz_clear(crtrr_mod);
+
+  mpz_clear(rand_val); mpz_clear(rand_n); mpz_clear(rand_n1);
+}
+
Index: c_lib/src/interrupt.c
===================================================================
--- c_lib/src/interrupt.c	(revision 6597)
+++ c_lib/src/interrupt.c	(revision 6597)
@@ -0,0 +1,145 @@
+/******************************************************************************
+       Copyright (C) 2006 William Stein <wstein@gmail.com>
+                     2006 Martin Albrecht <malb@informatik.uni-bremen.de>
+
+  Distributed under the terms of the GNU General Public License (GPL), Version 2.
+
+  The full text of the GPL is available at:
+                  http://www.gnu.org/licenses/
+
+******************************************************************************/
+
+#include "stdsage.h"
+#include "interrupt.h"
+#include <stdio.h>
+
+struct sage_signals _signals;
+
+void msg(char* s);
+
+void sage_signal_handler(int sig) {
+
+  char *s = _signals.s;
+  _signals.s = NULL;
+
+  //we override the default handler
+  if ( _signals.mpio && 1 ) {
+
+    //what to do?
+
+    switch(sig) {
+
+    case SIGINT:
+      if( s ) {
+	PyErr_SetString(PyExc_KeyboardInterrupt, s);
+      } else {
+	PyErr_SetString(PyExc_KeyboardInterrupt, "");
+      }
+      break;
+
+    case SIGALRM:
+      if( s ) {
+	PyErr_SetString(PyExc_KeyboardInterrupt, s);
+      } else {
+	PyErr_SetString(PyExc_KeyboardInterrupt, "Alarm received");
+      }
+      break;
+
+    default:
+      if( s ) {
+	PyErr_SetString(PyExc_RuntimeError, s);
+      } else {
+	PyErr_SetString(PyExc_RuntimeError, "");
+      }
+    }
+
+
+    //notify 'calling' function
+
+    _signals.mpio |= 4;
+
+    signal(sig, sage_signal_handler);
+    //where to go next?
+    if ( _signals.mpio & 2 ) {
+      siglongjmp(_signals.env, sig);
+    } else {
+      //this case shouldn't happen as _sig_[on|off]_short is disabled
+      return;
+    }
+    
+  } else {
+
+    //we use the default handler
+    _signals.mpio = 0;
+
+    switch(sig) {
+    case SIGSEGV: 
+      sig_handle_sigsegv(sig);
+      break;
+    case SIGBUS: 
+      sig_handle_sigbus(sig);
+      break;
+    case SIGFPE: 
+      sig_handle_sigfpe(sig);
+      break;
+    default:
+      _signals.python_handler(sig);
+      break;
+    };
+    
+    signal(sig, sage_signal_handler);
+  }
+}
+
+void setup_signal_handler(void) {
+  void *tmp = NULL;
+
+  //we need to make sure not to store our own signal handler as the old one
+  //because that would cause infinite recursion if an error occurs and we are
+  //not supposed to catch it.
+  tmp = signal(SIGINT, sage_signal_handler);
+
+  if(sage_signal_handler != tmp) {
+    _signals.python_handler = tmp;
+  }
+  
+  _signals.s = NULL;
+
+/*  signal(SIGBUS, sig_handle_sigbus); */
+  signal(SIGBUS, sage_signal_handler);
+
+  signal(SIGALRM,sage_signal_handler);
+  signal(SIGSEGV,sage_signal_handler);
+  signal(SIGABRT,sage_signal_handler);
+  signal(SIGFPE,sage_signal_handler);
+}
+
+
+void msg(char* s) {
+  fprintf(stderr, "\n\n------------------------------------------------------------\n");
+  fprintf(stderr, s);
+  fprintf(stderr, "This probably occured because a *compiled* component\n");
+  fprintf(stderr, "of SAGE has a bug in it (typically accessing invalid memory)\n");
+  fprintf(stderr, "or is not properly wrapped with _sig_on, _sig_off.\n");
+  fprintf(stderr, "You might want to run SAGE under gdb with 'sage -gdb' to debug this.\n");
+  fprintf(stderr, "SAGE will now terminate (sorry).\n");
+  fprintf(stderr, "------------------------------------------------------------\n\n");
+}
+
+void sig_handle_sigsegv(int n) {
+  msg("Unhandled SIGSEGV: A segmentation fault occured in SAGE.\n");
+  PyErr_SetString(PyExc_KeyboardInterrupt, "");
+  exit(1);
+}
+
+void sig_handle_sigbus(int n) {
+  msg("Unhandled SIGBUS: A bus error occured in SAGE.\n");
+  PyErr_SetString(PyExc_KeyboardInterrupt, "");
+  exit(1);
+}
+
+void sig_handle_sigfpe(int n) {
+  msg("Unhandled SIGFPE: An unhandled floating point exception occured in SAGE.\n");
+  PyErr_SetString(PyExc_KeyboardInterrupt, "");
+  exit(1);
+}
Index: c_lib/src/mpn_pylong.c
===================================================================
--- c_lib/src/mpn_pylong.c	(revision 6006)
+++ c_lib/src/mpn_pylong.c	(revision 6006)
@@ -0,0 +1,253 @@
+/* mpn <-> pylong conversion and "pythonhash" for mpn
+ *
+ * Author:  Gonzalo TornarÃ­a <tornaria@math.utexas.edu>
+ * Date:    March 2006
+ * License: GPL v2
+ *
+ * the code to change the base to 2^SHIFT is based on the function
+ * mpn_get_str from GNU MP, but the new bugs are mine
+ *
+ * this is free software: if it breaks, you get to keep all the pieces
+ */
+
+#include "mpn_pylong.h"
+
+/* This code assumes that SHIFT < GMP_NUMB_BITS */
+#if SHIFT >= GMP_NUMB_BITS
+#error "Python limb larger than GMP limb !!!"
+#endif
+
+/* Use these "portable" (I hope) sizebits functions
+ * We could implement this in terms of count_leading_zeros from GMP,
+ * but it is not exported !
+ */
+static const
+unsigned char
+__sizebits_tab[128] =
+{
+  0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+};
+
+#if GMP_LIMB_BITS > 64
+#error "word size > 64 unsupported"
+#endif
+
+static inline
+unsigned long
+mpn_sizebits(mp_ptr up, mp_size_t un) {
+  unsigned long cnt;
+  mp_limb_t x;
+  if (un==0) return 0;
+  cnt = (un - 1) * GMP_NUMB_BITS;
+  x = up[un - 1];
+#if GMP_LIMB_BITS > 32
+  if ((x >> 32) != 0) { x >>= 32; cnt += 32; }
+#endif
+#if GMP_LIMB_BITS > 16
+  if ((x >> 16) != 0) { x >>= 16; cnt += 16; }
+#endif
+#if GMP_LIMB_BITS > 8
+  if ((x >>  8) != 0) { x >>=  8; cnt += 8; }
+#endif
+  return cnt + ((x & 0x80) ? 8 : __sizebits_tab[x]);
+}
+
+static inline
+unsigned long
+pylong_sizebits(digit *digits, py_size_t size) {
+  unsigned long cnt;
+  digit x;
+  if (size==0) return 0;
+  cnt = (size - 1) * SHIFT;
+  x = digits[size - 1];
+#if SHIFT > 32
+  if ((x >> 32) != 0) { x >>= 32; cnt += 32; }
+#endif
+#if SHIFT > 16
+  if ((x >> 16) != 0) { x >>= 16; cnt += 16; }
+#endif
+#if SHIFT > 8
+  if ((x >>  8) != 0) { x >>=  8; cnt += 8; }
+#endif
+  return cnt + ((x & 0x80) ? 8 : __sizebits_tab[x]);
+}
+
+
+/* mpn -> pylong conversion */
+
+int
+mpn_pylong_size (mp_ptr up, mp_size_t un)
+{
+  return (mpn_sizebits(up, un) + SHIFT - 1) / SHIFT;
+}
+
+/* this is based from GMP code in mpn/get_str.c */
+
+/* Assume digits points to a chunk of size size
+ * where size >= mpn_pylong_size(up, un)
+ */
+void
+mpn_get_pylong (digit *digits, py_size_t size, mp_ptr up, mp_size_t un)
+{
+  mp_limb_t n1, n0;
+  mp_size_t i;
+  int bit_pos;
+  /* point past the allocated chunk */
+  digit * s = digits + size;
+
+  /* input length 0 is special ! */
+  if (un == 0) {
+    while (size) digits[--size]=0;
+    return;
+  }
+
+  i = un - 1;
+  n1 = up[i];
+  bit_pos = size * SHIFT - i * GMP_NUMB_BITS;
+
+  for (;;)
+    {
+      bit_pos -= SHIFT;
+      while (bit_pos >= 0)
+        {
+          *--s = (n1 >> bit_pos) & MASK;
+          bit_pos -= SHIFT;
+        }
+      if (i == 0)
+        break;
+      n0 = (n1 << -bit_pos) & MASK;
+      n1 = up[--i];
+      bit_pos += GMP_NUMB_BITS;
+      *--s = n0 | (n1 >> bit_pos);
+    }
+}
+
+/* pylong -> mpn conversion */
+
+mp_size_t
+mpn_size_from_pylong (digit *digits, py_size_t size)
+{
+  return (pylong_sizebits(digits, size) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
+}
+
+void
+mpn_set_pylong (mp_ptr up, mp_size_t un, digit *digits, py_size_t size)
+{
+  mp_limb_t n1, d;
+  mp_size_t i;
+  int bit_pos;
+  /* point past the allocated chunk */
+  digit * s = digits + size;
+
+  /* input length 0 is special ! */
+  if (size == 0) {
+    while (un) up[--un]=0;
+    return;
+  }
+
+  i = un - 1;
+  n1 = 0;
+  bit_pos = size * SHIFT - i * GMP_NUMB_BITS;
+
+  for (;;)
+    {
+      bit_pos -= SHIFT;
+      while (bit_pos >= 0)
+        {
+          d = (mp_limb_t) *--s;
+          n1 |= (d << bit_pos) & GMP_NUMB_MASK;
+          bit_pos -= SHIFT;
+        }
+      if (i == 0)
+        break;
+      d = (mp_limb_t) *--s;
+      /* add some high bits of d; maybe none if bit_pos=-SHIFT */
+      up[i--] = n1 | (d & MASK) >> -bit_pos;
+      bit_pos += GMP_NUMB_BITS;
+      n1 = (d << bit_pos) & GMP_NUMB_MASK;
+    }
+  up[0] = n1;
+}
+
+
+/************************************************************/
+
+/* Hashing functions */
+
+#define LONG_BIT_SHIFT  (8*sizeof(long) - SHIFT)
+
+/*
+ * for an mpz, this number has to be multiplied by the sign
+ * also remember to catch -1 and map it to -2 !
+ */
+long
+mpn_pythonhash (mp_ptr up, mp_size_t un)
+{
+  mp_limb_t n1, n0;
+  mp_size_t i;
+  int bit_pos;
+  long x = 0;
+
+  /* input length 0 is special ! */
+  if (un == 0) return 0;
+
+  i = un - 1;
+  n1 = up[i];
+  {
+    unsigned long bits;
+    bits = mpn_sizebits(up, un) + SHIFT - 1;
+    bits -= bits % SHIFT;
+    /* position of the MSW in base 2^SHIFT, counted from the MSW in
+     * the GMP representation (in base 2^GMP_NUMB_BITS)
+     */
+    bit_pos = bits - i * GMP_NUMB_BITS;
+  }
+
+  for (;;)
+    {
+      while (bit_pos >= 0)
+        {
+          /* Force a native long #-bits (32 or 64) circular shift */
+          x = ((x << SHIFT) & ~MASK) | ((x >> LONG_BIT_SHIFT) & MASK);
+          x += (n1 >> bit_pos) & MASK;
+          bit_pos -= SHIFT;
+        }
+      i--;
+      if (i < 0)
+        break;
+      n0 = (n1 << -bit_pos) & MASK;
+      n1 = up[i];
+      bit_pos += GMP_NUMB_BITS;
+      /* Force a native long #-bits (32 or 64) circular shift */
+      x = ((x << SHIFT) & ~MASK) | ((x >> LONG_BIT_SHIFT) & MASK);
+      x += n0 | (n1 >> bit_pos);
+      bit_pos -= SHIFT;
+    }
+
+  return x;
+}
+
+#if 0
+/* This is a *very* bad hash...
+ * If we decide to give up pylong compatibility, we should research to
+ * find a decent (but fast) hash
+ *
+ * Some pointers to start:
+ * <http://www.isthe.com/chongo/tech/comp/fnv/>
+ * <http://www.azillionmonkeys.com/qed/hash.html>
+ * <http://burtleburtle.net/bob/hash/doobs.html>
+ */
+long
+mpn_fasthash (mp_ptr up, mp_size_t un)
+{
+  long x=0;
+  int i=un;
+  while (i)
+    x^=up[--i];
+  return x;
+}
+
+#endif
Index: c_lib/src/mpz_pylong.c
===================================================================
--- c_lib/src/mpz_pylong.c	(revision 6597)
+++ c_lib/src/mpz_pylong.c	(revision 6597)
@@ -0,0 +1,81 @@
+/* mpz <-> pylong conversion and "pythonhash" for mpz
+ *
+ * Author:  Gonzalo TornarÃ­a <tornaria@math.utexas.edu>
+ * Date:    March 2006
+ * License: GPL v2
+ *
+ * this is free software: if it breaks, you get to keep all the pieces
+
+AUTHORS:
+  -- David Harvey (2007-08-18): added mpz_get_pyintlong function
+
+ */
+
+#include "mpn_pylong.h"
+#include "mpz_pylong.h"
+
+/* mpz python hash */
+long
+mpz_pythonhash (mpz_srcptr z)
+{
+  long x = mpn_pythonhash(z->_mp_d, abs(z->_mp_size));
+  if (z->_mp_size < 0)
+    x = -x;
+  if (x == -1)
+    x = -2;
+  return x;
+}
+
+/* mpz -> pylong conversion */
+PyObject *
+mpz_get_pylong(mpz_srcptr z)
+{
+  py_size_t size = mpn_pylong_size(z->_mp_d, abs(z->_mp_size));
+  PyLongObject *l = PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size);
+
+  if (l != NULL)
+  {
+    mpn_get_pylong(l->ob_digit, size, z->_mp_d, abs(z->_mp_size));
+    if (z->_mp_size < 0)
+      l->ob_size = -(l->ob_size);
+  }
+
+  return (PyObject *) l;
+}
+
+/* mpz -> pyint/pylong conversion; if the value fits in a python int, it
+returns a python int (optimised for that pathway), otherwise returns
+a python long */
+PyObject *
+mpz_get_pyintlong(mpz_srcptr z)
+{
+  if (mpz_fits_slong_p(z))
+     return PyInt_FromLong(mpz_get_si(z));
+
+  return mpz_get_pylong(z);
+}
+
+/* pylong -> mpz conversion */
+int
+mpz_set_pylong(mpz_ptr z, PyObject * ll)
+{
+  register PyLongObject * l = (PyLongObject *) ll;
+  mp_size_t size;
+  int i;
+
+  if (l==NULL || !PyLong_Check(l)) {
+    PyErr_BadInternalCall();
+    return -1;
+  }
+  
+  size = mpn_size_from_pylong(l->ob_digit, abs(l->ob_size));
+
+  if (z->_mp_alloc < size)
+    _mpz_realloc (z, size);
+
+  mpn_set_pylong(z->_mp_d, size, l->ob_digit, abs(l->ob_size));
+  z->_mp_size = l->ob_size < 0 ? -size : size;
+
+  return size;
+}
+
Index: c_lib/src/ntl_wrap.cpp
===================================================================
--- c_lib/src/ntl_wrap.cpp	(revision 7049)
+++ c_lib/src/ntl_wrap.cpp	(revision 7049)
@@ -0,0 +1,1173 @@
+#include <iostream>
+#include <sstream>
+using namespace std;
+
+#include "ntl_wrap.h"
+#include <NTL/mat_poly_ZZ.h>
+#include <NTL/LLL.h>
+
+void del_charstar(char* a) {
+  delete[] a;
+}
+
+//////// ZZ //////////
+
+/* Return value is only valid if the result should fit into an int.
+   AUTHOR: David Harvey (2008-06-08) */
+int ZZ_to_int(const ZZ* x)
+{
+  return to_int(*x);
+}
+
+/* Returns a *new* ZZ object.
+   AUTHOR: David Harvey (2008-06-08) */
+struct ZZ* int_to_ZZ(int value)
+{
+  ZZ* output = new ZZ();
+  conv(*output, value);
+  return output;
+}
+
+/* Copies the ZZ into the mpz_t
+   Assumes output has been mpz_init'd.
+   AUTHOR: David Harvey
+           Joel B. Mohler moved the ZZX_getitem_as_mpz code out to this function (2007-03-13) */
+void ZZ_to_mpz(mpz_t* output, const struct ZZ* x)
+{
+    unsigned char stack_bytes[4096];
+    int use_heap;
+    unsigned long size = NumBytes(*x);
+    use_heap = (size > sizeof(stack_bytes));
+    unsigned char* bytes = use_heap ? (unsigned char*) malloc(size) : stack_bytes;
+    BytesFromZZ(bytes, *x, size);
+    mpz_import(*output, size, -1, 1, 0, 0, bytes);
+    if (sign(*x) < 0)
+        mpz_neg(*output, *output);
+    if (use_heap)
+        free(bytes);
+}
+
+// Ok, I know that this is obvious
+// I just wanted to document the appearance of the magic number 8 in the code below
+#define bits_in_byte        8
+
+/* Copies the mpz_t into the ZZ
+   AUTHOR: Joel B. Mohler (2007-03-15) */
+void mpz_to_ZZ(struct ZZ* output, const mpz_t* x)
+{
+    unsigned char stack_bytes[4096];
+    int use_heap;
+    size_t size = (mpz_sizeinbase(*x, 2) + bits_in_byte-1) / bits_in_byte;
+    use_heap = (size > sizeof(stack_bytes));
+    void* bytes = use_heap ? malloc(size) : stack_bytes;
+    size_t words_written;
+    mpz_export(bytes, &words_written, -1, 1, 0, 0, *x);
+    clear(*output);
+    ZZFromBytes(*output, (unsigned char *)bytes, words_written);
+    if (mpz_sgn(*x) < 0)
+        NTL::negate(*output, *output);
+    if (use_heap)
+        free(bytes);
+}
+
+/* Sets given ZZ to value
+   AUTHOR: David Harvey (2008-06-08) */
+void ZZ_set_from_int(ZZ* x, int value)
+{
+  conv(*x, value);
+}
+
+/*Random-number generation */
+
+/*
+void setSeed(const struct ZZ* n)
+{
+  SetSeed(*n);
+}
+ 
+struct ZZ* ZZ_randomBnd(const struct ZZ* n)
+{ 
+  ZZ *z = new ZZ();
+  RandomBnd(*z,*n);
+  return z;
+}
+
+struct ZZ* ZZ_randomBits(long n)
+{ 
+  ZZ *z = new ZZ();
+  RandomBits(*z,n);
+  return z;
+}
+*/
+
+long ZZ_remove(struct ZZ &dest, const struct ZZ &src, const struct ZZ &f)
+{
+    // Based on the code for mpz_remove
+    ZZ fpow[40];            // inexaustible...until year 2020 or so
+    ZZ x, rem;
+    long pwr;
+    int p;
+
+    if (compare(f, 1) <= 0)
+        Error("Division by zero");
+
+    if (compare(src, 0) == 0)
+    {
+        if (src != dest)
+           dest = src;
+        return 0;
+    }
+
+    if (compare(f, 2) == 0)
+    {
+        dest = src;
+        return MakeOdd(dest);
+    }
+
+    /* We could perhaps compute mpz_scan1(src,0)/mpz_scan1(f,0).  It is an
+     upper bound of the result we're seeking.  We could also shift down the
+     operands so that they become odd, to make intermediate values smaller.  */
+
+    pwr = 0;
+    fpow[0] = ZZ(f);
+    dest = src;
+    rem = ZZ();
+    x = ZZ();
+
+    /* Divide by f, f^2, ..., f^(2^k) until we get a remainder for f^(2^k).  */
+    for (p = 0;;p++)
+    {
+        DivRem(x, rem, dest, fpow[p]);
+        if (compare(rem, 0) != 0)
+            break;
+        fpow[p+1] = ZZ();
+        mul(fpow[p+1], fpow[p], fpow[p]);
+        dest = x;
+    }
+
+    pwr = (1 << p) - 1;
+    
+    /* Divide by f^(2^(k-1)), f^(2^(k-2)), ..., f for all divisors that give a
+       zero remainder.  */
+    while (--p >= 0)
+    {
+        DivRem(x, rem, dest, fpow[p]);
+        if (compare(rem, 0) == 0)
+        {
+            pwr += 1 << p;
+            dest = x;
+        }
+    }
+    return pwr;
+}
+
+//////// ZZ_p //////////
+
+/* Return value is only valid if the result should fit into an int.
+   AUTHOR: David Harvey (2008-06-08) */
+int ZZ_p_to_int(const ZZ_p& x )
+{
+  return ZZ_to_int(&rep(x));
+}
+
+/* Returns a *new* ZZ_p object.
+   AUTHOR: David Harvey (2008-06-08) */
+ZZ_p int_to_ZZ_p(int value)
+{
+  ZZ_p r;
+  r = value;
+  return r;
+}
+
+/* Sets given ZZ_p to value
+   AUTHOR: David Harvey (2008-06-08) */
+void ZZ_p_set_from_int(ZZ_p* x, int value)
+{
+  conv(*x, value);
+}
+
+void ZZ_p_modulus(struct ZZ* mod, const struct ZZ_p* x)
+{
+	(*mod) = x->modulus();
+}
+
+struct ZZ_p* ZZ_p_pow(const struct ZZ_p* x, long e) 
+{
+  ZZ_p *z = new ZZ_p();
+  power(*z, *x, e);
+  return z;
+}
+
+void ntl_ZZ_set_modulus(ZZ* x)
+{
+  ZZ_p::init(*x);
+}
+
+ZZ_p* ZZ_p_inv(ZZ_p* x)
+{
+  ZZ_p *z = new ZZ_p();
+  inv(*z, *x);
+  return z;
+}
+
+ZZ_p* ZZ_p_random(void)
+{
+  ZZ_p *z = new ZZ_p();
+  random(*z);
+  return z;
+}
+
+struct ZZ_p* ZZ_p_neg(struct ZZ_p* x)
+{
+  return new ZZ_p(-(*x));
+}
+
+
+
+///////////////////////////////////////////////
+//////// ZZX //////////
+///////////////////////////////////////////////
+
+char* ZZX_repr(struct ZZX* x)
+{
+  ostringstream instore;
+  instore << (*x);
+  int n = strlen(instore.str().data());
+  char* buf = new char[n+1];
+  strcpy(buf, instore.str().data());
+  return buf;
+}
+
+struct ZZX* ZZX_copy(struct ZZX* x) {
+  return new ZZX(*x);
+}
+
+/* Sets ith coefficient of x to value.
+   AUTHOR: David Harvey (2006-06-08) */
+void ZZX_setitem_from_int(struct ZZX* x, long i, int value)
+{
+  SetCoeff(*x, i, value);
+}
+
+/* Returns ith coefficient of x.
+   Return value is only valid if the result should fit into an int.
+   AUTHOR: David Harvey (2006-06-08) */
+int ZZX_getitem_as_int(struct ZZX* x, long i)
+{
+  return ZZ_to_int(&coeff(*x, i));
+}
+
+/* Copies ith coefficient of x to output.
+   Assumes output has been mpz_init'd.
+   AUTHOR: David Harvey (2007-02) */
+void ZZX_getitem_as_mpz(mpz_t* output, struct ZZX* x, long i)
+{
+    const ZZ& z = coeff(*x, i);
+    ZZ_to_mpz(output, &z);
+}
+
+struct ZZX* ZZX_div(struct ZZX* x, struct ZZX* y, int* divisible)
+{
+  struct ZZX* z = new ZZX();
+  *divisible = divide(*z, *x, *y);
+  return z;
+}
+
+
+
+void ZZX_quo_rem(struct ZZX* x, struct ZZX* other, struct ZZX** r, struct ZZX** q)
+{
+  struct ZZX *qq = new ZZX(), *rr = new ZZX();
+  DivRem(*qq, *rr, *x, *other);
+  *r = rr; *q = qq;
+}
+
+
+struct ZZX* ZZX_square(struct ZZX* x)
+{
+  struct ZZX* s = new ZZX();
+  sqr(*s, *x);
+  return s;
+}
+
+
+int ZZX_is_monic(struct ZZX* x)
+{
+  IsOne(LeadCoeff(*x));
+}
+
+
+struct ZZX* ZZX_neg(struct ZZX* x)
+{
+  struct ZZX* y = new ZZX();
+  *y = -*x;
+  return y;
+}
+
+
+struct ZZX* ZZX_left_shift(struct ZZX* x, long n)
+{
+  struct ZZX* y = new ZZX();
+  LeftShift(*y, *x, n);
+  return y;
+}
+
+
+struct ZZX* ZZX_right_shift(struct ZZX* x, long n)
+{
+  struct ZZX* y = new ZZX();
+  RightShift(*y, *x, n);
+  return y;
+}
+
+struct ZZX* ZZX_primitive_part(struct ZZX* x)
+{
+  struct ZZX* p = new ZZX();
+  PrimitivePart(*p, *x);
+  return p;
+}
+
+
+void ZZX_pseudo_quo_rem(struct ZZX* x, struct ZZX* y, struct ZZX** r, struct ZZX** q)
+{
+  *r = new ZZX();
+  *q = new ZZX();
+  PseudoDivRem(**q, **r, *x, *y);
+}
+
+
+struct ZZX* ZZX_gcd(struct ZZX* x, struct ZZX* y)
+{
+  struct ZZX* g = new ZZX();
+  GCD(*g, *x, *y);
+  return g;
+}
+
+
+void ZZX_xgcd(struct ZZX* x, struct ZZX* y, struct ZZ** r, struct ZZX** s, \
+	      struct ZZX** t, int proof)
+{
+  *r = new ZZ();
+  *s = new ZZX();
+  *t = new ZZX();
+  XGCD(**r, **s, **t, *x, *y, proof);
+}
+
+
+long ZZX_degree(struct ZZX* x)
+{
+  return deg(*x);
+}
+
+void ZZX_set_x(struct ZZX* x)
+{
+  SetX(*x);
+}
+
+
+int ZZX_is_x(struct ZZX* x)
+{
+  return IsX(*x);
+}
+
+
+struct ZZX* ZZX_derivative(struct ZZX* x)
+{
+  ZZX* d = new ZZX();
+  diff(*d, *x);
+  return d;
+}
+
+
+struct ZZX* ZZX_reverse(struct ZZX* x)
+{
+  ZZX* r = new ZZX();
+  reverse(*r, *x);
+  return r;
+}
+
+struct ZZX* ZZX_reverse_hi(struct ZZX* x, int hi)
+{
+  ZZX* r = new ZZX();
+  reverse(*r, *x, hi);
+  return r;
+}
+
+
+struct ZZX* ZZX_truncate(struct ZZX* x, long m)
+{
+  ZZX* t = new ZZX();
+  trunc(*t, *x, m);
+  return t;
+}
+
+
+struct ZZX* ZZX_multiply_and_truncate(struct ZZX* x, struct ZZX* y, long m)
+{
+  ZZX* t = new ZZX();
+  MulTrunc(*t, *x, *y, m);
+  return t;
+}
+
+
+struct ZZX* ZZX_square_and_truncate(struct ZZX* x, long m)
+{
+  ZZX* t = new ZZX();
+  SqrTrunc(*t, *x, m);
+  return t;
+}
+
+
+struct ZZX* ZZX_invert_and_truncate(struct ZZX* x, long m)
+{
+  ZZX* t = new ZZX();
+  InvTrunc(*t, *x, m);
+  return t;
+}
+
+
+struct ZZX* ZZX_multiply_mod(struct ZZX* x, struct ZZX* y,  struct ZZX* modulus)
+{
+  ZZX* p = new ZZX();
+  MulMod(*p, *x, *y, *modulus);
+  return p;
+}
+
+
+struct ZZ* ZZX_trace_mod(struct ZZX* x, struct ZZX* y)
+{
+  ZZ* p = new ZZ();
+  TraceMod(*p, *x, *y);
+  return p;
+}
+
+
+char* ZZX_trace_list(struct ZZX* x)
+{
+  vec_ZZ v;
+  TraceVec(v, *x);
+  ostringstream instore;
+  instore << v;
+  int n = strlen(instore.str().data());
+  char* buf = new char[n+1];
+  strcpy(buf, instore.str().data());
+  return buf;
+}
+
+
+struct ZZ* ZZX_resultant(struct ZZX* x, struct ZZX* y, int proof)
+{
+  ZZ* res = new ZZ();
+  resultant(*res, *x, *y, proof);
+  return res;
+}
+
+
+struct ZZ* ZZX_norm_mod(struct ZZX* x, struct ZZX* y, int proof)
+{
+  ZZ* res = new ZZ();
+  NormMod(*res, *x, *y, proof);
+  return res;
+}
+
+
+struct ZZ* ZZX_discriminant(struct ZZX* x, int proof)
+{
+  ZZ* d = new ZZ();
+  discriminant(*d, *x, proof);
+  return d;
+}
+
+
+struct ZZX* ZZX_charpoly_mod(struct ZZX* x, struct ZZX* y, int proof)
+{
+  ZZX* f = new ZZX();
+  CharPolyMod(*f, *x, *y, proof);
+  return f;
+}
+
+
+struct ZZX* ZZX_minpoly_mod(struct ZZX* x, struct ZZX* y)
+{
+  ZZX* f = new ZZX();
+  MinPolyMod(*f, *x, *y);
+  return f;
+}
+
+
+void ZZX_clear(struct ZZX* x)
+{
+  clear(*x);
+}
+
+
+void ZZX_preallocate_space(struct ZZX* x, long n)
+{
+  x->SetMaxLength(n);
+}
+
+/*
+EXTERN struct ZZ* ZZX_polyeval(struct ZZX* f, struct ZZ* a)
+{
+  ZZ* b = new ZZ();
+  *b = PolyEval(*f, *a);
+  return b;
+}
+*/
+
+void ZZX_squarefree_decomposition(struct ZZX*** v, long** e, long* n, struct ZZX* x)
+{
+  vec_pair_ZZX_long factors;
+  SquareFreeDecomp(factors, *x);
+  *n = factors.length();
+  *v = (ZZX**) malloc(sizeof(ZZX*) * (*n));
+  *e = (long*) malloc(sizeof(long) * (*n));
+  for (long i = 0; i < (*n); i++) {
+    (*v)[i] = new ZZX(factors[i].a);
+    (*e)[i] = factors[i].b;
+  }
+}
+
+///////////////////////////////////////////////
+//////// ZZ_pX //////////
+///////////////////////////////////////////////
+
+char* ZZ_pX_repr(struct ZZ_pX* x)
+{
+  ostringstream instore;
+  instore << (*x);
+  int n = strlen(instore.str().data());
+  char* buf = new char[n+1];
+  strcpy(buf, instore.str().data());
+  return buf;
+}
+
+void ZZ_pX_dealloc(struct ZZ_pX* x) {
+  delete x;
+}
+
+struct ZZ_pX* ZZ_pX_copy(struct ZZ_pX* x) {
+  return new ZZ_pX(*x);
+}
+
+/* Sets ith coefficient of x to value.
+   AUTHOR: David Harvey (2008-06-08) */
+void ZZ_pX_setitem_from_int(struct ZZ_pX* x, long i, int value)
+{
+  SetCoeff(*x, i, value);
+}
+
+/* Returns ith coefficient of x.
+   Return value is only valid if the result should fit into an int.
+   AUTHOR: David Harvey (2008-06-08) */
+int ZZ_pX_getitem_as_int(struct ZZ_pX* x, long i)
+{
+    return ZZ_to_int(&rep(coeff(*x, i)));
+}
+
+struct ZZ_pX* ZZ_pX_add(struct ZZ_pX* x, struct ZZ_pX* y)
+{
+  ZZ_pX *z = new ZZ_pX();
+  add(*z, *x, *y);
+  return z;
+}
+
+struct ZZ_pX* ZZ_pX_sub(struct ZZ_pX* x, struct ZZ_pX* y)
+{
+  ZZ_pX *z = new ZZ_pX();
+  sub(*z, *x, *y);
+  return z;
+}
+
+struct ZZ_pX* ZZ_pX_mul(struct ZZ_pX* x, struct ZZ_pX* y)
+{
+  ZZ_pX *z = new ZZ_pX();
+  mul(*z, *x, *y);
+  return z;
+}
+
+
+struct ZZ_pX* ZZ_pX_div(struct ZZ_pX* x, struct ZZ_pX* y, int* divisible)
+{
+  struct ZZ_pX* z = new ZZ_pX();
+  *divisible = divide(*z, *x, *y);
+  return z;
+}
+
+
+struct ZZ_pX* ZZ_pX_mod(struct ZZ_pX* x, struct ZZ_pX* y)
+{
+  struct ZZ_pX* z = new ZZ_pX();
+  rem(*z, *x, *y);
+  return z;
+}
+
+
+
+void ZZ_pX_quo_rem(struct ZZ_pX* x, struct ZZ_pX* y, struct ZZ_pX** r, struct ZZ_pX** q)
+{
+  *r = new ZZ_pX();
+  *q = new ZZ_pX();
+  DivRem(**q, **r, *x, *y);
+}
+
+
+struct ZZ_pX* ZZ_pX_square(struct ZZ_pX* x)
+{
+  struct ZZ_pX* s = new ZZ_pX();
+  sqr(*s, *x);
+  return s;
+}
+
+
+
+int ZZ_pX_is_monic(struct ZZ_pX* x)
+{
+  IsOne(LeadCoeff(*x));
+}
+
+
+struct ZZ_pX* ZZ_pX_neg(struct ZZ_pX* x)
+{
+  struct ZZ_pX* y = new ZZ_pX();
+  *y = -*x;
+  return y;
+}
+
+
+struct ZZ_pX* ZZ_pX_left_shift(struct ZZ_pX* x, long n)
+{
+  struct ZZ_pX* y = new ZZ_pX();
+  LeftShift(*y, *x, n);
+  return y;
+}
+
+
+struct ZZ_pX* ZZ_pX_right_shift(struct ZZ_pX* x, long n)
+{
+  struct ZZ_pX* y = new ZZ_pX();
+  RightShift(*y, *x, n);
+  return y;
+}
+
+
+
+struct ZZ_pX* ZZ_pX_gcd(struct ZZ_pX* x, struct ZZ_pX* y)
+{
+  struct ZZ_pX* g = new ZZ_pX();
+  GCD(*g, *x, *y);
+  return g;
+}
+
+
+void ZZ_pX_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b)
+{
+  *d = new ZZ_pX();
+  *s = new ZZ_pX();
+  *t = new ZZ_pX();
+  XGCD(**d, **s, **t, *a, *b);
+}
+
+void ZZ_pX_plain_xgcd(struct ZZ_pX** d, struct ZZ_pX** s, struct ZZ_pX** t, struct ZZ_pX* a, struct ZZ_pX* b)
+{
+  *d = new ZZ_pX();
+  *s = new ZZ_pX();
+  *t = new ZZ_pX();
+  PlainXGCD(**d, **s, **t, *a, *b);
+}
+
+ZZ_p* ZZ_pX_leading_coefficient(struct ZZ_pX* x)
+{
+  return new ZZ_p(LeadCoeff(*x));
+}
+
+
+void ZZ_pX_set_x(struct ZZ_pX* x)
+{
+  SetX(*x);
+}
+
+
+int ZZ_pX_is_x(struct ZZ_pX* x)
+{
+  return IsX(*x);
+}
+
+
+struct ZZ_pX* ZZ_pX_derivative(struct ZZ_pX* x)
+{
+  ZZ_pX* d = new ZZ_pX();
+  diff(*d, *x);
+  return d;
+}
+
+
+struct ZZ_pX* ZZ_pX_reverse(struct ZZ_pX* x)
+{
+  ZZ_pX* r = new ZZ_pX();
+  reverse(*r, *x);
+  return r;
+}
+
+struct ZZ_pX* ZZ_pX_reverse_hi(struct ZZ_pX* x, int hi)
+{
+  ZZ_pX* r = new ZZ_pX();
+  reverse(*r, *x, hi);
+  return r;
+}
+
+
+struct ZZ_pX* ZZ_pX_truncate(struct ZZ_pX* x, long m)
+{
+  ZZ_pX* t = new ZZ_pX();
+  trunc(*t, *x, m);
+  return t;
+}
+
+
+struct ZZ_pX* ZZ_pX_multiply_and_truncate(struct ZZ_pX* x, struct ZZ_pX* y, long m)
+{
+  ZZ_pX* t = new ZZ_pX();
+  MulTrunc(*t, *x, *y, m);
+  return t;
+}
+
+
+struct ZZ_pX* ZZ_pX_square_and_truncate(struct ZZ_pX* x, long m)
+{
+  ZZ_pX* t = new ZZ_pX();
+  SqrTrunc(*t, *x, m);
+  return t;
+}
+
+
+struct ZZ_pX* ZZ_pX_invert_and_truncate(struct ZZ_pX* x, long m)
+{
+  ZZ_pX* t = new ZZ_pX();
+  InvTrunc(*t, *x, m);
+  return t;
+}
+
+
+struct ZZ_pX* ZZ_pX_multiply_mod(struct ZZ_pX* x, struct ZZ_pX* y,  struct ZZ_pX* modulus)
+{
+  ZZ_pX* p = new ZZ_pX();
+  MulMod(*p, *x, *y, *modulus);
+  return p;
+}
+
+
+struct ZZ_p* ZZ_pX_trace_mod(struct ZZ_pX* x, struct ZZ_pX* y)
+{
+  ZZ_p* p = new ZZ_p();
+  TraceMod(*p, *x, *y);
+  return p;
+}
+
+
+char* ZZ_pX_trace_list(struct ZZ_pX* x)
+{
+  vec_ZZ_p v;
+  TraceVec(v, *x);
+  ostringstream instore;
+  instore << v;
+  int n = strlen(instore.str().data());
+  char* buf = new char[n+1];
+  strcpy(buf, instore.str().data());
+  return buf;
+}
+
+
+struct ZZ_p* ZZ_pX_resultant(struct ZZ_pX* x, struct ZZ_pX* y)
+{
+  ZZ_p* res = new ZZ_p();
+  resultant(*res, *x, *y);
+  return res;
+}
+
+
+struct ZZ_p* ZZ_pX_norm_mod(struct ZZ_pX* x, struct ZZ_pX* y)
+{
+  ZZ_p* res = new ZZ_p();
+  NormMod(*res, *x, *y);
+  return res;
+}
+
+
+
+struct ZZ_pX* ZZ_pX_charpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y)
+{
+  ZZ_pX* f = new ZZ_pX();
+  CharPolyMod(*f, *x, *y);
+  return f;
+}
+
+
+struct ZZ_pX* ZZ_pX_minpoly_mod(struct ZZ_pX* x, struct ZZ_pX* y)
+{
+  ZZ_pX* f = new ZZ_pX();
+  MinPolyMod(*f, *x, *y);
+  return f;
+}
+
+
+void ZZ_pX_clear(struct ZZ_pX* x)
+{
+  clear(*x);
+}
+
+
+void ZZ_pX_preallocate_space(struct ZZ_pX* x, long n)
+{
+  x->SetMaxLength(n);
+}
+
+
+void ZZ_pX_factor(struct ZZ_pX*** v, long** e, long* n, struct ZZ_pX* x, long verbose)
+{
+  long i;
+  vec_pair_ZZ_pX_long factors;
+  berlekamp(factors, *x, verbose);
+  *n = factors.length();
+  *v = (ZZ_pX**) malloc(sizeof(ZZ_pX*) * (*n));
+  *e = (long*) malloc(sizeof(long)*(*n));
+  for (i=0; i<(*n); i++) {
+    (*v)[i] = new ZZ_pX(factors[i].a);
+    (*e)[i] = factors[i].b;
+  }
+}
+
+void ZZ_pX_linear_roots(struct ZZ_p*** v, long* n, struct ZZ_pX* f)
+{
+  long i;
+  // printf("1\n");
+  vec_ZZ_p w;
+  FindRoots(w, *f);
+  // printf("2\n");
+  *n = w.length();
+  //   printf("3 %d\n",*n);
+  (*v) = (ZZ_p**) malloc(sizeof(ZZ_p*)*(*n));
+  for (i=0; i<(*n); i++) {
+    (*v)[i] = new ZZ_p(w[i]);
+  }
+}
+
+/////////// ZZ_pE //////////////
+
+struct ZZ_pX ZZ_pE_to_ZZ_pX(struct ZZ_pE x)
+{
+  ZZ_pX *ans = new ZZ_pX(rep(x));
+  return *ans;
+}
+
+
+
+//////// mat_ZZ //////////
+
+void mat_ZZ_SetDims(struct mat_ZZ* mZZ, long nrows, long ncols){
+  mZZ->SetDims(nrows, ncols);
+}
+
+struct mat_ZZ* mat_ZZ_pow(const struct mat_ZZ* x, long e) 
+{
+  mat_ZZ *z = new mat_ZZ();
+  power(*z, *x, e);
+  return z;
+}
+
+long mat_ZZ_nrows(const struct mat_ZZ* x)
+{
+  return x->NumRows();
+}
+
+
+long mat_ZZ_ncols(const struct mat_ZZ* x)
+{
+  return x->NumCols();
+}
+
+void mat_ZZ_setitem(struct mat_ZZ* x, int i, int j, const struct ZZ* z)
+{
+  (*x)[i][j] = *z;
+  
+}
+
+struct ZZ* mat_ZZ_getitem(const struct mat_ZZ* x, int i, int j)
+{
+  return new ZZ((*x)(i,j));
+}
+
+struct ZZ* mat_ZZ_determinant(const struct mat_ZZ* x, long deterministic)
+{
+  ZZ* d = new ZZ();
+  determinant(*d, *x, deterministic);
+  return d;
+}
+
+struct mat_ZZ* mat_ZZ_HNF(const struct mat_ZZ* A, const struct ZZ* D)
+{
+  struct mat_ZZ* W = new mat_ZZ();
+  HNF(*W, *A, *D);
+  return W;
+}
+
+long mat_ZZ_LLL(struct ZZ **det, struct mat_ZZ *x, long a, long b, long verbose)
+{
+  *det = new ZZ();
+  return LLL(**det,*x,a,b,verbose);
+}
+
+long mat_ZZ_LLL_U(struct ZZ **det, struct mat_ZZ *x, struct mat_ZZ *U, long a, long b, long verbose)
+{
+  *det = new ZZ();
+  return LLL(**det,*x,*U,a,b,verbose);
+}
+
+
+struct ZZX* mat_ZZ_charpoly(const struct mat_ZZ* A)
+{
+  ZZX* f = new ZZX();
+  CharPoly(*f, *A);
+  return f;
+}
+
+
+
+/** 
+ * GF2X
+ *
+ * @author Martin Albrecht <malb@informatik.uni-bremen.de>
+ *
+ * @versions 2006-01 malb
+ *           initial version (based on code by William Stein)
+ */
+
+struct GF2X* GF2X_pow(const struct GF2X* x, long e) 
+{
+  GF2X *z = new GF2X();
+  power(*z, *x, e);
+  return z;
+}
+
+struct GF2X* GF2X_neg(struct GF2X* x)
+{
+  return new GF2X(-(*x));
+}
+
+struct GF2X* GF2X_copy(struct GF2X* x)
+{
+  GF2X *z = new GF2X(*x);
+  return z;
+}
+
+long GF2X_deg(struct GF2X* x)
+{
+  return deg(*x);
+}
+
+void GF2X_hex(long h)
+{
+  GF2X::HexOutput=h;
+}
+
+
+
+PyObject* GF2X_to_bin(const struct GF2X* x) 
+{
+  long hex;
+  hex = GF2X::HexOutput;
+  GF2X::HexOutput=0;
+  std::ostringstream instore;
+  instore << (*x);
+  GF2X::HexOutput=hex;
+  return PyString_FromString(instore.str().data());
+}
+
+PyObject* GF2X_to_hex(const struct GF2X* x)
+{
+  long hex;
+  hex = GF2X::HexOutput;
+  GF2X::HexOutput=1;
+  std::ostringstream instore;
+  instore << (*x);
+  GF2X::HexOutput=hex;
+  return PyString_FromString(instore.str().data());
+}
+
+
+
+/** 
+ * GF2E
+ *
+ * @author Martin Albrecht <malb@informatik.uni-bremen.de>
+ *
+ * @versions 2006-01 malb
+ *           initial version (based on code by William Stein)
+ */
+
+
+void ntl_GF2E_set_modulus(GF2X* x)
+{
+  GF2E::init(*x);
+}
+
+
+struct GF2E* GF2E_pow(const struct GF2E* x, long e) 
+{
+  GF2E *z = new GF2E();
+  power(*z, *x, e);
+  return z;
+}
+
+
+struct GF2E* GF2E_neg(struct GF2E* x)
+{
+  return new GF2E(-(*x));
+}
+
+struct GF2E* GF2E_copy(struct GF2E* x)
+{
+  GF2E *z = new GF2E(*x);
+  return z;
+}
+
+long GF2E_trace(struct GF2E* x)
+{
+  return rep(trace(*x));
+}
+
+
+long GF2E_degree()
+{
+  return GF2E::degree();
+}
+
+const struct GF2X* GF2E_modulus()
+{
+  GF2XModulus mod = GF2E::modulus();
+  GF2X *z = new GF2X(mod.val());
+  return z;
+}
+
+struct GF2E *GF2E_random(void)
+{
+  GF2E *z = new GF2E();
+  random(*z);
+  return z;
+}
+
+const struct GF2X *GF2E_ntl_GF2X(struct GF2E *x) {
+  GF2X *r = new GF2X(rep(*x));
+  return r;
+}
+
+
+/** 
+ * mat_GF2E
+ *
+ * @author Martin Albrecht <malb@informatik.uni-bremen.de>
+ *
+ * @versions 2006-01 malb
+ *           initial version (based on code by William Stein)
+ */
+
+void mat_GF2E_SetDims(struct mat_GF2E* m, long nrows, long ncols){
+  m->SetDims(nrows, ncols);
+}
+
+struct mat_GF2E* mat_GF2E_pow(const struct mat_GF2E* x, long e) 
+{
+  mat_GF2E *z = new mat_GF2E();
+  power(*z, *x, e);
+  return z;
+}
+
+long mat_GF2E_nrows(const struct mat_GF2E* x)
+{
+  return x->NumRows();
+}
+
+
+long mat_GF2E_ncols(const struct mat_GF2E* x)
+{
+  return x->NumCols();
+}
+
+void mat_GF2E_setitem(struct mat_GF2E* x, int i, int j, const struct GF2E* z)
+{
+  (*x)[i][j] = *z;
+}
+
+struct GF2E* mat_GF2E_getitem(const struct mat_GF2E* x, int i, int j)
+{
+  return new GF2E((*x)(i,j));
+}
+ 
+struct GF2E* mat_GF2E_determinant(const struct mat_GF2E* x)
+{
+  GF2E* d = new GF2E();
+  determinant(*d, *x);
+  return d;
+}
+
+long mat_GF2E_gauss(struct mat_GF2E *x, long w)
+{
+  if(w==0) {
+    return gauss(*x);
+  } else {
+    return gauss(*x, w);
+  }
+}
+
+struct mat_GF2E* mat_GF2E_transpose(const struct mat_GF2E* x) {
+  mat_GF2E *y = new mat_GF2E();
+  transpose(*y,*x);
+  return y;
+}
+
+
+
+ZZ_pContext* ZZ_pContext_new(ZZ *p)
+{
+	return new ZZ_pContext(*p);
+}
+
+ZZ_pContext* ZZ_pContext_construct(void *mem, ZZ *p)
+{
+	return new(mem) ZZ_pContext(*p);
+}
+
+void ZZ_pContext_restore(ZZ_pContext *ctx)
+{
+	ctx->restore();
+}
+
+ZZ_pEContext* ZZ_pEContext_new(ZZ_pX *f)
+{
+	return new ZZ_pEContext(*f);
+}
+
+ZZ_pEContext* ZZ_pEContext_construct(void *mem, ZZ_pX *f)
+{
+	return new(mem) ZZ_pEContext(*f);
+}
+
+void ZZ_pEContext_restore(ZZ_pEContext *ctx)
+{
+	ctx->restore();
+}
+
+zz_pContext* zz_pContext_new(long p)
+{
+	return new zz_pContext(p);
+}
+
+zz_pContext* zz_pContext_construct(void *mem, long p)
+{
+	return new(mem) zz_pContext(p);
+}
+
+void zz_pContext_restore(zz_pContext *ctx)
+{
+	ctx->restore();
+}
Index: c_lib/src/stdsage.c
===================================================================
--- c_lib/src/stdsage.c	(revision 6597)
+++ c_lib/src/stdsage.c	(revision 6597)
@@ -0,0 +1,38 @@
+/**
+ * @file stdsage.c
+ *
+ * Some global C stuff that gets imported into pyrex modules.
+ *
+ */
+   
+/******************************************************************************
+       Copyright (C) 2006 William Stein <wstein@gmail.com>
+                     2006 David Harvey <dmharvey@math.harvard.edu>
+                     2006 Martin Albrecht <malb@informatik.uni-bremen.de>
+
+  Distributed under the terms of the GNU General Public License (GPL), Version 2.
+
+  The full text of the GPL is available at:
+                  http://www.gnu.org/licenses/
+
+******************************************************************************/
+
+
+#include "stdsage.h"
+#include "interrupt.h"
+
+PyObject* global_empty_tuple;
+
+void init_global_empty_tuple(void) {
+  _CALLED_ONLY_ONCE;
+
+  global_empty_tuple = PyTuple_New(0);
+}
+
+
+void init_csage(void) {
+  //_CALLED_ONLY_ONCE;
+  
+  init_global_empty_tuple();
+  setup_signal_handler();
+}
Index: _lib/stdsage.c
===================================================================
--- c_lib/stdsage.c	(revision 6032)
+++ 	(revision )
@@ -1,38 +1,0 @@
-/**
- * @file stdsage.c
- *
- * Some global C stuff that gets imported into pyrex modules.
- *
- */
-   
-/******************************************************************************
-       Copyright (C) 2006 William Stein <wstein@gmail.com>
-                     2006 David Harvey <dmharvey@math.harvard.edu>
-                     2006 Martin Albrecht <malb@informatik.uni-bremen.de>
-
-  Distributed under the terms of the GNU General Public License (GPL), Version 2.
-
-  The full text of the GPL is available at:
-                  http://www.gnu.org/licenses/
-
-******************************************************************************/
-
-
-#include "stdsage.h"
-#include "interrupt.h"
-
-PyObject* global_empty_tuple;
-
-void init_global_empty_tuple(void) {
-  _CALLED_ONLY_ONCE;
-
-  global_empty_tuple = PyTuple_New(0);
-}
-
-
-void init_csage(void) {
-  //_CALLED_ONLY_ONCE;
-  
-  init_global_empty_tuple();
-  setup_signal_handler();
-}
Index: _lib/stdsage.h
===================================================================
--- c_lib/stdsage.h	(revision 6135)
+++ 	(revision )
@@ -1,179 +1,0 @@
-/******************************************************************************
-       Copyright (C) 2006 William Stein <wstein@gmail.com>
-                     2006 Martin Albrecht <malb@informatik.uni-bremen.de>
-
-  Distributed under the terms of the GNU General Public License (GPL), Version 2.
-
-  The full text of the GPL is available at:
-                  http://www.gnu.org/licenses/
-
-******************************************************************************/
-
-/**
- * @file stdsage.h
- *
- * @author William Stein <wstein@gmail.com>
- * @auhtor Martin Albrecht <malb@informatik.uni-bremen.de>
- *
- * @brief General C (.h) code this is useful to include in any pyrex module.
- *
- * Put 
- @verbatim
- 
-  include 'relative/path/to/stdsage.pxi' 
-
- @endverbatim
- *
- * at the top of your Pyrex file. 
- *
- * These are mostly things that can't be done in Pyrex.
- */
-
-#ifndef STDSAGE_H
-#define STDSAGE_H
-
-#include "Python.h"
-
-/* Building with this not commented out causes
-   serious problems on RHEL5 64-bit for Kiran Kedlaya... i.e., it doesn't work. */
-/* #include "ccobject.h" */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*****************************************
-          For PARI 
-          Memory management
-
- *****************************************/
-
-#define set_gel(x, n, z)  gel(x,n)=z;
-
-/******************************************
- Some macros exported for Pyrex in cdefs.pxi
- ****************************************/
-
-/** Tests whether zzz_obj is of type zzz_type. The zzz_type must be a
- * built-in or extension type. This is just a C++-compatible wrapper
- * for PyObject_TypeCheck. 
- */
-#define PY_TYPE_CHECK(zzz_obj, zzz_type) \
-    (PyObject_TypeCheck((PyObject*)(zzz_obj), (PyTypeObject*)(zzz_type)))
-
-/** Returns the type field of a python object, cast to void*. The
- *  returned value should only be used as an opaque object e.g. for
- *  type comparisons. 
- */
-#define PY_TYPE(zzz_obj) ((void*)((zzz_obj)->ob_type))
-
-/** Constructs a new object of type zzz_type by calling tp_new
- *  directly, with no arguments. 
- */
-
-#define PY_NEW(zzz_type) \
-    (((PyTypeObject*)(zzz_type))->tp_new((PyTypeObject*)(zzz_type), global_empty_tuple, NULL)) 
-
-/** Resets the tp_new slot of zzz_type1 to point to the tp_new slot of
- *  zzz_type2. This is used in SAGE to speed up Pyrex's boilerplate
- *  object construction code by skipping irrelevant base class tp_new
- *  methods. 
- */
-#define PY_SET_TP_NEW(zzz_type1, zzz_type2) \
-    (((PyTypeObject*)zzz_type1)->tp_new = ((PyTypeObject*)zzz_type2)->tp_new)
-
-
-/**
- * Tests whether the given object has a python dictionary. 
- */
-#define HAS_DICTIONARY(zzz_obj) \
-    (((PyObject*)(zzz_obj))->ob_type->tp_dictoffset != NULL)
-
-/** 
- * Very very unsafe access to the list of pointers to PyObject*'s
- * underlying a list / sequence.  This does error checking of any kind
- * -- make damn sure you hand it a list or sequence!
- */
-#define FAST_SEQ_UNSAFE(zzz_obj) \
-    PySequence_Fast_ITEMS(PySequence_Fast(zzz_obj, "expected sequence type"))
-
-/** Returns the type field of a python object, cast to void*. The
- *  returned value should only be used as an opaque object e.g. for
- *  type comparisons.
- */
-#define PY_IS_NUMERIC(zzz_obj) \
-     (PyInt_Check(zzz_obj) ||  PyBool_Check(zzz_obj) || PyLong_Check(zzz_obj) || \
-       PyFloat_Check(zzz_obj) || PyComplex_Check(zzz_obj))
-
-
-/** This is exactly the same as isinstance (and does return a Python
- *  bool), but the second argument must be a C-extension type -- so it
- *  can't be a Python class or a list.  If you just want an int return
- *  value, i.e., aren't going to pass this back to Python, just use
- *  PY_TYPE_CHECK. 
- */
-#define IS_INSTANCE(zzz_obj, zzz_type) \
-    PyBool_FromLong(PY_TYPE_CHECK(zzz_obj, zzz_type))
-
-
-/** 
- * A global empty python tuple object. This is used to speed up some
- * python API calls where we want to avoid constructing a tuple every
- * time. 
- */
-
-extern PyObject* global_empty_tuple;
-
-
-
-/*****************************************
-          Memory management
-
-NOTE -- before changing these away from Python's keep the following in
-mind (from the Python C/API guide):
-
-"In most situations, however, it is recommended to allocate memory from
-the Python heap specifically because the latter is under control of
-the Python memory manager. For example, this is required when the
-interpreter is extended with new object types written in C. Another
-reason for using the Python heap is the desire to inform the Python
-memory manager about the memory needs of the extension module. Even
-when the requested memory is used exclusively for internal,
-highly-specific purposes, delegating all memory requests to the Python
-memory manager causes the interpreter to have a more accurate image of
-its memory footprint as a whole. Consequently, under certain
-circumstances, the Python memory manager may or may not trigger
-appropriate actions, like garbage collection, memory compaction or
-other preventive procedures. Note that by using the C library
-allocator as shown in the previous example, the allocated memory for
-the I/O buffer escapes completely the Python memory manager."
-
- *****************************************/
-
-#define sage_malloc  malloc
-#define sage_free    free
-#define sage_realloc realloc
-
-/**
- * Initialisation of singal handlers, global variables, etc. Called
- * exactly once at SAGE start-up. 
- *
- * @note: It is safe to call this function more than once but nothing
- * will happen after the first call.
- */
-void init_csage(void);
-
-
-
-/**
- * a handy macro to be placed at the top of a function definition
- * below the variable declarations to ensure a function is called once
- * at maximum.
- */
-#define _CALLED_ONLY_ONCE static int ncalls = 0; if (ncalls>0) return; else ncalls++
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
Index: sage/algebras/quaternion_algebra.py
===================================================================
--- sage/algebras/quaternion_algebra.py	(revision 5958)
+++ sage/algebras/quaternion_algebra.py	(revision 6510)
@@ -60,5 +60,5 @@
     """
     D = Integer(D)
-    D = D.square_free_part()
+    D = D.squarefree_part()
     if D%4 == 1:
         return D
@@ -72,6 +72,6 @@
     if a.is_square() or b.is_square() or (a+b).is_square():
         return [ ]
-    a = a.square_free_part()
-    b = b.square_free_part()
+    a = a.squarefree_part()
+    b = b.squarefree_part()
     c = Integer(GCD(a,b))
     if c != 1:
@@ -405,5 +405,8 @@
         
     def discriminant(self):
-        return self.gram_matrix().determinant()
+        """
+        Given a quaternion algebra A defined over the field of rational numbers, return the discriminant of A, i.e. the product of the ramified primes of A.
+        """
+        return mul(self.ramified_primes())
 
     def gram_matrix(self):
@@ -439,4 +442,98 @@
         """
         return False
+
+    def is_division_algebra(self):
+        """
+        Return True if the quaternion algebra is a division algebra
+        (i.e. a ring, not necessarily commutative, in which every nonzero
+        element is invertible).  So if this returns False, the quaternion
+        algebra is isomorphic to the 2x2 matrix algebra.
+
+        At the moment, this is implemented only for finite fields.
+
+        EXAMPLES:
+            sage: Q.<i,j,k> = QuaternionAlgebra(GF(5), -3, -7)
+            sage: Q.is_division_algebra()
+            False
+        """
+        if self.base_ring().is_finite():
+            return False
+        else:
+            raise AttributeError, "Only implemented for quaternion algebras over finite fields."
+
+    def is_exact(self):
+        """
+        Return True if elements of this quaternion algebra are represented exactly, i.e. there is no precision loss when doing arithmetic.  A quaternion algebra is exact if and only if its base field is exact.
+
+        EXAMPLES:
+            sage: Q.<i,j,k> = QuaternionAlgebra(QQ, -3, -7)
+            sage: Q.is_exact()
+            True
+            sage: Q.<i,j,k> = QuaternionAlgebra(Qp(7), -3, -7)
+            sage: Q.is_exact()
+            False
+        """
+        return self.base_ring().is_exact()
+
+    def is_field(self):
+        """
+        Return False always, since all quaternion algebras are noncommutative and all fields are commutative.
+
+        EXAMPLES:
+            sage: Q.<i,j,k> = QuaternionAlgebra(QQ, -3, -7)
+            sage: Q.is_field()
+            False
+        """
+        return False
+
+    def is_finite(self):
+        """
+        Return True if the quaternion algebra is a finite ring, i.e. if and only if the base field is finite.
+        
+        EXAMPLES:
+            sage: Q.<i,j,k> = QuaternionAlgebra(QQ, -3, -7)
+            sage: Q.is_finite()
+            False
+            sage: Q.<i,j,k> = QuaternionAlgebra(GF(5), -3, -7)
+            sage: Q.is_finite()
+            True
+        """
+        return self.base_ring().is_finite()
+
+    def is_integral_domain(self):
+        """
+        Return False always, since all quaternion algebras are noncommutative and integral domains are commutative (in SAGE).
+
+        EXAMPLES:
+            sage: Q.<i,j,k> = QuaternionAlgebra(QQ, -3, -7)
+            sage: Q.is_integral_domain()
+            False
+        """
+        return False
+    
+    def is_noetherian(self):
+        """
+        Return True always, since any quaternion algebra is a noetherian ring (because it's a finitely-generated module over a field, which is noetherian).
+
+        EXAMPLES:
+            sage: Q.<i,j,k> = QuaternionAlgebra(QQ, -3, -7)
+            sage: Q.is_noetherian()
+            True
+        """
+        return True
+
+    def order(self):
+        """
+        Return the number of elements of the quaternion algebra, or +Infinity if the algebra is not finite.
+        
+        EXAMPLES:
+            sage: Q.<i,j,k> = QuaternionAlgebra(QQ, -3, -7)
+            sage: Q.order()
+            +Infinity
+            sage: Q.<i,j,k> = QuaternionAlgebra(GF(5), -3, -7)
+            sage: Q.order()
+            20
+        """
+        return 4*self.base_ring().order()
     
     def ramified_primes(self):
Index: sage/algebras/quaternion_algebra_element.py
===================================================================
--- sage/algebras/quaternion_algebra_element.py	(revision 4450)
+++ sage/algebras/quaternion_algebra_element.py	(revision 6442)
@@ -24,4 +24,5 @@
 from sage.rings.polynomial.polynomial_ring import PolynomialRing
 from sage.algebras.free_algebra_quotient_element import FreeAlgebraQuotientElement
+from sage.rings.infinity import Infinity
 
 class QuaternionAlgebraElement(FreeAlgebraQuotientElement):
@@ -37,4 +38,13 @@
     
     def conjugate(self):
+        """
+        Return the conjugate of this element.
+
+        EXAMPLES:
+            sage: A.<i,j,k>=QuaternionAlgebra(QQ,-5,-2)
+            sage: x=3*i-j+2
+            sage: x.conjugate()
+            2 - 3*i + j
+        """
         return self.parent()(self.reduced_trace()) - self        
 	
@@ -43,42 +53,63 @@
         Return the reduced trace of this element.
         
-	\note{In a quaternion algebra $A$, every element $x$ is
-	quadratic over the center, thus $x^2 = \Tr(x)*x - \Nr(x)$, so
-	we solve for a linear relation $(1,-\Tr(x),\Nr(x))$ among
-	$[x^2, x, 1]$ for the reduced trace of $x$.}
-	"""
-	v = self.vector()
-	if v[1] == 0 and v[2] == 0 and v[3] == 0: return 2*v[0]
-	u = (self**2).vector()
+        \note{In a quaternion algebra $A$, every element $x$ is
+        quadratic over the center, thus $x^2 = \Tr(x)*x - \Nr(x)$, so
+        we solve for a linear relation $(1,-\Tr(x),\Nr(x))$ among
+        $[x^2, x, 1]$ for the reduced trace of $x$.}
+
+        EXAMPLES:
+            sage: A.<i,j,k>=QuaternionAlgebra(QQ,-5,-2)
+            sage: x=3*i-j+2
+            sage: x.reduced_trace()
+            4
+        """
+        v = self.vector()
+        if v[1] == 0 and v[2] == 0 and v[3] == 0: return 2*v[0]
+        u = (self**2).vector()
         K = self.parent().base_ring()
-	A = MatrixSpace(K,3,4)	
-	M = A(list(u) + list(v) + [1,0,0,0]).kernel()
-	w = M.gen(0)
-	if w[0] == 1: return -w[1]
+        A = MatrixSpace(K,3,4)	
+        M = A(list(u) + list(v) + [1,0,0,0]).kernel()
+        w = M.gen(0)
+        if w[0] == 1: return -w[1]
         return -w[1]/w[0]
 		
     def reduced_norm(self):
         """
-	"""
+        Return the reduced norm of this element.
+
+        EXAMPLES:
+            sage: A.<i,j,k>=QuaternionAlgebra(QQ,-5,-2)
+            sage: x=3*i-j+2
+            sage: x.reduced_norm()
+            51
+        """
         x = self * self.conjugate()
-	return x.vector()[0]
+        return x.vector()[0]
 
     def charpoly(self, var):
         """
-	"""
-	v = self.vector()
-	if v[1] == 0 and v[2] == 0 and v[3] == 0:
-	    return 2*v[0]
-	u = (self**2).vector()
-	A = MatrixSpace(RationalField(),3,4)	
-	M = A(list(u) + list(v) + [1,0,0,0]).kernel()
-	w = M.gen(0)
-	P = PolynomialRing(self.parent().base_ring(), var)
-	x = P.gen()
-	if w[0] == 1:
+        Return the characteristic polynomial of this element in terms
+        of the given variable.
+
+        EXAMPLES:
+            sage: A.<i,j,k>=QuaternionAlgebra(QQ,-5,-2)
+            sage: x=3*i-j+2
+            sage: x.charpoly('t')
+            t^2 - 4*t + 51
+        """
+        v = self.vector()
+        if v[1] == 0 and v[2] == 0 and v[3] == 0:
+            return 2*v[0]
+        u = (self**2).vector()
+        A = MatrixSpace(RationalField(),3,4)	
+        M = A(list(u) + list(v) + [1,0,0,0]).kernel()
+        w = M.gen(0)
+        P = PolynomialRing(self.parent().base_ring(), var)
+        x = P.gen()
+        if w[0] == 1:
             x**2 + w[1]*x + w[2]
-        return x**2 + w[1]/w[0]*x + w[2]/w[0]
+            return x**2 + w[1]/w[0]*x + w[2]/w[0]
 		
-	return x**2 - self.reduced_trace()*x + self.reduced_norm()
+        return x**2 - self.reduced_trace()*x + self.reduced_norm()
 
     characteristic_polynomial = charpoly
@@ -86,15 +117,109 @@
     def minpoly(self, var):
         """
-	"""
-	v = self.vector()
-	if v[1] == 0 and v[2] == 0 and v[3] == 0:
-	    K = self.parent().base_ring()
-	    P = PolynomialRing(K, var)
-	    x = P.gen()
-	    return x - v[0]
-	return self.charpoly(var)
+        Return the minimal polynomial of this element in terms
+        of the given variable.
+
+        EXAMPLES:
+            sage: A.<i,j,k>=QuaternionAlgebra(QQ,-5,-2)
+            sage: x=3*i-j+2
+            sage: x.minpoly('t')
+            t^2 - 4*t + 51
+        """
+        v = self.vector()
+        if v[1] == 0 and v[2] == 0 and v[3] == 0:
+            K = self.parent().base_ring()
+            P = PolynomialRing(K, var)
+            x = P.gen()
+            return x - v[0]
+        return self.charpoly(var)
 
     minimal_polynomial = minpoly
-    
+
+    def is_unit(self):
+        """
+        Return True if the element is an invertible element of the
+        quaternion algebra.
+
+        EXAMPLES:
+            sage: A.<i,j,k> = QuaternionAlgebra(QQ,-1,-1)
+            sage: i.is_unit()
+            True
+            sage: (i-5+j*k).is_unit()
+            True
+            sage: A(0).is_unit()
+            False
+        """
+        if self.reduced_norm() == 0:
+            return False
+        else:
+            return True
+
+    def additive_order(self):        
+        if self.base_ring().is_finite():
+            return self.base_ring().characteristic()
+        else:
+            return Infinity
+
+    def is_scalar(self):
+        """
+        Return True is this element of a quaternion algebra is
+        a scalar (i.e. lies in the base field).
+
+        EXAMPLES:
+            sage: A.<i,j,k> = QuaternionAlgebra(QQ,-1,-1)
+            sage: i.is_scalar()
+            False
+            sage: (i-5+j*k).is_scalar()
+            False
+            sage: A(12).is_scalar()
+            True
+        """
+        if (self.reduced_trace()-2*self).is_zero():
+            return True
+        else:
+            return False
+
+    def _div_(self, other):
+        """
+        Right division in the quaternion algebra
+
+        EXAMPLES:
+            sage: A.<i,j,k>=QuaternionAlgebra(QQ,-1,-1)
+            sage: x=3*i-j+2
+            sage: y=i-1
+            sage: x/y
+            1/2 - 5/2*i + 1/2*j - 1/2*k
+
+        Note that 1/x will raise an AttributeError.  The way to get
+        the inverse of x is
+            sage: A(1)/x
+            1/7 - 3/14*i + 1/14*j
+        """
+        if other.is_unit() == False:
+            raise AttributeError, "The second operand must be a unit"
+        H = self.parent()
+        if H(other).is_scalar():
+            return QuaternionAlgebraElement(H, [self.vector()[i]/(H(other).reduced_trace()/2) for i in range(4)])
+        elif self.is_scalar():
+            return self*other.conjugate()/other.reduced_norm()
+        else:
+            return self*(H(1)/other)
+
+    def _backslash_(self, other):
+        """
+        Left division in the quaternion algebra
+
+        EXAMPLES:
+            sage: A.<i,j,k>=QuaternionAlgebra(QQ,-1,-1)
+            sage: x=3*i-j+2
+            sage: y=i-1
+            sage: x\y
+            1/14 + 5/14*i - 1/14*j - 1/14*k
+        """
+        if self.is_unit() == False:
+            raise AttributeError, "The first operand must be a unit"
+        else:
+            H = self.parent()
+            return (H(1)/self)*other
 
 class QuaternionAlgebraElement_fast(QuaternionAlgebraElement):
@@ -125,4 +250,5 @@
              a[0]*b[2] +    a[2]*b[0] + d1*a[1]*b[3] -    d1*a[3]*b[1],
              a[0]*b[3] +    a[3]*b[0] +    a[1]*b[2] -       a[2]*b[1]])
+
         
     def conjugate(self):
Index: sage/all.py
===================================================================
--- sage/all.py	(revision 6263)
+++ sage/all.py	(revision 6943)
@@ -84,4 +84,5 @@
 
 from sage.crypto.all     import *
+import sage.crypto.mq as mq
 
 from sage.plot.all       import *
@@ -248,4 +249,6 @@
     sage.matrix.matrix_mod2_dense.free_m4ri()
 
+    pari._unsafe_deallocate_pari_stack()
+    
     ### The following is removed -- since it would cleanup
     ### the tmp directory that the sage cleaner depends upon.
@@ -279,4 +282,7 @@
     sage.rings.integer.free_integer_pool()
     sage.rings.integer.clear_mpz_globals()
+
+    from sage.libs.all import symmetrica 
+    symmetrica.end() 
         
 def _quit_sage_(self):
Index: sage/calculus/all.py
===================================================================
--- sage/calculus/all.py	(revision 5935)
+++ sage/calculus/all.py	(revision 6580)
@@ -4,4 +4,5 @@
                       is_SymbolicExpressionRing,
                       is_SymbolicExpression,
+                      is_SymbolicVariable,
                       CallableSymbolicExpressionRing,
                       is_CallableSymbolicExpressionRing,
@@ -16,4 +17,6 @@
                       is_SymbolicExpressionRing)
 
+from calculus import maxima as maxima_calculus
+
 
 from functional import (diff, derivative,
@@ -23,4 +26,8 @@
                         taylor, simplify)
 
+from desolvers import (desolve, desolve_laplace, desolve_system,
+                       eulers_method, eulers_method_2x2, 
+                       eulers_method_2x2_plot)
+
 from var import (var, function, clear_vars)
 
Index: sage/calculus/calculus.py
===================================================================
--- sage/calculus/calculus.py	(revision 6254)
+++ sage/calculus/calculus.py	(revision 7010)
@@ -206,9 +206,10 @@
 
 from sage.rings.all import (CommutativeRing, RealField, is_Polynomial,
-                            is_MPolynomial, is_MPolynomialRing,
+                            is_MPolynomial, is_MPolynomialRing, is_FractionFieldElement, 
                             is_RealNumber, is_ComplexNumber, RR,
                             Integer, Rational, CC,
                             QuadDoubleElement,
-                            PolynomialRing, ComplexField)
+                            PolynomialRing, ComplexField,
+                            algdep)
 
 from sage.structure.element import RingElement, is_Element
@@ -332,4 +333,12 @@
 
     def _coerce_impl(self, x):
+        """
+        EXAMPLES:
+            sage: x=var('x'); y0,y1=PolynomialRing(ZZ,2,'y').gens()
+            sage: x+y0/y1
+            y0/y1 + x
+            sage: x.subs(x=y0/y1)
+            y0/y1
+        """
         if isinstance(x, CallableSymbolicExpression):
             return x._expr
@@ -341,4 +350,9 @@
             if x.base_ring() != self:  # would want coercion to go the other way
                 return SymbolicPolynomial(x)
+            else:
+                raise TypeError, "Basering is Symbolic Ring, please coerce in the other direction."
+        elif is_FractionFieldElement(x) and (is_Polynomial(x.numerator()) or is_MPolynomial(x.numerator())):
+            if x.base_ring() != self:  # would want coercion to go the other way
+                return SymbolicPolynomial(x.numerator()) / SymbolicPolynomial(x.denominator())
             else:
                 raise TypeError, "Basering is Symbolic Ring, please coerce in the other direction."
@@ -787,5 +801,148 @@
 
     n = numerical_approx
-
+        
+    def minpoly(self, bits=None, degree=None, epsilon=0):
+        """
+        Return the minimal polynomial of self, if possible. 
+        
+        INPUT:
+            bits    -- the number of bits to use in numerical approx
+            degree  -- the expected algebraic degree
+            epsilon -- return without error as long as f(self) < epsilon, 
+                       in the case that the result cannot be proven. 
+                       
+            All of the above parameters are optional, with epsilon=0, 
+            bits and degree tested up to 1000 and 24 by default respectively.
+            If these are known, it will be faster to give them explicitly.  
+            
+        OUTPUT: 
+            The minimal polynomial of self. This is proved symbolically if
+            epsilon=0 (default). 
+            
+            If the minimal polynomial could not be found, two distinct kinds
+            of errors are raised. If no reasonable candidate was found with
+            the given bit/degree parameters, a ValueError will be raised. 
+            If a reasonable candidate was found but (perhaps due to limits
+            in the underlying symbolic package) was unable to be proved 
+            correct, a NotImplementedError will be raised. 
+        
+        ALGORITHM: 
+            Use the PARI algdep command on a numerical approximation of self
+            to get a candidate minpoly f. Approximate f(self) to higher 
+            precision and if the result is still close enough to 0 then
+            evaluate f(self) symbolically, attempting to prove vanishing. 
+            If this fails, and epsilon is non-zero, return f as long as 
+            f(self) < epsilon. Otherwise raise an error. 
+            
+        
+        NOTE: Failure of this function does not prove self is
+              not algebraic. 
+        
+        
+        EXAMPLES: 
+        
+        First some simple examples: 
+            sage: sqrt(2).minpoly()
+            x^2 - 2
+            sage: a = 2^(1/3)
+            sage: a.minpoly()
+            x^3 - 2
+            sage: (sqrt(2)-3^(1/3)).minpoly()
+            x^6 - 6*x^4 + 6*x^3 + 12*x^2 + 36*x + 1
+            
+        Sometimes it fails. 
+            sage: sin(1).minpoly()
+            Traceback (most recent call last):
+            ...
+            ValueError: Could not find minimal polynomial (1000 bits, degree 24).
+            
+        Note that simplification may be necessary.
+            sage: a = sqrt(2)+sqrt(3)+sqrt(5)
+            sage: f = a.minpoly(); f
+            x^8 - 40*x^6 + 352*x^4 - 960*x^2 + 576
+            sage: f(a)
+            (sqrt(5) + sqrt(3) + sqrt(2))^2*((sqrt(5) + sqrt(3) + sqrt(2))^2*((sqrt(5) + sqrt(3) + sqrt(2))^2*((sqrt(5) + sqrt(3) + sqrt(2))^2 - 40) + 352) - 960) + 576
+            sage: f(a).simplify_radical()
+            0
+
+        Here we verify it gives the same result as the abstract number field. 
+            sage: (sqrt(2) + sqrt(3) + sqrt(6)).minpoly()
+            x^4 - 22*x^2 - 48*x - 23
+            sage: K.<a,b> = NumberField([x^2-2, x^2-3])
+            sage: (a+b+a*b).absolute_minpoly()
+            x^4 - 22*x^2 - 48*x - 23
+
+        Works with trig funcitons too. 
+            sage: sin(pi/3).minpoly()
+            x^2 - 3/4
+            
+        Here we show use of the epsilon parameter. That this result is 
+        actually exact can be shown using the addition formula for sin,
+        but maxima is unable to see that. 
+        
+            sage: a = sin(pi/5)
+            sage: a.minpoly()
+            Traceback (most recent call last):
+            ...
+            NotImplementedError: Could not prove minimal polynomial x^4 - 5/4*x^2 + 5/16 (epsilon 0.00000000000000e-1)
+            sage: f = a.minpoly(epsilon=1e-100); f
+            x^4 - 5/4*x^2 + 5/16
+            sage: f(a).numerical_approx(100)
+            0.00000000000000000000000000000
+            
+        The degree must be high enough (default tops out at 24). 
+            sage: a = sqrt(3) + sqrt(2)
+            sage: a.minpoly(bits=100, degree=3)
+            Traceback (most recent call last):
+            ...
+            ValueError: Could not find minimal polynomial (100 bits, degree 3).
+            sage: a.minpoly(bits=100, degree=10)
+            x^4 - 10*x^2 + 1
+            
+        Here we solve a cubic and then recover it from its complicated radical expansion. 
+            sage: f = x^3 - x + 1
+            sage: a = f.solve(x)[0].rhs(); a
+            (sqrt(3)*I/2 - 1/2)/(3*(sqrt(23)/(6*sqrt(3)) - 1/2)^(1/3)) + (sqrt(23)/(6*sqrt(3)) - 1/2)^(1/3)*(-sqrt(3)*I/2 - 1/2)
+            sage: a.minpoly()
+            x^3 - x + 1
+        """
+        bits_list = [bits] if bits else [100,200,500,1000]
+        degree_list = [degree] if degree else [2,4,8,12,24]
+        
+        for bits in bits_list:
+            a = self.numerical_approx(bits)
+            check_bits = int(1.25 * bits + 80)
+            aa = self.numerical_approx(check_bits)
+            
+            for degree in degree_list:
+
+                f = algdep(a, degree) # TODO: use the known_bits parameter?            
+                # If indeed we have found a minimal polynomial, 
+                # it should be accurate to a much higher precision. 
+                error = abs(f(aa))
+                dx = ~RR(Integer(1) << (check_bits - degree - 2))
+                expected_error = abs(f.derivative()(CC(aa))) * dx
+                
+                if error < expected_error:
+                    # Degree might have been an over-estimate, factor because we want (irreducible) minpoly. 
+                    ff = f.factor()
+                    for g, e in ff:
+                        lead = g.leading_coefficient()
+                        if lead != 1:
+                            g = g / lead
+                        expected_error = abs(g.derivative()(CC(aa))) * dx
+                        error = abs(g(aa))
+                        if error < expected_error:
+                            # See if we can prove equality exactly
+                            if g(self).simplify_trig().simplify_radical() == 0:
+                                return g
+                            # Otherwise fall back to numerical guess
+                            elif epsilon and error < epsilon:
+                                return g
+                            else:
+                                raise NotImplementedError, "Could not prove minimal polynomial %s (epsilon %s)" % (g, RR(error).str(no_sci=False))
+                    
+        raise ValueError, "Could not find minimal polynomial (%s bits, degree %s)." % (bits, degree)
+        
     def _mpfr_(self, field):
         raise TypeError
@@ -1044,5 +1201,5 @@
             3*x^35 + 2*y^35
             sage: parent(g)
-            Polynomial Ring in x, y over Finite Field of size 7
+            Multivariate Polynomial Ring in x, y over Finite Field of size 7
         """
         vars = self.variables()
@@ -1921,8 +2078,8 @@
             sage: var('x, u, v')
             (x, u, v)
-            sage: f = expand((2*u*v^2-v^2-4*u^3)^2 * (-u)^3 * (x-sin(x))^3)
-            sage: f.factor()
-            u^3*(2*u*v^2 - v^2 - 4*u^3)^2*(sin(x) - x)^3
-            sage: g = f.factor_list(); g
+            sage: f = expand((2*u*v^2-v^2-4*u^3)^2 * (-u)^3 * (x-sin(x))^3)     # not tested -- trac #946
+            sage: f.factor()                                 # not tested
+            u^3*(2*u*v^2 - v^2 - 4*u^3)^2*(sin(x) - x)^3     # not tested
+            sage: g = f.factor_list(); g                     # not tested 
             [(u, 3), (2*u*v^2 - v^2 - 4*u^3, 2), (sin(x) - x, 3)]
 
@@ -2506,5 +2663,5 @@
         """
         return R(self._obj)
-       
+        
     def _repr_(self, simplify=True):
         """
@@ -2796,5 +2953,5 @@
             new_ops = [ops[0]._recursive_sub_over_ring(kwds, ring=ring), Integer(ops[1])]
         else:
-            new_ops = [op._recursive_sub_over_ring(kwds, ring=ring) for op in ops]                
+            new_ops = [op._recursive_sub_over_ring(kwds, ring=ring) for op in ops]
         return ring(self._operator(*new_ops))
         
@@ -2989,11 +3146,17 @@
             return '%s%s' % (symbols[op], s[0])
         
-    def _latex_(self):
+    def _latex_(self, simplify=True):
         # if we are not simplified, return the latex of a simplified version
-        if not self.is_simplified():
+        if simplify and not self.is_simplified():
             return self.simplify()._latex_()
         op = self._operator
         ops = self._operands
-        s = [x._latex_() for x in self._operands]
+        s = []
+        for x in self._operands:
+            try:
+                s.append(x._latex_(simplify=simplify))
+            except TypeError:
+                s.append(x._latex_())
+        ## what it used to be --> s = [x._latex_() for x in self._operands]
 
         if op is operator.add:
@@ -3038,4 +3201,7 @@
 import re
 
+def is_SymbolicVariable(x):
+    return isinstance(x, SymbolicVariable)
+
 class SymbolicVariable(SymbolicExpression):
     def __init__(self, name):
@@ -3102,4 +3268,5 @@
     def _sys_init_(self, system):
         return self._name
+        
 
 _vars = {}
Index: sage/calculus/desolvers.py
===================================================================
--- sage/calculus/desolvers.py	(revision 5943)
+++ sage/calculus/desolvers.py	(revision 6996)
@@ -72,30 +72,30 @@
 
 #def desolve_laplace2(de,vars,ics=None):
-    """
-    Solves an ODE using laplace transforms via maxima. Initial conditions
-    are optional.
-
-    INPUT:
-        de    -- a lambda expression representing the ODE
-                 (eg, de = "diff(f(x),x,2)=diff(f(x),x)+sin(x)")
-        vars  -- a list of strings representing the variables
-                 (eg, vars = ["x","f"], if x is the independent
-                  variable and f is the dependent variable)
-        ics   -- a list of numbers representing initial conditions,
-                 with symbols allowed which are represented by strings
-                 (eg, f(0)=1, f'(0)=2 is ics = [0,1,2])
-
-    EXAMPLES:
-        sage.: from sage.calculus.desolvers import desolve_laplace
-        sage.: x = var('x')
-        sage.: f = function('f', x)
-        sage.: de = lambda y: diff(y,x,x) - 2*diff(y,x) + y
-        sage.: desolve_laplace(de(f(x)),[f,x])
-         #x*%e^x*(?%at('diff('f(x),x,1),x=0))-'f(0)*x*%e^x+'f(0)*%e^x
-        sage.: desolve_laplace(de(f(x)),[f,x],[0,1,2])  ## IC option does not work
-         #x*%e^x*(?%at('diff('f(x),x,1),x=0))-'f(0)*x*%e^x+'f(0)*%e^x
-
-    AUTHOR: David Joyner (1st version 1-2006, 8-2007)
-    """
+##     """
+##     Solves an ODE using laplace transforms via maxima. Initial conditions
+##     are optional.
+
+##     INPUT:
+##         de    -- a lambda expression representing the ODE
+##                  (eg, de = "diff(f(x),x,2)=diff(f(x),x)+sin(x)")
+##         vars  -- a list of strings representing the variables
+##                  (eg, vars = ["x","f"], if x is the independent
+##                   variable and f is the dependent variable)
+##         ics   -- a list of numbers representing initial conditions,
+##                  with symbols allowed which are represented by strings
+##                  (eg, f(0)=1, f'(0)=2 is ics = [0,1,2])
+
+##     EXAMPLES:
+##         sage: from sage.calculus.desolvers import desolve_laplace
+##         sage: x = var('x')
+##         sage: f = function('f', x)
+##         sage: de = lambda y: diff(y,x,x) - 2*diff(y,x) + y
+##         sage: desolve_laplace(de(f(x)),[f,x])
+##          #x*%e^x*(?%at('diff('f(x),x,1),x=0))-'f(0)*x*%e^x+'f(0)*%e^x
+##         sage: desolve_laplace(de(f(x)),[f,x],[0,1,2])  ## IC option does not work
+##          #x*%e^x*(?%at('diff('f(x),x,1),x=0))-'f(0)*x*%e^x+'f(0)*%e^x
+
+##     AUTHOR: David Joyner (1st version 1-2006, 8-2007)
+##     """
 #    ######## this method seems reasonable but doesnt work for some reason
 #    name0 = vars[0]._repr_()[0:(len(vars[0]._repr_())-2-len(str(vars[1])))]
@@ -231,9 +231,9 @@
         sage: from sage.calculus.desolvers import eulers_method
         sage: x,y = PolynomialRing(QQ,2,"xy").gens()
-        sage.: eulers_method(5*x+y-5,0,1,1/2,1)
-         x                    y                  h*f(x,y)
-         0                    1                   -2
-       1/2                   -1                 -7/4
-         1                -11/4                -11/8
+        sage: eulers_method(5*x+y-5,0,1,1/2,1)
+             x                    y                  h*f(x,y)
+             0                    1                   -2
+           1/2                   -1                 -7/4
+             1                -11/4                -11/8
         sage: x,y = PolynomialRing(QQ,2,"xy").gens()
         sage: eulers_method(5*x+y-5,0,1,1/2,1,method="none")
@@ -245,9 +245,9 @@
         sage: RR = RealField(sci_not=0, prec=4, rnd='RNDU')
         sage: x,y=PolynomialRing(RR,2,"xy").gens()
-        sage.: eulers_method(5*x+y-5,0,1,1/2,1)
-         x                    y                  h*f(x,y)
-         0                    1                -2.00
-       1/2                -1.00                -1.75
-         1                -2.75                -1.37
+        sage: eulers_method(5*x+y-5,0,1,1/2,1)
+             x                    y                  h*f(x,y)
+             0                    1                 -2.0
+           1/2                 -1.0                 -1.7
+             1                 -2.7                 -1.3
         sage: x,y=PolynomialRing(QQ,2,"xy").gens()
         sage: eulers_method(5*x+y-5,1,1,1/3,2)
@@ -262,5 +262,5 @@
         sage: P1 = list_plot(pts)
         sage: P2 = line(pts)
-        sage.: show(P1+P2)
+        sage: (P1+P2).show()
 
     AUTHOR: David Joyner
@@ -300,19 +300,19 @@
         sage: eulers_method_2x2(f,g, 0, 0, 0, 1/3, 1,method="none")
         [[0, 0, 0], [1/3, 0, 0], [2/3, 1/9, 0], [1, 10/27, 1/27], [4/3, 68/81, 4/27]]
-        sage.:. eulers_method_2x2(f,g, 0, 0, 0, 1/3, 1)
-         t                    x                h*f(t,x,y)                    y           h*g(t,x,y)
-         0                    0                         0                    0                    0
-       1/3                    0                       1/9                    0                    0
-       2/3                  1/9                      7/27                    0                 1/27
-         1                10/27                     38/81                 1/27                  1/9
-        sage.: RR = RealField(sci_not=0, prec=4, rnd='RNDU')
-        sage.: t,x,y=PolynomialRing(RR,3,"txy").gens()
-        sage.: f = x+y+t; g = x-y
-        sage.:. eulers_method_2x2(f,g, 0, 0, 0, 1/3, 1)
-         t                    x                h*f(t,x,y)                    y           h*g(t,x,y)
-         0                    0                     0.000                    0                0.000
-       1/3                0.000                     0.125                0.000                0.000
-       2/3                0.125                     0.282                0.000               0.0430
-         1                0.407                     0.563               0.0430                0.141
+        sage: eulers_method_2x2(f,g, 0, 0, 0, 1/3, 1)
+             t                    x                h*f(t,x,y)                    y           h*g(t,x,y)
+             0                    0                         0                    0                    0
+           1/3                    0                       1/9                    0                    0
+           2/3                  1/9                      7/27                    0                 1/27
+             1                10/27                     38/81                 1/27                  1/9
+        sage: RR = RealField(sci_not=0, prec=4, rnd='RNDU')
+        sage: t,x,y=PolynomialRing(RR,3,"txy").gens()
+        sage: f = x+y+t; g = x-y
+        sage: eulers_method_2x2(f,g, 0, 0, 0, 1/3, 1)
+             t                    x                h*f(t,x,y)                    y           h*g(t,x,y)
+             0                    0                      0.00                    0                 0.00
+           1/3                 0.00                      0.13                 0.00                 0.00
+           2/3                 0.13                      0.29                 0.00                0.043
+             1                 0.41                      0.57                0.043                 0.15
 
     To numerically approximate y(1), where (1+t^2)y''+y'-y=0, y(0)=1,y'(0)=-1, 
@@ -320,26 +320,26 @@
     y1' = y2, y1(0)=1; y2' = (y1-y2)/(1+t^2), y2(0)=-1.
 
-         sage.: RR = RealField(sci_not=0, prec=4, rnd='RNDU')
-         sage.: t, x, y=PolynomialRing(RR,3,"txy").gens()
-         sage.: f = y; g = (x-y)/(1+t^2)
-         sage.:. eulers_method_2x2(f,g, 0, 1, -1, 1/4, 1)
-         t                    x                h*f(t,x,y)                    y           h*g(t,x,y)
-         0                    1                    -0.250                   -1                0.500
-       1/4                0.750                    -0.125               -0.500                0.282
-       1/2                0.625                   -0.0546               -0.218                0.188
-       3/4                0.625                  -0.00781              -0.0312                0.110
-         1                0.625                    0.0196               0.0782               0.0704
+         sage: RR = RealField(sci_not=0, prec=4, rnd='RNDU')
+         sage: t, x, y=PolynomialRing(RR,3,"txy").gens()
+         sage: f = y; g = (x-y)/(1+t^2)
+         sage: eulers_method_2x2(f,g, 0, 1, -1, 1/4, 1)
+             t                    x                h*f(t,x,y)                    y           h*g(t,x,y)
+             0                    1                     -0.25                   -1                 0.50
+           1/4                 0.75                     -0.12                -0.50                 0.29
+           1/2                 0.63                    -0.054                -0.21                 0.19
+           3/4                 0.63                   -0.0078               -0.031                 0.11
+             1                 0.63                     0.020                0.079                0.071
 
     To numerically approximate y(1), where y''+ty'+y=0, y(0)=1,y'(0)=0: 
 
-        sage.: t,x,y=PolynomialRing(RR,3,"txy").gens()
-        sage.: f = y; g = -x-y*t
-        sage.:. eulers_method_2x2(f,g, 0, 1, 0, 1/4, 1)
-         t                    x                h*f(t,x,y)                    y           h*g(t,x,y)
-         0                    1                     0.000                    0               -0.250
-       1/4                 1.00                   -0.0625               -0.250               -0.234
-       1/2                0.938                    -0.117               -0.468               -0.171
-       3/4                0.875                    -0.156               -0.625               -0.101
-         1                0.750                    -0.171               -0.687              -0.0156
+        sage: t,x,y=PolynomialRing(RR,3,"txy").gens()
+        sage: f = y; g = -x-y*t
+        sage: eulers_method_2x2(f,g, 0, 1, 0, 1/4, 1)
+             t                    x                h*f(t,x,y)                    y           h*g(t,x,y)
+             0                    1                      0.00                    0                -0.25
+           1/4                  1.0                    -0.062                -0.25                -0.23
+           1/2                 0.94                     -0.11                -0.46                -0.17
+           3/4                 0.88                     -0.15                -0.62                -0.10
+             1                 0.75                     -0.17                -0.68               -0.015
 
     AUTHOR: David Joyner
Index: sage/calculus/functional.py
===================================================================
--- sage/calculus/functional.py	(revision 6071)
+++ sage/calculus/functional.py	(revision 6996)
@@ -94,5 +94,5 @@
         sage: f(x) = 1/(sqrt(2*pi)) * e^(-x^2/2)
         sage: P = plot(f, -4, 4, hue=0.8, thickness=2)
-        sage: P.save('sage.png', ymin=0, ymax=0.4)
+        sage: P.show(ymin=0, ymax=0.4)
         sage: numerical_integral(f, -4, 4)                    # random output
         (0.99993665751633376, 1.1101527003413533e-14)
Index: sage/calculus/tests.py
===================================================================
--- sage/calculus/tests.py	(revision 5841)
+++ sage/calculus/tests.py	(revision 6995)
@@ -53,5 +53,5 @@
     1/(4*sqrt(2))*x + 1/sqrt(2)
     sage: -f
-    (-1/(4*sqrt(2)))*x + -1/sqrt(2)
+    (-1/(4*sqrt(2)))*x - 1/sqrt(2)
     sage: (-f).degree()
     1
@@ -139,7 +139,7 @@
     sage: integrate(log(x)*exp(-x^2))        # todo -- mathematica can do this
     integrate(e^(-x^2)*log(x), x)
-    
-    sage.: # Todo -- Mathematica can do this and gets pi^2/15
-    sage.: # integrate(log(1+sqrt(1+4*x)/2)/x, x, 0, 1)
+
+Todo -- Mathematica can do this and gets pi^2/15
+    sage: integrate(log(1+sqrt(1+4*x)/2)/x, x, 0, 1)  # not tested
     [boom!]
     Integral is divergent
Index: sage/calculus/wester.py
===================================================================
--- sage/calculus/wester.py	(revision 5841)
+++ sage/calculus/wester.py	(revision 6991)
@@ -135,5 +135,5 @@
 y^4 + (-3)*y^2 + 1
 sage: factor(f)
-(y + -a) * (y + -a + 1) * (y + a - 1) * (y + a)
+(y - a) * (y - a + 1) * (y + a - 1) * (y + a)
 
 sage: # (YES) Factorize  x^4-3*x^2+1 mod 5.
Index: sage/categories/action.pyx
===================================================================
--- sage/categories/action.pyx	(revision 5742)
+++ sage/categories/action.pyx	(revision 6663)
@@ -35,9 +35,9 @@
 include "../ext/stdsage.pxi"
 
-def LeftAction(G, S, op=None):
-    return Action(G, S, 1, op)
-    
-def RightAction(G, S, op=None):
-    return Action(G, S, 0, op)
+#def LeftAction(G, S, op=None):
+#    return Action(G, S, 1, op)
+#    
+#def RightAction(G, S, op=None):
+#    return Action(G, S, 0, op)
 
 cdef class Action(Functor):
Index: sage/categories/category_types.py
===================================================================
--- sage/categories/category_types.py	(revision 6152)
+++ sage/categories/category_types.py	(revision 6995)
@@ -294,6 +294,6 @@
     EXAMPLES:
         sage: S = SymmetricGroup(3)
-        sage.: GSets(S)
-        Category of G-sets for Symmetric group of order 3! as a permutation group
+        sage: GSets(S)
+        Category of G-sets for SymmetricGroup(3)
     """
     def __init__(self, G):
@@ -308,6 +308,6 @@
         EXAMPLES:
             sage: S8 = SymmetricGroup(8)
-            sage.: C = GSets(S8)
-            sage.: loads(C.dumps()) == C
+            sage: C = GSets(S8)
+            sage: loads(C.dumps()) == C
             True
         """
@@ -1123,5 +1123,5 @@
         We create a scheme morphism from a ring homomorphism.x
             sage: phi = ZZ.hom(QQ); phi
-            Coercion morphism:
+            Ring Coercion morphism:
               From: Integer Ring
               To:   Rational Field
@@ -1130,5 +1130,5 @@
               From: Spectrum of Rational Field
               To:   Spectrum of Integer Ring
-              Defn: Coercion morphism:
+              Defn: Ring Coercion morphism:
                       From: Integer Ring
                       To:   Rational Field
@@ -1142,5 +1142,5 @@
               From: Spectrum of Rational Field
               To:   Spectrum of Integer Ring
-              Defn: Coercion morphism:
+              Defn: Ring Coercion morphism:
                       From: Integer Ring
                       To:   Rational Field
Index: sage/categories/homset.py
===================================================================
--- sage/categories/homset.py	(revision 5476)
+++ sage/categories/homset.py	(revision 6577)
@@ -55,4 +55,6 @@
         Set of Morphisms from Integer Ring to Rational Field in Category of sets
     """
+    if hasattr(X, '_Hom_'):
+        return X._Hom_(Y, cat)
     import category_types
     global _cache
@@ -249,5 +251,5 @@
             self.__domain, self.__codomain, self.__category)
 
-    def __call__(self, x, y=None):
+    def __call__(self, x, y=None, check=True):
         """
         Construct a morphism in this homset from x if possible.
Index: sage/categories/morphism.pxd
===================================================================
--- sage/categories/morphism.pxd	(revision 5476)
+++ sage/categories/morphism.pxd	(revision 6774)
@@ -17,5 +17,5 @@
 
 cdef class FormalCoercionMorphism(Morphism):
-    pass
+    cdef Element _call_c(self, x)
 
 cdef class FormalCompositeMorphism(Morphism):
Index: sage/categories/morphism.pyx
===================================================================
--- sage/categories/morphism.pyx	(revision 6221)
+++ sage/categories/morphism.pyx	(revision 6782)
@@ -54,4 +54,7 @@
         self._domain = _slots['_domain']
         self._codomain = _slots['_codomain']
+
+    def _test_update_slots(self, _slots):
+        self._update_slots(_slots)
     
     cdef _extra_slots(self, _slots):
@@ -59,4 +62,7 @@
         _slots['_codomain'] = self._codomain
         return _slots
+
+    def _test_extra_slots(self, _slots):
+        return self._extra_slots(_slots)
         
     def __reduce__(self):
@@ -101,9 +107,17 @@
                         
     def __call__(self, x):
-        if not PY_TYPE_CHECK(x, Element) or (<Element>x)._parent is not self._domain:
+        if not PY_TYPE_CHECK(x, Element):
+            try:
+                return self._call_c(x)
+            except TypeError:
+                raise TypeError, "%s must be coercible into %s (and is not an element)"%(x, self._domain)
+        elif (<Element>x)._parent is not self._domain:
             try:
                 x = self._domain(x)
             except TypeError:
-                raise TypeError, "%s must be coercible into %s"%(x,self._domain)
+                try:
+                    return self.pushforward(x)
+                except TypeError:
+                    raise TypeError, "%s must be coercible into %s"%(x, self._domain)
         return self._call_c(x)
 
@@ -118,4 +132,7 @@
             
     cdef Element _call_c_impl(self, Element x):
+        raise NotImplementedError
+
+    def pushforward(self, I):
         raise NotImplementedError
 
@@ -156,4 +173,5 @@
         return "Coercion"
 
+    # We need to override _call_c in this special case so that FormalCoercionMorphisms can operate on things that are not elements.
     cdef Element _call_c(self, x):
         return self._codomain._coerce_(x)
@@ -164,4 +182,5 @@
         return "Call"
 
+    # We need to override _call_c in this special case so that CallMorphisms can operate on things that are not elements.
     cdef Element _call_c(self, x):
         return self._codomain(x)
@@ -177,5 +196,5 @@
         return "Identity"
 
-    cdef Element _call_c(self, x):
+    cdef Element _call_c_impl(self, Element x):
         return x
         
@@ -205,7 +224,10 @@
         self.__first = _slots['__first']
         self.__second = _slots['__second']
-    
+        Morphism._update_slots(self, _slots)
+        
     cdef _extra_slots(self, _slots):
-        return Morphism._extra_slots(self, {'__first': self.__first, '__second': self.__second})
+        _slots['__first'] = self.__first
+        _slots['__second'] = self.__second
+        return Morphism._extra_slots(self, _slots)
 
     cdef Element _call_c_impl(self, Element x):
Index: sage/categories/pushout.py
===================================================================
--- sage/categories/pushout.py	(revision 5875)
+++ sage/categories/pushout.py	(revision 6689)
@@ -317,11 +317,11 @@
             TypeError: Ambiguous Base Extension
             sage: pushout(ZZ['x,y,z'], QQ['w,x,z,t'])
-            Polynomial Ring in w, x, y, z, t over Rational Field
+            Multivariate Polynomial Ring in w, x, y, z, t over Rational Field
 
         Some other examples
             sage: pushout(Zp(7)['y'], Frac(QQ['t'])['x,y,z'])
-            Polynomial Ring in x, y, z over Fraction Field of Univariate Polynomial Ring in t over 7-adic Field with capped relative precision 20
+            Multivariate Polynomial Ring in x, y, z over Fraction Field of Univariate Polynomial Ring in t over 7-adic Field with capped relative precision 20
             sage: pushout(ZZ['x,y,z'], Frac(ZZ['x'])['y'])
-            Polynomial Ring in y, z over Fraction Field of Univariate Polynomial Ring in x over Integer Ring
+            Multivariate Polynomial Ring in y, z over Fraction Field of Univariate Polynomial Ring in x over Integer Ring
             sage: pushout(MatrixSpace(RDF, 2, 2), Frac(ZZ['x']))
             Full MatrixSpace of 2 by 2 dense matrices over Fraction Field of Univariate Polynomial Ring in x over Real Double Field
@@ -338,4 +338,10 @@
     if R == S:
         return R
+    
+    if isinstance(R, type):
+        R = type_to_parent(R)
+
+    if isinstance(S, type):
+        S = type_to_parent(S)
 
     R_tower = construction_tower(R)
@@ -627,2 +633,15 @@
         c = R.construction()
     return tower
+
+
+
+def type_to_parent(P):
+    import sage.rings.all
+    if P in [int, long]:
+        return sage.rings.all.ZZ
+    elif P is float:
+        return sage.rings.all.RDF
+    elif P is complex:
+        return sage.rings.all.CDF
+    else:
+        raise TypeError, "Not a scalar type."
Index: sage/coding/code_bounds.py
===================================================================
--- sage/coding/code_bounds.py	(revision 4062)
+++ sage/coding/code_bounds.py	(revision 6995)
@@ -323,6 +323,5 @@
         sage: f = lambda x: gv_bound_asymp(x,2)
         sage: P = plot(f,0,1)
-        sage.: show(P)
-        
+        sage: P.save()
     """
     return (1-entropy(delta,q))
@@ -336,6 +335,5 @@
         sage: f = lambda x: hamming_bound_asymp(x,2)
         sage: P = plot(f,0,1)
-        sage.: show(P)
-        
+        sage: P.save()
     """
     return (1-entropy(delta/2,q))
@@ -348,5 +346,5 @@
         sage: f = lambda x: singleton_bound_asymp(x,2)
         sage: P = plot(f,0,1)
-        sage.: show(P)
+        sage: P.save()
         
     """
@@ -361,5 +359,4 @@
         sage: plotkin_bound_asymp(1/4,2)
         1/2 
-
     """
     r = 1-1/q
Index: sage/coding/code_constructions.py
===================================================================
--- sage/coding/code_constructions.py	(revision 6175)
+++ sage/coding/code_constructions.py	(revision 6439)
@@ -71,8 +71,8 @@
             Communication and Computing, 15, (2004), p. 63--79
     """
-    from sage.combinat.combinat import tuples
+    from sage.combinat.all import Tuples
     mset = [x for x in F if x!=0]
     d = len(P[0])
-    pts = tuples(mset,d) 
+    pts = Tuples(mset,d).list() 
     n = len(pts) ## (q-1)^d
     k = len(P)
Index: sage/coding/linear_code.py
===================================================================
--- sage/coding/linear_code.py	(revision 5504)
+++ sage/coding/linear_code.py	(revision 6877)
@@ -190,5 +190,5 @@
 from sage.rings.fraction_field import FractionField
 from sage.rings.integer_ring import IntegerRing
-from sage.combinat.combinat import partitions_set
+from sage.combinat.set_partition import SetPartitions
 
 ZZ = IntegerRing()
@@ -602,14 +602,4 @@
             sage: C.minimum_distance()
             3
-            sage: C = RandomLinearCode(10,5,GF(4,'a'))
-            sage: C.gen_mat()                ## random
-	    [    1     0     0     0     0 x + 1     1     0     0     0]
-	    [x + 1     1     0     1     0 x + 1     1     1     0     0]
-	    [    0 x + 1     0 x + 1     0     x x + 1 x + 1 x + 1     0]
-	    [    1     0     x     0     1     0     0     0     0     1]
-	    [    0     0     1     1     0     0     0     0     x x + 1]
-            sage: C.minimum_distance()       ## random
-            2
-
         """
         #sage: C.minimum_distance_upper_bound()  # optional (net connection)
@@ -1522,7 +1512,8 @@
         if i>n-dp and i<=n:
             return binomial(n,i)*(q**(i+k-n) -1)/(q-1)
-        P = partitions_set(J,2)
+        P = SetPartitions(J,2).list()
         b = QQ(0)
         for p in P:
+            p = list(p)
             S = p[0]
             if len(S)==n-i:
Index: sage/combinat/all.py
===================================================================
--- sage/combinat/all.py	(revision 2468)
+++ sage/combinat/all.py	(revision 6908)
@@ -2,4 +2,87 @@
 from expnums import expnums
 
+
+
+#Combinatorial Algebra
+from combinatorial_algebra import CombinatorialAlgebra
+
+
+from schubert_polynomial import SchubertPolynomialRing, is_SchubertPolynomial
+from symmetric_group_algebra import SymmetricGroupAlgebra
+#from hall_littlewood import HallLittlewood_qp, HallLittlewood_q, HallLittlewood_p
+
+from permutation import Permutation, Permutations, Arrangements, PermutationOptions, CyclicPermutations, CyclicPermutationsOfPartition
+import permutation
+
+#Compositions
+from composition import Composition, Compositions
+import composition
+from composition_signed import SignedCompositions
+
+#Partitions
+import partition
+from partition import Partition, Partitions, PartitionsInBox, OrderedPartitions, RestrictedPartitions, PartitionTuples, PartitionsGreatestLE, PartitionsGreatestEQ
+import skew_partition
+from skew_partition import SkewPartition, SkewPartitions
+from partition_algebra import SetPartitionsAk, SetPartitionsPk, SetPartitionsTk, SetPartitionsIk, SetPartitionsBk, SetPartitionsSk, SetPartitionsRk, SetPartitionsRk, SetPartitionsPRk
+
+#Tableaux
+from tableau import Tableau, Tableaux, StandardTableaux, SemistandardTableaux
+import tableau
+from skew_tableau import SkewTableau, StandardSkewTableaux
+import skew_tableau
+from ribbon import Ribbon, StandardRibbonTableaux
+import ribbon
+
+#Words
+from word import Words
+import word
+from subword import Subwords
+import subword
+
+import ranker
+from graph_path import GraphPaths
+
+#Tuples
+from tuple import Tuples, UnorderedTuples
+
+from alternating_sign_matrix import AlternatingSignMatrices, ContreTableaux, TruncatedStaircases
+
+
+from combination import Combinations
+import combination
+
+
+import choose_nk
+import multichoose_nk
+import permutation_nk
+import split_nk
+from cartesian_product import CartesianProduct
+
+from set_partition import SetPartitions
+import set_partition
+from set_partition_ordered import OrderedSetPartitions
+import set_partition_ordered
+
+import subset
+from subset import Subsets
+
+import q_analogues
+
+import necklace
+from necklace import Necklaces
+from lyndon_word import LyndonWords, StandardBracketedLyndonWords
+import lyndon_word
+
+from dyck_word import DyckWords, DyckWord
+
 from sloane_functions import sloane
 
+
+from sfa import SymmetricFunctionAlgebra, SFAPower, SFASchur, SFAHomogeneous, SFAElementary, SFAMonomial
+
+#import lrcalc
+
+import integer_list
+from integer_vector import IntegerVectors
+from integer_vector_weighted import WeightedIntegerVectors
Index: sage/combinat/alternating_sign_matrix.py
===================================================================
--- sage/combinat/alternating_sign_matrix.py	(revision 6439)
+++ sage/combinat/alternating_sign_matrix.py	(revision 6439)
@@ -0,0 +1,311 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from combinat import CombinatorialClass, CombinatorialObject
+from sage.matrix.matrix_space import MatrixSpace
+from sage.rings.all import ZZ, Integer, factorial
+from sage.sets.set import Set
+from sage.misc.misc import prod
+import copy
+
+def from_contre_tableau(comps):
+    """
+    Returns an alternating sign matrix from a contretableaux.
+
+    TESTS:
+        sage: import sage.combinat.alternating_sign_matrix as asm
+        sage: asm.from_contre_tableau([[1, 2, 3], [1, 2], [1]])
+        [0 0 1]
+        [0 1 0]
+        [1 0 0]
+        sage: asm.from_contre_tableau([[1, 2, 3], [2, 3], [3]])
+        [1 0 0]
+        [0 1 0]
+        [0 0 1]
+    """
+    n = len(comps)
+    MS = MatrixSpace(ZZ, n)
+    M = [ [0 for i in range(n)] for j in range(n) ]
+
+    previous_set = Set([])
+
+    for col in range(n-1, -1, -1):
+        set = Set( comps[col] )
+        for x in set - previous_set:
+            M[x-1][col] = 1
+
+        for x in previous_set - set:
+            M[x-1][col] = -1
+
+        previous_set = set
+
+    return MS(M)
+
+def AlternatingSignMatrices(n):
+    """
+    Returns the combinatorial class of alternating sign matrices of
+    size n.
+
+    EXAMPLES:
+        sage: a2 = AlternatingSignMatrices(2); a2
+        Alternating sign matrices of size 2
+        sage: for a in a2: print a, "-\n"
+        [0 1]
+        [1 0] 
+        -
+        [1 0]
+        [0 1]
+        -
+    """
+    return AlternatingSignMatrices_n(n)
+
+class AlternatingSignMatrices_n(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: a2 = AlternatingSignMatrices(2); a2
+            Alternating sign matrices of size 2
+            sage: a2 == loads(dumps(a2))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(AlternatingSignMatrices(2))
+            'Alternating sign matrices of size 2'
+        """
+        return "Alternating sign matrices of size %s"%self.n
+
+    def count(self):
+        """
+        TESTS:
+            sage: [ AlternatingSignMatrices(n).count() for n in range(0, 11)]
+            [1, 1, 2, 7, 42, 429, 7436, 218348, 10850216, 911835460, 129534272700]
+
+            sage: asms = [ AlternatingSignMatrices(n) for n in range(6) ]
+            sage: all( [ asm.count() == len(asm.list()) for asm in asms] )
+            True
+        """
+        return prod( [ factorial(3*k+1)/factorial(self.n+k) for k in range(self.n)] )
+
+    def iterator(self):
+        """
+
+        TESTS:
+            sage: AlternatingSignMatrices(0).list()
+            [[]]
+            sage: AlternatingSignMatrices(1).list()
+            [[1]]
+            sage: map(list, AlternatingSignMatrices(2).list())
+            [[(0, 1), (1, 0)], [(1, 0), (0, 1)]]
+            sage: map(list, AlternatingSignMatrices(3).list())
+            [[(0, 0, 1), (0, 1, 0), (1, 0, 0)],
+             [(0, 1, 0), (0, 0, 1), (1, 0, 0)],
+             [(0, 0, 1), (1, 0, 0), (0, 1, 0)],
+             [(0, 1, 0), (1, -1, 1), (0, 1, 0)],
+             [(0, 1, 0), (1, 0, 0), (0, 0, 1)],
+             [(1, 0, 0), (0, 0, 1), (0, 1, 0)],
+             [(1, 0, 0), (0, 1, 0), (0, 0, 1)]]
+
+        """
+        for z in ContreTableaux(self.n):
+            yield from_contre_tableau(z)
+
+
+def ContreTableaux(n):
+    """
+    Returns the combinatorial class of contre tableaux of size n.
+
+    EXAMPLES:
+        sage: ct4 = ContreTableaux(4); ct4
+        Contre tableaux of size 4
+        sage: ct4.count()
+        42
+        sage: ct4.first()
+        [[1, 2, 3, 4], [1, 2, 3], [1, 2], [1]]
+        sage: ct4.last()
+        [[1, 2, 3, 4], [2, 3, 4], [3, 4], [4]]
+        sage: ct4.random()  #random
+        [[1, 2, 3, 4], [2, 3, 4], [3, 4], [3]]
+    """
+    return ContreTableaux_n(n)
+
+class ContreTableaux_n(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: ct2 = ContreTableaux(2); ct2
+            Contre tableaux of size 2
+            sage: ct2 == loads(dumps(ct2))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(ContreTableaux(2))
+            'Contre tableaux of size 2'
+        """
+        return "Contre tableaux of size %s"%self.n
+
+    def count(self):
+        """
+        TESTS:
+            sage: [ ContreTableaux(n).count() for n in range(0, 11)]
+            [1, 1, 2, 7, 42, 429, 7436, 218348, 10850216, 911835460, 129534272700]
+        """
+        return prod( [ factorial(3*k+1)/factorial(self.n+k) for k in range(self.n)] )
+
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: ContreTableaux(0).list()     #indirect test
+            [[]]
+            sage: ContreTableaux(1).list()     #indirect test
+            [[[1]]]
+            sage: ContreTableaux(2).list()     #indirect test
+            [[[1, 2], [1]], [[1, 2], [2]]]
+            sage: ContreTableaux(3).list()     #indirect test
+            [[[1, 2, 3], [1, 2], [1]],
+             [[1, 2, 3], [1, 2], [2]],
+             [[1, 2, 3], [1, 3], [1]],
+             [[1, 2, 3], [1, 3], [2]],
+             [[1, 2, 3], [1, 3], [3]],
+             [[1, 2, 3], [2, 3], [2]],
+             [[1, 2, 3], [2, 3], [3]]]
+        """
+        def proc(i):
+            if i == 0:
+                yield []
+            elif i == 1:
+                yield [range(1, self.n+1)]
+
+            else:
+                for columns in proc(i-1):
+                    previous_column = columns[-1]
+                    for column in _next_column_iterator(previous_column, len(previous_column)-1):
+                        yield columns + [ column ]
+
+        for z in proc(self.n):
+            yield z
+
+
+
+
+def _next_column_iterator(previous_column, height):
+    """
+    Returns a generator for all columbs of height height
+    properly filled from row 1 to i
+
+    TESTS:
+        sage: import sage.combinat.alternating_sign_matrix as asm
+        sage: list(asm._next_column_iterator([1], 0))
+        [[]]
+        sage: list(asm._next_column_iterator([1,5],1))
+        [[1], [2], [3], [4], [5]]
+        sage: list(asm._next_column_iterator([1,4,5],2))
+        [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5], [4, 5]]
+    
+    """
+    assert height <= len(previous_column)-1
+    def proc(i):
+        if i == 0:
+            yield [-1]*height
+        else:
+            for column in proc(i-1):
+                min_value = previous_column[i-1]
+                if i > 1:
+                    min_value = max(min_value, column[i-2]+1)
+                for value in range(min_value, previous_column[i]+1):
+                    c = copy.copy(column)
+                    c[i-1] = value
+                    yield c
+
+    for z in proc(height):
+        yield z
+            
+def _previous_column_iterator(column, height, max_value):
+    """
+    TESTS:
+        sage: import sage.combinat.alternating_sign_matrix as asm
+        sage: list(asm._previous_column_iterator([2,3], 3, 4))
+        [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
+    """
+    new_column = [1] + column + [ max_value ] * (height - len(column))
+    return _next_column_iterator(new_column, height)
+        
+def TruncatedStaircases(n, last_column):
+    """
+    Returns the combinatorial class of truncated staircases
+    of size n with last column last_column.
+
+    EXAMPLES:
+        sage: t4 = TruncatedStaircases(4, [2,3]); t4
+        Truncated staircases of size 4 with last column [2, 3]
+        sage: t4.count()
+        4
+        sage: t4.first()
+        [[4, 3, 2, 1], [3, 2, 1], [3, 2]]
+        sage: t4.list()
+        [[[4, 3, 2, 1], [3, 2, 1], [3, 2]], [[4, 3, 2, 1], [4, 2, 1], [3, 2]], [[4, 3, 2, 1], [4, 3, 1], [3, 2]], [[4, 3, 2, 1], [4, 3, 2], [3, 2]]]
+    """
+    return TruncatedStaircases_nlastcolumn(n, last_column)
+
+class TruncatedStaircases_nlastcolumn(CombinatorialClass):
+    def __init__(self, n, last_column):
+        """
+        TESTS:
+            sage: t4 = TruncatedStaircases(4, [2,3]); t4
+            Truncated staircases of size 4 with last column [2, 3]
+            sage: t4 == loads(dumps(t4))
+            True
+        """
+        self.n = n
+        self.last_column = last_column
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(TruncatedStaircases(4, [2,3]))
+            'Truncated staircases of size 4 with last column [2, 3]'
+        """
+        return "Truncated staircases of size %s with last column %s"%(self.n, self.last_column)
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: TruncatedStaircases(4, [2,3]).list() #indirect test
+            [[[4, 3, 2, 1], [3, 2, 1], [3, 2]], [[4, 3, 2, 1], [4, 2, 1], [3, 2]], [[4, 3, 2, 1], [4, 3, 1], [3, 2]], [[4, 3, 2, 1], [4, 3, 2], [3, 2]]]
+
+        """
+        def proc(i):
+            if i < len(self.last_column):
+                return
+            elif i == len(self.last_column):
+                yield [self.last_column]
+            else:
+                for columns in proc(i-1):
+                    previous_column = columns[0]
+                    for column in _previous_column_iterator(previous_column, len(previous_column)+1, self.n):
+                        yield [column] + columns
+
+        for z in proc(self.n):
+            yield map(lambda x: list(reversed(x)), z)
+
+        
Index: sage/combinat/cartesian_product.py
===================================================================
--- sage/combinat/cartesian_product.py	(revision 6439)
+++ sage/combinat/cartesian_product.py	(revision 6439)
@@ -0,0 +1,142 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+import random as rnd
+import __builtin__
+from combinat import CombinatorialClass, CombinatorialObject
+
+
+def CartesianProduct(*iters):
+    """
+    Returns the combinatorial class of the cartesian
+    product of *iters.
+
+    EXAMPLES:
+        sage: cp = CartesianProduct([1,2], [3,4]); cp
+        Cartesian product of [1, 2], [3, 4]
+        sage: cp.list()
+        [[1, 3], [1, 4], [2, 3], [2, 4]]
+    """
+    return CartesianProduct_iters(*iters)
+
+class CartesianProduct_iters(CombinatorialClass):
+    def __init__(self, *iters):
+        """
+        TESTS:
+            sage: import sage.combinat.cartesian_product as cartesian_product
+            sage: cp = cartesian_product.CartesianProduct_iters([1,2],[3,4]); cp
+            Cartesian product of [1, 2], [3, 4]
+            sage: loads(dumps(cp)) == cp
+            True
+        """
+        self.iters = iters
+
+    def __repr__(self):
+        """
+        EXAMPLES:
+            sage: CartesianProduct(range(2), range(3))
+            Cartesian product of [0, 1], [0, 1, 2]
+        """
+        return "Cartesian product of " + ", ".join(map(str, self.iters))
+
+    def count(self):
+        """
+        Returns the number of elements in the cartesian product of
+        everything in *iters.
+
+        EXAMPLES:
+            sage: CartesianProduct(range(2), range(3)).count()
+            6
+            sage: CartesianProduct(range(2), xrange(3)).count()
+            6
+            sage: CartesianProduct(range(2), xrange(3), xrange(4)).count()
+            24
+        """
+        total = 1
+        for it in self.iters:
+            total *= len(it)
+        return total
+
+    
+    def list(self):
+        """
+        Returns
+
+        EXAMPLES:
+            sage: CartesianProduct(range(3), range(3)).list()
+            [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
+            sage: CartesianProduct('dog', 'cat').list()
+            [['d', 'c'],
+             ['d', 'a'],
+             ['d', 't'],
+             ['o', 'c'],
+             ['o', 'a'],
+             ['o', 't'],
+             ['g', 'c'],
+             ['g', 'a'],
+             ['g', 't']]
+        """
+        return [e for e in self.iterator()]
+
+
+    def iterator(self):
+        """
+        An iterator for the elements in the cartesian product
+        of the iterables *iters.
+
+        From Recipe 19.9 in the Python Cookbook by Alex Martelli
+        and David Ascher.
+
+        EXAMPLES:
+            sage: [e for e in CartesianProduct(range(3), range(3))]
+            [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
+            sage: [e for e in CartesianProduct('dog', 'cat')]
+            [['d', 'c'],
+             ['d', 'a'],
+             ['d', 't'],
+             ['o', 'c'],
+             ['o', 'a'],
+             ['o', 't'],
+             ['g', 'c'],
+             ['g', 'a'],
+             ['g', 't']]
+        """
+
+        # visualize an odometer, with "wheels" displaying "digits"...:
+        wheels = map(iter, self.iters)
+        digits = [it.next() for it in wheels]
+        while True:
+            yield __builtin__.list(digits)
+            for i in range(len(digits)-1, -1, -1):
+                try:
+                    digits[i] = wheels[i].next()
+                    break
+                except StopIteration:
+                    wheels[i] = iter(self.iters[i])
+                    digits[i] = wheels[i].next()
+            else:
+                break
+
+    def random(self):
+        """
+        Returns a random element from the cartesian product
+        of *iters.
+
+        EXAMPLES:
+            sage: CartesianProduct('dog', 'cat').random() #random
+            ['d', 'c']
+        """
+
+        return list(map(rnd.choice, self.iters))
Index: sage/combinat/choose_nk.py
===================================================================
--- sage/combinat/choose_nk.py	(revision 6439)
+++ sage/combinat/choose_nk.py	(revision 6439)
@@ -0,0 +1,207 @@
+from sage.rings.arith import binomial
+import random as rnd
+from combinat import CombinatorialClass
+
+def ChooseNK(n, k):
+    return ChooseNK_nk(n,k)
+
+class ChooseNK_nk(CombinatorialClass):
+    def __init__(self, n, k):
+        self.n = n
+        self.k = k
+
+        
+    def count(self):
+        """
+        Returns the number of choices of k things from a list
+        of n things.
+
+        EXAMPLES:
+            sage: from sage.combinat.choose_nk import ChooseNK
+            sage: ChooseNK(3,2).count()
+            3
+            sage: ChooseNK(5,2).count()
+            10
+        """
+        return binomial(self.n, self.k)
+
+    def iterator(self):
+        """
+        An iterator for all choies of k thinkgs from range(n).
+
+        EXAMPLES:
+            sage: from sage.combinat.choose_nk import ChooseNK
+            sage: [c for c in ChooseNK(5,2)]
+            [[0, 1],
+             [0, 2],
+             [0, 3],
+             [0, 4],
+             [1, 2],
+             [1, 3],
+             [1, 4],
+             [2, 3],
+             [2, 4],
+             [3, 4]]
+        """
+        k = self.k
+        n = self.n
+        dif = 1
+        if k == 0:
+            yield []
+            return
+
+        if n < 1+(k-1)*dif:
+            return
+        else:
+            subword = [ i*dif for i in range(k) ]
+
+        yield subword[:]
+        finished = False
+
+        while not finished:    
+            #Find the biggest element that can be increased
+            if subword[-1] < n-1:
+                subword[-1] += 1
+                yield subword[:]
+                continue
+
+            finished = True
+            for i in reversed(range(k-1)):
+                if subword[i]+dif < subword[i+1]:
+                    subword[i] += 1
+                    #Reset the bigger elements
+                    for j in range(1,k-i):
+                        subword[i+j] = subword[i]+j*dif
+                    yield subword[:]
+                    finished = False
+                    break
+
+        return 
+        
+
+    def random(self):
+        """
+        Returns a random choice of k things from range(n).
+
+        EXAMPLES:
+            sage: from sage.combinat.choose_nk import ChooseNK
+            sage: ChooseNK(5,2).random() #random
+            [0,3]
+        """
+        r = rnd.sample(xrange(self.n),self.k)
+        r.sort()
+        return r
+
+
+def rank(comb, n):
+    """
+    Returns the rank of comb in the subsets of range(n) of
+    size k.
+
+    The algorithm used is based on combinadics and James
+    McCaffrey's MSDN article.
+    See: http://en.wikipedia.org/wiki/Combinadic
+
+    EXAMPLES:
+        sage: import sage.combinat.choose_nk as choose_nk
+        sage: choose_nk.rank([], 3)
+        0
+        sage: choose_nk.rank([0], 3)
+        0
+        sage: choose_nk.rank([1], 3)
+        1
+        sage: choose_nk.rank([2], 3)
+        2
+        sage: choose_nk.rank([0,1], 3)
+        0
+        sage: choose_nk.rank([0,2], 3)
+        1
+        sage: choose_nk.rank([1,2], 3)
+        2
+        sage: choose_nk.rank([0,1,2], 3)
+        0        
+    """
+
+    k = len(comb)
+    if k > n:
+        raise ValueError, "len(comb) must be <= n"
+    
+    #Generate the combinadic from the
+    #combination
+    w = [0]*k
+    for i in range(k):
+        w[i] = (n-1) - comb[i]
+
+    #Calculate the integer that is the dual of
+    #the lexicographic index of the combination
+    r = k
+    t = 0
+    for i in range(k):
+        t += binomial(w[i],r)
+        r -= 1
+
+    return binomial(n,k)-t-1
+
+
+
+def _comb_largest(a,b,x):
+    """
+    Helper function for from_rank.
+    """
+    w = a - 1
+
+    while binomial(w,b) > x:
+        w -= 1
+
+    return w
+
+def from_rank(r, n, k):
+    """
+    Returns the combination of rank r in the subsets of range(n)
+    of size k when listed in lexicographic order.
+
+    The algorithm used is based on combinadics and James
+    McCaffrey's MSDN article. 
+    See: http://en.wikipedia.org/wiki/Combinadic
+
+
+    EXAMPLES:
+        sage: import sage.combinat.choose_nk as choose_nk
+        sage: choose_nk.from_rank(0,3,0)
+        []
+        sage: choose_nk.from_rank(0,3,1)
+        [0]
+        sage: choose_nk.from_rank(1,3,1)
+        [1]
+        sage: choose_nk.from_rank(2,3,1)
+        [2]
+        sage: choose_nk.from_rank(0,3,2)
+        [0, 1]
+        sage: choose_nk.from_rank(1,3,2)
+        [0, 2]
+        sage: choose_nk.from_rank(2,3,2)
+        [1, 2]
+        sage: choose_nk.from_rank(0,3,3)
+        [0, 1, 2]
+    """
+    if k < 0:
+        raise ValueError, "k must be > 0"
+    if k > n:
+        raise ValueError, "k must be <= n"
+    
+    a = n
+    b = k
+    x = binomial(n,k) - 1 - r # x is the 'dual' of m
+    comb = [None]*k
+
+    for i in range(k):
+        comb[i] = _comb_largest(a,b,x)
+        x = x - binomial(comb[i], b)
+        a = comb[i]
+        b = b -1
+
+    for i in range(k):
+        comb[i] = (n-1)-comb[i]
+
+    return comb
+
Index: sage/combinat/combinat.py
===================================================================
--- sage/combinat/combinat.py	(revision 5805)
+++ sage/combinat/combinat.py	(revision 6995)
@@ -6,8 +6,6 @@
         -- William Stein (2006-07), editing of docs and code; many optimizations,
                       refinements, and bug fixes in corner cases
-        -- David Joyner (2006-09): bug fix for combinations, added
-                      permutations_iterator, combinations_iterator
-                      from Python Cookbook, edited docs.
-        -- Bobby Moretti (2007-05) added a lazy fibonacci sequence generator
+        -- DJ (2006-09): bug fix for combinations, added permutations_iterator,
+                      combinations_iterator from Python Cookbook, edited docs.
                       
 This module implements some combinatorial functions, as listed
@@ -18,108 +16,101 @@
 \item Bell numbers, \code{bell_number}
 
-\item Bernoulli numbers, \code{bernoulli_number} (though PARI's
-  bernoulli is better)
-
-\item Catalan numbers, \code{catalan_number} (not to be confused with
-  the Catalan constant)
+\item Bernoulli numbers, \code{bernoulli_number} (though PARI's bernoulli is 
+  better)
+
+\item Catalan numbers, \code{catalan_number} (not to be confused with the
+  Catalan constant)
 
 \item Eulerian/Euler numbers, \code{euler_number} (Maxima)
 
-\item Fibonacci numbers, \code{fibonacci} (PARI) and
-  \code{fibonacci_number} (GAP) The PARI version is better.
+\item Fibonacci numbers, \code{fibonacci} (PARI) and \code{fibonacci_number} (GAP)
+  The PARI version is better.
 
 \item Lucas numbers, \code{lucas_number1}, \code{lucas_number2}.
  
-\item Stirling numbers, \code{stirling_number1},
-\code{stirling_number2}.
-
+\item Stirling numbers, \code{stirling_number1}, \code{stirling_number2}.
 \end{itemize}
  
 Set-theoretic constructions:
 \begin{itemize}
-
-\item Combinations of a multiset, \code{combinations},
-\code{combinations_iterator}, and \code{number_of_combinations}. These
-are unordered selections without repetition of k objects from a
-multiset S.
-
-\item Arrangements of a multiset, \code{arrangements} and
-  \code{number_of_arrangements} These are ordered selections without
-  repetition of k objects from a multiset S.
-
-\item Derangements of a multiset, \code{derangements} and
-\code{number_of_derangements}.
+\item Combinations of a multiset, \code{combinations}, \code{combinations_iterator},
+and \code{number_of_combinations}. These are unordered selections without
+repetition of k objects from a multiset S.
+
+\item Arrangements of a multiset, \code{arrangements} and \code{number_of_arrangements}
+  These are ordered selections without repetition of k objects from a 
+  multiset S.
+
+\item Derangements of a multiset, \code{derangements} and \code{number_of_derangements}.
 
 \item Tuples of a multiset, \code{tuples} and \code{number_of_tuples}.
-  An ordered tuple of length k of set S is a ordered selection with
-  repetitions of S and is represented by a sorted list of length k
-  containing elements from S.
-
-\item Unordered tuples of a set, \code{unordered_tuple} and
-  \code{number_of_unordered_tuples}.  An unordered tuple of length k
-  of set S is a unordered selection with repetitions of S and is
-  represented by a sorted list of length k containing elements from S.
-
-\item Permutations of a multiset, \code{permutations},
-\code{permutations_iterator}, \code{number_of_permutations}. A
-permutation is a list that contains exactly the same elements but
+  An ordered tuple of length k of set S is a ordered selection with 
+  repetitions of S and is represented by a sorted list of length k 
+  containing elements from S. 
+
+\item Unordered tuples of a set, \code{unordered_tuple} and \code{number_of_unordered_tuples}.
+  An unordered tuple of length k of set S is a unordered selection with 
+  repetitions of S and is represented by a sorted list of length k 
+  containing elements from S. 
+
+\item Permutations of a multiset, \code{permutations}, \code{permutations_iterator},
+\code{number_of_permutations}. A permutation is a list that contains exactly the same elements but 
 possibly in different order.
-
 \end{itemize}
 
 Partitions:
 \begin{itemize}
-
-\item Partitions of a set, \code{partitions_set},
-  \code{number_of_partitions_set}.  An unordered partition of set S is
-  a set of pairwise disjoint nonempty sets with union S and is
-  represented by a sorted list of such sets.
-
-\item Partitions of an integer, \code{partitions_list},
-  \code{number_of_partitions}.  An unordered partition of n is an
-  unordered sum $n = p_1+p_2 +\ldots+ p_k$ of positive integers and is
-  represented by the list $p = [p_1,p_2,\ldots,p_k]$, in nonincreasing
-  order, i.e., $p1\geq p_2 ...\geq p_k$.
-
-\item Ordered partitions of an integer, \code{ordered_partitions},
-  \code{number_of_ordered_partitions}.  An ordered partition of n is
-  an ordered sum $n = p_1+p_2 +\ldots+ p_k$ of positive integers and
-  is represented by the list $p = [p_1,p_2,\ldots,p_k]$, in
-  nonincreasing order, i.e., $p1\geq p_2 ...\geq p_k$.
-
-\item Restricted partitions of an integer,
-  \code{partitions_restricted},
-  \code{number_of_partitions_restricted}.  An unordered restricted
-  partition of n is an unordered sum $n = p_1+p_2 +\ldots+ p_k$ of
-  positive integers $p_i$ belonging to a given set $S$, and is
-  represented by the list $p = [p_1,p_2,\ldots,p_k]$, in nonincreasing
-  order, i.e., $p1\geq p_2 ...\geq p_k$.
-
-\item \code{partitions_greatest} implements a special type of
-   restricted partition.
-
-\item \code{partitions_greatest_eq} is another type of restricted
-partition.
+\item Partitions of a set, \code{partitions_set}, \code{number_of_partitions_set}.
+  An unordered partition of set S is a set of pairwise disjoint 
+  nonempty sets with union S and is represented by a sorted list of 
+  such sets. 
+
+\item Partitions of an integer, \code{partitions_list}, \code{number_of_partitions_list}.
+  An unordered partition of n is an unordered sum 
+  $n = p_1+p_2 +\ldots+ p_k$ of positive integers and is represented by 
+  the list $p = [p_1,p_2,\ldots,p_k]$, in nonincreasing order, i.e., 
+  $p1\geq p_2 ...\geq p_k$. 
+
+\item Ordered partitions of an integer, \code{ordered_partitions}, 
+  \code{number_of_ordered_partitions}.
+  An ordered partition of n is an ordered sum $n = p_1+p_2 +\ldots+ p_k$ 
+  of positive integers and is represented by 
+  the list $p = [p_1,p_2,\ldots,p_k]$, in nonincreasing order, i.e., 
+  $p1\geq p_2 ...\geq p_k$. 
+
+\item Restricted partitions of an integer, \code{partitions_restricted}, 
+  \code{number_of_partitions_restricted}.
+  An unordered restricted partition of n is an unordered sum 
+  $n = p_1+p_2 +\ldots+ p_k$ of positive integers $p_i$ belonging to a
+  given set $S$, and is represented by the list $p = [p_1,p_2,\ldots,p_k]$, 
+  in nonincreasing order, i.e., $p1\geq p_2 ...\geq p_k$. 
+
+\item \code{partitions_greatest}
+   implements a special type of restricted partition.
+
+\item \code{partitions_greatest_eq} is another type of restricted partition.
 
 \item Tuples of partitions, \code{partition_tuples},
-  \code{number_of_partition_tuples}.  A $k$-tuple of partitions is
-  represented by a list of all $k$-tuples of partitions which together
-  form a partition of $n$.
-
-\item Powers of a partition, \code{partition_power(pi, k)}.  The power
-  of a partition corresponds to the $k$-th power of a permutation with
-  cycle structure $\pi$.
-
-\item Sign of a partition, \code{partition_sign( pi ) } This means the
-  sign of a permutation with cycle structure given by the partition
-  pi.
-
-\item Associated partition, \code{partition_associated( pi )} The
-  ``associated'' (also called ``conjugate'' in the literature)
-  partition of the partition pi which is obtained by transposing the
+  \code{number_of_partition_tuples}.
+  A $k$-tuple of partitions is represented by a list of all $k$-tuples 
+  of partitions which together form a partition of $n$. 
+
+\item Powers of a partition, \code{partition_power(pi, k)}.
+  The power of a partition corresponds to the $k$-th power of a 
+  permutation with cycle structure $\pi$.
+
+\item Sign of a partition, \code{partition_sign( pi ) }
+  This means the sign of a permutation with cycle structure given by the 
+  partition pi.
+
+\item Associated partition, \code{partition_associated( pi )}
+  The ``associated'' (also called ``conjugate'' in the literature) 
+  partition of the partition pi which is obtained by transposing the 
   corresponding Ferrers diagram.
 
-\item Ferrers diagram, \code{ferrers_diagram}.  Analogous to the Young
-  diagram of an irredicible representation of $S_n$.  \end{itemize}
+\item Ferrers diagram, \code{ferrers_diagram}.
+  Analogous to the Young diagram of an irredicible representation 
+  of $S_n$.
+  \end{itemize}
 
 Related functions:
@@ -183,5 +174,6 @@
 
 #*****************************************************************************
-#       Copyright (C) 2006 David Joyner <wdjoyner@gmail.com>, 
+#       Copyright (C) 2006 David Joyner <wdjoyner@gmail.com>,
+#                     2007 Mike Hansen <mhansen@gmail.com>,
 #                     2006 William Stein <wstein@gmail.com>
 #
@@ -198,4 +190,6 @@
 #*****************************************************************************
 
+import os
+
 from sage.interfaces.all import gap, maxima
 from sage.rings.all import QQ, RR, ZZ
@@ -203,27 +197,27 @@
 from sage.misc.sage_eval import sage_eval
 from sage.libs.all import pari
-
-import expnums
+from sage.rings.arith import factorial
+from random import randint
+from sage.misc.misc import prod
+from sage.structure.sage_object import SageObject
+import __builtin__
+from sage.algebras.algebra import Algebra
+from sage.algebras.algebra_element import AlgebraElement
+import sage.structure.parent_base
 import partitions as partitions_ext
 
 ######### combinatorial sequences
 
-def bell_number(n, algorithm='sage'):
+def bell_number(n):
     r"""
     Returns the n-th Bell number (the number of ways to partition a
     set of n elements into pairwise disjoint nonempty subsets).
 
-    INPUT:
-        n -- an integer
-        algorithm -- 'sage': use N. Alexander's custom implementation in SAGE
-                     'gap': use Gap's Bell command (slow)
-
     If $n \leq 0$, returns $1$.
-
+    
+    Wraps GAP's Bell.
     
     EXAMPLES:
         sage: bell_number(10)
-        115975
-        sage: bell_number(10, algorithm='gap')
         115975
         sage: bell_number(2)
@@ -237,20 +231,7 @@
         ...
         TypeError: no coercion of this rational to integer
-
-    To compute all Bell numbers up to n, use expnums:
-        sage: expnums(10,1)
-        [1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147]
-        sage: [bell_number(n) for n in range(10)]
-        [1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147]
-    """
-    n = ZZ(n)
-    if n <= 0:
-        return ZZ(1)
-    if algorithm == 'sage':
-        return expnums.expnums(n+1,1)[-1]
-    elif algorithm == 'gap':
-        return ZZ(gap.eval("Bell(%s)"%ZZ(n)))
-    else:
-        raise ValueError, "unknown algorithm '%s'"%algorithm
+    """
+    ans=gap.eval("Bell(%s)"%ZZ(n))
+    return ZZ(eval(ans))
 
 ## def bernoulli_number(n):
@@ -269,7 +250,4 @@
     r"""
     Returns the n-th Catalan number 
-
-    INPUT:
-        n -- an integer
 
       Catalan numbers: The $n$-th Catalan number is given directly in terms of 
@@ -315,7 +293,4 @@
     Returns the n-th Euler number
 
-    INPUT:
-        n -- an integer
-
     IMPLEMENTATION: Wraps Maxima's euler.
     
@@ -342,10 +317,9 @@
 def fibonacci(n, algorithm="pari"):
     """
-    Returns then n-th Fibonacci number.
-
-    The Fibonacci sequence $F_n$ is defined by the initial conditions
-    $F_1=F_2=1$ and the recurrence relation $F_{n+2} = F_{n+1} +
-    F_n$. For negative $n$ we define $F_n = (-1)^{n+1}F_{-n}$, which
-    is consistent with the recurrence relation.
+    Returns then n-th Fibonacci number. The Fibonacci sequence $F_n$
+    is defined by the initial conditions $F_1=F_2=1$ and the
+    recurrence relation $F_{n+2} = F_{n+1} + F_n$. For negative $n$ we
+    define $F_n = (-1)^{n+1}F_{-n}$, which is consistent with the
+    recurrence relation.
 
     For negative $n$, define $F_{n} = -F_{|n|}$.
@@ -385,96 +359,4 @@
     else:
         raise ValueError, "no algorithm %s"%algorithm
-
-def fibonacci_sequence(start, stop=None, algorithm=None):
-    r"""
-    Returns an iterator over the Fibonacci sequence, for all fibonacci numbers
-    $f_n$ from \code{n = start} up to (but not including) \code{n = stop}
-
-    INPUT:
-        start -- starting value 
-        stop -- stopping value
-        algorithm -- default (None) -- passed on to fibonacci function (or
-                     not passed on if None, i.e., use the default).
-        
-
-    EXAMPLES:
-        sage: fibs = [i for i in fibonacci_sequence(10, 20)]
-        sage: fibs
-        [55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
-
-        sage: sum([i for i in fibonacci_sequence(100, 110)])
-        69919376923075308730013
-
-    SEE ALSO: fibonacci_xrange
-
-    AUTHOR:
-        Bobby Moretti
-    """
-    from sage.rings.integer_ring import ZZ
-    if stop is None:
-        stop = ZZ(start)
-        start = ZZ(0)
-    else:
-        start = ZZ(start)
-        stop = ZZ(stop)
-
-    if algorithm:
-        for n in xrange(start, stop):
-            yield fibonacci(n, algorithm=algorithm)
-    else:
-        for n in xrange(start, stop):
-            yield fibonacci(n)
-
-def fibonacci_xrange(start, stop=None, algorithm='pari'):
-    r"""
-    Returns an iterator over all of the Fibonacci numbers in the given range,
-    including \code{f_n = start} up to, but not including, \code{f_n = stop}.
-    
-    EXAMPLES:
-        sage: fibs_in_some_range =  [i for i in fibonacci_xrange(10^7, 10^8)]
-        sage: len(fibs_in_some_range)
-        4
-        sage: fibs_in_some_range
-        [14930352, 24157817, 39088169, 63245986]
-
-        sage: fibs = [i for i in fibonacci_xrange(10, 100)]
-        sage: fibs
-        [13, 21, 34, 55, 89]
-
-        sage: list(fibonacci_xrange(13, 34))
-        [13, 21]
-
-    A solution to the second Project Euler problem:
-        sage: sum([i for i in fibonacci_xrange(10^6) if is_even(i)])
-        1089154
-
-    SEE ALSO: fibonacci_sequence
-
-    AUTHOR:
-        Bobby Moretti
-    """
-    from sage.rings.integer_ring import ZZ
-    if stop is None:
-        stop = ZZ(start)
-        start = ZZ(0)
-    else:
-        start = ZZ(start)
-        stop = ZZ(stop)
-
-    # iterate until we've gotten high enough
-    fn = 0
-    n = 0
-    while fn < start:
-        n += 1
-        fn = fibonacci(n)
-
-    while True:
-        fn = fibonacci(n)
-        n += 1
-        if fn < stop:
-            yield fn
-        else:
-            return
-
 
 def lucas_number1(n,P,Q):
@@ -581,7 +463,7 @@
 def stirling_number1(n,k):
     """
-    Returns the n-th Stilling number $S_1(n,k)$ of the first kind (the
-    number of permutations of n points with k cycles).  Wraps GAP's
-    Stirling1.
+    Returns the n-th Stilling number $S_1(n,k)$ of the first kind (the number of 
+    permutations of n points with k cycles). 
+    Wraps GAP's Stirling1.
     
     EXAMPLES:
@@ -622,4 +504,720 @@
     return ZZ(gap.eval("Stirling2(%s,%s)"%(ZZ(n),ZZ(k))))
 
+def mod_stirling(q,n,k):
+    """
+    """
+    if k>n or k<0 or n<0:
+        raise ValueError, "n (= %s) and k (= %s) must greater than or equal to 0, and n must be greater than or equal to k"
+
+    if k == 0:
+        return 1
+    elif k == 1:
+        return (n**2+(2*q+1)*n)/2
+    elif k == n:
+        return prod( [ q+i for i in range(1, n+1) ] )
+    else:
+        return mod_stirling(q,n-1,k)+(q+n)*mod_stirling(q, n-1, k-1)
+    
+
+
+
+class CombinatorialObject(SageObject):
+    def __init__(self, l):
+        self.list = l
+
+    def __str__(self):
+        return str(self.list)
+
+    def __repr__(self):
+        return self.list.__repr__()
+    
+    def __eq__(self, other):
+        if isinstance(other, CombinatorialObject):
+            return self.list.__eq__(other.list)
+        else:
+            return self.list.__eq__(other)
+
+    def __lt__(self, other):
+        if isinstance(other, CombinatorialObject):
+            return self.list.__lt__(other.list)
+        else:
+            return self.list.__lt__(other)
+
+    def __le__(self, other):
+        if isinstance(other, CombinatorialObject):
+            return self.list.__le__(other.list)
+        else:
+            return self.list.__le__(other)
+
+    def __gt__(self, other):
+        if isinstance(other, CombinatorialObject):
+            return self.list.__gt__(other.list)
+        else:
+            return self.list.__gt__(other)
+
+    def __ge__(self, other):
+        if isinstance(other, CombinatorialObject):
+            return self.list.__ge__(other.list)
+        else:
+            return self.list.__ge__(other)
+
+    def __ne__(self, other):
+        if isinstance(other, CombinatorialObject):
+            return self.list.__ne__(other.list)
+        else:
+            return self.list.__ne__(other)
+
+    def __add__(self, other):
+        return self.list + other
+
+    def __hash__(self):
+        return str(self.list).__hash__()
+
+    #def __cmp__(self, other):
+    #    return self.list.__cmp__(other)
+
+    def __len__(self):
+        return self.list.__len__()
+
+    def __getitem__(self, key):
+        return self.list.__getitem__(key)
+
+    def __iter__(self):
+        return self.list.__iter__()
+
+    def __contains__(self, item):
+        return self.list.__contains__(item)
+
+
+    def index(self, key):
+        return self.list.index(key)
+    
+
+class CombinatorialClass(SageObject):
+    def __len__(self):
+        """
+        Returns the number of elements in the combinatorial class.
+
+        EXAMPLES:
+            sage: len(Partitions(5))
+            7
+        """
+        return self.count()
+
+    def __getitem__(self, i):
+        """
+        Returns the combinatorial object of rank i.
+
+        EXAMPLES:
+            sage: p5 = Partitions(5)
+            sage: p5[0]
+            [5]
+            sage: p5[6]
+            [1, 1, 1, 1, 1]
+            sage: p5[7]
+            Traceback (most recent call last):
+            ...
+            ValueError: the value must be between 0 and 6 inclusive
+        """
+        return self.unrank(i)
+
+    def __str__(self):
+        """
+        Returns a string representation of self.
+
+        EXAMPLES:
+            sage: str(Partitions(5))
+            'Partitions of the integer 5'
+        """
+        return self.__repr__()
+    
+    def __repr__(self):
+        """
+        EXAMPLES:
+            sage: repr(Partitions(5))
+            'Partitions of the integer 5'
+        """
+        if hasattr(self, '_name') and self._name:
+            return self._name
+        else:
+            return "Combinatorial Class -- REDEFINE ME!"
+
+    def __contains__(self, x):
+        """
+        Tests whether or not the combinatorial class contains the
+        object x.  This raises a NotImplementedError as a default
+        since _all_ subclasses of CombinatorialClass should
+        override this.
+
+        Note that we could replace this with a default implementation
+        that just iterates through the elements of the combinatorial
+        class and checks for equality.  However, since we use __contains__
+        for type checking, this operation should be cheap and should be
+        implemented manually for each combinatorial class.
+        """
+        raise NotImplementedError
+
+    def __iter__(self):
+        """
+        Allows the combinatorial class to be treated as an iterator.
+
+        EXAMPLES:
+            sage: p5 = Partitions(5)
+            sage: [i for i in p5]
+            [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]]
+        """
+        return self.iterator()
+
+    def __cmp__(self, x):
+        """
+        Compares two different combinatorial classes.  For now, the comparison
+        is done just on their repr's.
+
+        EXAMPLES:
+            sage: p5 = Partitions(5)
+            sage: p6 = Partitions(6)
+            sage: repr(p5) == repr(p6)
+            False
+            sage: p5 == p6
+            False
+        """
+        return cmp(repr(self), repr(x))
+    
+    def __count_from_iterator(self):
+        """
+        Default implmentation of count which just goes through the iterator
+        of the combinatorial class to count the number of objects.
+        """
+        c = 0
+        for x in self.iterator():
+            c += 1
+        return c
+    count = __count_from_iterator
+
+    def __call__(self, x):
+        """
+        Returns x as an element of the combinatorial class's object class.
+
+        EXAMPLES:
+            sage: p5 = Partitions(5)
+            sage: a = [2,2,1]
+            sage: type(a)
+            <type 'list'>
+            sage: a = p5(a)
+            sage: type(a)
+            <class 'sage.combinat.partition.Partition_class'>
+            sage: p5([2,1])
+            Traceback (most recent call last):
+            ...
+            ValueError: [2, 1] not in Partitions of the integer 5
+        """
+        if x in self:
+            return self.object_class(x)
+        else:
+            raise ValueError, "%s not in %s"%(x, self)
+
+    def __list_from_iterator(self):
+        """
+        The default implementation of list which builds the list from
+        the iterator.
+        """
+        return [x for x in self.iterator()]
+
+    #Set list to the default implementation
+    list  = __list_from_iterator
+
+    #Set the default object class to be CombinatorialObject
+    object_class = CombinatorialObject
+
+    def __iterator_from_next(self):
+        """
+        An iterator to use when .first() and .next() are provided.
+        """
+        f = self.first()
+        yield f
+        while True:
+            try:
+                f = self.next(f)
+            except:
+                break
+            
+            if f == None:
+                break
+            else:
+                yield f
+                
+    def __iterator_from_previous(self):
+        """
+        An iterator to use when .last() and .previous() are provided.
+        """
+        l = self.last()
+        yield l
+        while True:
+            try:
+                l = self.previous(l)
+            except:
+                break
+            
+            if l == None:
+                break
+            else:
+                yield l
+                
+    def __iterator_from_unrank(self):
+        """
+        An iterator to use when .unrank() is provided.
+        """
+        r = 0
+        u = self.unrank(r)
+        yield f
+        while True:
+            r += 1
+            try:
+                u = self.unrank(l)
+            except:
+                break
+            
+            if u == None:
+                break
+            else:
+                yield u
+
+    def __iterator_from_list(self):
+        """
+        An iterator to use when .list() is provided()
+        """
+        for x in self.list():
+            yield x
+            
+    def iterator(self):
+        """
+        Default implementation of iterator.
+        """
+        #Check to see if .first() and .next() are overridden in the subclass
+        if ( self.first != self.__first_from_iterator and
+             self.next  != self.__next_from_iterator ):
+            return self.__iterator_from_next()
+        #Check to see if .last() and .previous() are overridden in the subclass        
+        elif ( self.last != self.__last_from_iterator and
+               self.previous != self.__previous_from_iterator):
+            return self.__iterator_from_previous()
+        #Check to see if .unrank() is overridden in the subclass
+        elif self.unrank != self.__unrank_from_iterator:
+            return self.__iterator_from_unrank()
+        #Finally, check to see if .list() is overridden in the subclass
+        elif self.list != self.__list_from_iterator:
+            return self.__iterator_from_list()
+        else:
+            raise NotImplementedError, "iterator called but not implemented"
+
+
+    def __list_from_unrank_and_count(self):
+        return [ self.unrank(i) for i in range(self.count()) ]
+
+    def __unrank_from_iterator(self, r):
+        """
+        Default implementation of unrank which goes through the iterator.
+        """
+        counter = 0
+        for u in self.iterator():
+            if counter == r:
+                return u
+            counter += 1
+        raise ValueError, "the value must be between %s and %s inclusive"%(0,counter-1)
+
+    #Set the default implementation of unrank
+    unrank = __unrank_from_iterator
+
+    
+    def __random_from_unrank(self):
+        """
+        Default implementation of random which uses unrank.
+        """
+        c = self.count()
+        r = randint(0, c-1)
+        if hasattr(self, 'object_class'):
+            return self.object_class(self.unrank(r))
+        else:
+            return self.unrank(r)
+
+    #Set the default implementation of random
+    random = __random_from_unrank
+
+
+    def __rank_from_iterator(self, obj):
+        r = 0
+        for i in self.iterator():
+            if i == obj:
+                return r
+            r += 1
+            
+    rank =  __rank_from_iterator
+
+    def __first_from_iterator(self):
+        for i in self.iterator():
+            return i
+
+    first = __first_from_iterator
+
+    def __last_from_iterator(self):
+        for i in self.iterator():
+            pass
+        return i
+
+    last = __last_from_iterator
+
+    def __next_from_iterator(self, obj):
+        if hasattr(obj, 'next'):
+            res = obj.next()
+            if res:
+                return res
+            else:
+                return None
+        found = False
+        for i in self.iterator():
+            if found:
+                return i
+            if i == obj:
+                found = True
+        return None
+
+    next = __next_from_iterator
+
+    def __previous_from_iterator(self, obj):
+        if hasattr(obj, 'previous'):
+            res = obj.previous()
+            if res:
+                return res
+            else:
+                return None
+        prev = None
+        for i in self.iterator():
+            if i == obj:
+                break
+            prev = i
+        return prev
+
+    previous = __previous_from_iterator
+
+    def filter(self, f, name=None):
+        """
+        Returns the combinatorial subclass of f which consists of
+        the elements x of self such that f(x) is True.
+
+        EXAMPLES:
+            sage: P = Permutations(3).filter(lambda x: x.avoids([1,2]))
+            sage: P.list()
+            [[3, 2, 1]]
+        """
+        return FilteredCombinatorialClass(self, f, name=name)
+
+    def union(self, right_cc, name=None):
+        """
+        Returns the combinatorial class representing the union
+        of self and right_cc.
+
+        EXAMPLES:
+            sage: P = Permutations(2).union(Permutations(1))
+            sage: P.list()
+            [[1, 2], [2, 1], [1]]
+        """
+        return UnionCombinatorialClass(self, right_cc, name=name)
+
+class FilteredCombinatorialClass(CombinatorialClass):
+    def __init__(self, combinatorial_class, f, name=None):
+        """
+        TESTS:
+            sage: P = Permutations(3).filter(lambda x: x.avoids([1,2]))
+        """
+        self.f = f
+        self.combinatorial_class = combinatorial_class
+        self._name = name
+
+    def __repr__(self):
+        if self._name:
+            return self._name
+        else:
+            return "Filtered sublass of " + repr(self.combinatorial_class)
+
+    def __contains__(self, x):
+        return x in self.combinatorial_class and self.f(x)
+
+    def count(self):
+        c = 0
+        for x in self.iterator():
+            c += 1
+        return c
+
+    def list(self):
+        res = []
+        for x in self.combinatorial_class.iterator():
+            if self.f(x):
+                res.append(x)
+        return res
+
+    def iterator(self):
+        for x in self.combinatorial_class.iterator():
+            if self.f(x):
+                yield x
+
+    def __unrank_from_iterator(self, r):
+        """
+        Default implementation of unrank which goes through the iterator.
+        """
+        counter = 0
+        for u in self.iterator():
+            if counter == r:
+                return u
+            counter += 1
+        raise ValueError, "the value must be between %s and %s inclusive"%(0,counter-1)
+
+    #Set the default implementation of unrank
+    unrank = __unrank_from_iterator
+
+    
+    def __random_from_unrank(self):
+        """
+        Default implementation of random which uses unrank.
+        """
+        c = self.count()
+        r = randint(0, c-1)
+        if hasattr(self, 'object_class'):
+            return self.object_class(self.unrank(r))
+        else:
+            return self.unrank(r)
+
+    #Set the default implementation of random
+    random = __random_from_unrank
+
+
+    def __rank_from_iterator(self, obj):
+        r = 0
+        for i in self.iterator():
+            if i == obj:
+                return r
+            r += 1
+            
+    rank =  __rank_from_iterator
+
+    def __first_from_iterator(self):
+        for i in self.iterator():
+            return i
+
+    first = __first_from_iterator
+
+    def __last_from_iterator(self):
+        for i in self.iterator():
+            pass
+        return i
+
+    last = __last_from_iterator
+
+    def __next_from_iterator(self, obj):
+        if hasattr(obj, 'next'):
+            res = obj.next()
+            if res:
+                return res
+            else:
+                return None
+        found = False
+        for i in self.iterator():
+            if found:
+                return i
+            if i == obj:
+                found = True
+        return None
+
+    next = __next_from_iterator
+
+    def __previous_from_iterator(self, obj):
+        if hasattr(obj, 'previous'):
+            res = obj.previous()
+            if res:
+                return res
+            else:
+                return None
+        prev = None
+        for i in self.iterator():
+            if i == obj:
+                break
+            prev = i
+        return prev
+
+    previous = __previous_from_iterator
+
+
+class UnionCombinatorialClass(CombinatorialClass):
+    def __init__(self, left_cc, right_cc, name=None):
+        """
+        TESTS:
+            sage: P = Permutations(3).union(Permutations(2))
+            sage: P == loads(dumps(P))
+            True
+        """
+        self.left_cc = left_cc
+        self.right_cc = right_cc
+        self._name = name
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: print repr(Permutations(3).union(Permutations(2)))
+            Union combinatorial class of 
+                Standard permutations of 3
+            and
+                Standard permutations of 2
+
+        """
+        if self._name:
+            return self._name
+        else:
+            return "Union combinatorial class of \n    %s\nand\n    %s"%(self.left_cc, self.right_cc)
+
+    def __contains__(self, x):
+        return x in self.left_cc or x in self.right_cc
+
+    def count(self):
+        return self.left_cc.count() + self.right_cc.count()
+
+    def list(self):
+        res = []
+        for x in self.left_cc.iterator():
+            res.append(x)
+        for x in self.right_cc.iterator():
+            res.append(x)
+        return res
+
+    def iterator(self):
+        for x in self.left_cc.iterator():
+            yield x
+        for x in self.right_cc.iterator():
+            yield x
+
+    def __unrank_from_iterator(self, r):
+        """
+        Default implementation of unrank which goes through the iterator.
+        """
+        counter = 0
+        for u in self.iterator():
+            if counter == r:
+                return u
+            counter += 1
+        raise ValueError, "the value must be between %s and %s inclusive"%(0,counter-1)
+
+    #Set the default implementation of unrank
+    unrank = __unrank_from_iterator
+    
+    def __random_from_unrank(self):
+        """
+        Default implementation of random which uses unrank.
+        """
+        c = self.count()
+        r = randint(0, c-1)
+        if hasattr(self, 'object_class'):
+            return self.object_class(self.unrank(r))
+        else:
+            return self.unrank(r)
+
+    #Set the default implementation of random
+    random = __random_from_unrank
+
+    def __rank_from_iterator(self, obj):
+        r = 0
+        for i in self.iterator():
+            if i == obj:
+                return r
+            r += 1
+            
+    rank =  __rank_from_iterator
+
+    def __first_from_iterator(self):
+        for i in self.iterator():
+            return i
+
+    first = __first_from_iterator
+
+    def __last_from_iterator(self):
+        for i in self.iterator():
+            pass
+        return i
+
+    last = __last_from_iterator
+
+    def __next_from_iterator(self, obj):
+        if hasattr(obj, 'next'):
+            res = obj.next()
+            if res:
+                return res
+            else:
+                return None
+        found = False
+        for i in self.iterator():
+            if found:
+                return i
+            if i == obj:
+                found = True
+        return None
+
+    next = __next_from_iterator
+
+    def __previous_from_iterator(self, obj):
+        if hasattr(obj, 'previous'):
+            res = obj.previous()
+            if res:
+                return res
+            else:
+                return None
+        prev = None
+        for i in self.iterator():
+            if i == obj:
+                break
+            prev = i
+        return prev
+
+    previous = __previous_from_iterator
+        
+
+def hurwitz_zeta(s,x,N):
+    """
+    Returns the value of the $\zeta(s,x)$ to $N$ decimals, where s and x are real.
+
+    The Hurwitz zeta function is one of the many zeta functions. It defined as
+    \[
+    \zeta(s,x) = \sum_{k=0}^\infty (k+x)^{-s}.
+    \]
+    When $x = 1$, this coincides with Riemann's zeta function. The Dirichlet L-functions 
+    may be expressed as a linear combination of Hurwitz zeta functions.
+
+    EXAMPLES:
+        sage: hurwitz_zeta(3,1/2,6)
+        8.41439000000000
+        sage: hurwitz_zeta(1.1,1/2,6)
+        12.1041000000000
+        sage: hurwitz_zeta(1.1,1/2,50)
+        12.103813495683744469025853545548130581952676591199
+
+    REFERENCES:
+        http://en.wikipedia.org/wiki/Hurwitz_zeta_function
+
+    """
+    maxima.eval('load ("bffac")')
+    s = maxima.eval("bfhzeta (%s,%s,%s)"%(s,x,N))
+
+    #Handle the case where there is a 'b' in the string
+    #'1.2000b0' means 1.2000 and
+    #'1.2000b1' means 12.000
+    i = s.rfind('b')
+    if i == -1:
+        return sage_eval(s)
+    else:
+        if s[i+1:] == '0':
+            return sage_eval(s[:i])
+        else:
+            return sage_eval(s[:i])*10**sage_eval(s[i+1:])
+    
+    return s  ## returns an odd string
+
+
+#####################################################
 #### combinatorial sets/lists
 
@@ -1133,5 +1731,5 @@
 
     """
-    if k==None:
+    if k is None:
         ans=gap.eval("NrPartitionsSet(%s)"%S)
     else:
@@ -1174,5 +1772,5 @@
     if n <= 0:
         raise ValueError, "n (=%s) must be a positive integer"%n
-    if k==None:
+    if k is None:
         ans=gap.eval("Partitions(%s)"%(n))
     else:
@@ -1190,6 +1788,9 @@
              the positive integer n into sums with k summands.
         algorithm -- (default: 'default')
-            'bober' -- use Jonathon Bober's implementation (*very* fast,
-                      but new and not well tested yet).
+            'default' -- If k is not None, then use Gap (very slow).
+                         If k is None, use Jon Bober's highly
+                         optimized implementation (this is the fastest
+                         code in the world for this problem).
+            'bober' -- use Jonathon Bober's implementation
             'gap' -- use GAP (VERY *slow*)
             'pari' -- use PARI.  Speed seems the same as GAP until $n$ is
@@ -1198,6 +1799,4 @@
                       outputs numbpart(147007)%1000 as 536, but it
                       should be 533!.  So do not use this option.
-            'default' -- 'bober' when k is not specified; otherwise
-                      use 'gap'.
 
     IMPLEMENTATION: Wraps GAP's NrPartitions or PARI's numbpart function.
@@ -1245,4 +1844,6 @@
         sage: number_of_partitions(100)
         190569292
+        sage: number_of_partitions(100000)
+        27493510569775696512677516320986352688173429315980054758203125984302147328114964173055050741660736621590157844774296248940493063070200461792764493033510116079342457190155718943509725312466108452006369558934464248716828789832182345009262853831404597021307130674510624419227311238999702284408609370935531629697851569569892196108480158600569421098519
 
     A generating function for p(n) is given by the reciprocal of
@@ -1265,4 +1866,39 @@
         http://en.wikipedia.org/wiki/Partition_%28number_theory%29
 
+    TESTS:
+        sage: n = 500 + randint(0,500)
+        sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0
+        True
+        sage: n = 1500 + randint(0,1500)
+        sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0
+        True
+        sage: n = 1000000 + randint(0,1000000)
+        sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0
+        True
+        sage: n = 1000000 + randint(0,1000000)
+        sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0
+        True
+        sage: n = 1000000 + randint(0,1000000)
+        sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0
+        True
+        sage: n = 1000000 + randint(0,1000000)
+        sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0
+        True
+        sage: n = 1000000 + randint(0,1000000)
+        sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0
+        True
+        sage: n = 1000000 + randint(0,1000000)
+        sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0
+        True
+        sage: n = 100000000 + randint(0,100000000)  
+        sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0
+        True
+        sage: n = 1000000000 + randint(0,1000000000)  
+        sage: number_of_partitions( n - (n % 385) + 369) % 385 == 0      # takes a long time
+        True
+
+    Another consistency test for n up to 500:
+        sage: len([n for n in [1..500] if number_of_partitions(n) != number_of_partitions(n,algorithm='pari')])
+        0
     """
     n = ZZ(n)
@@ -1271,20 +1907,27 @@
     elif n == 0:
         return ZZ(1)
-    if algorithm == 'gap' or (not k is None and algorithm=='default'):
-        if k==None:
+
+    if algorithm == 'default':
+        if k is None:
+            algorithm = 'bober'
+        else:
+            algorithm = 'gap'
+            
+    if algorithm == 'gap':
+        if k is None:
             ans=gap.eval("NrPartitions(%s)"%(ZZ(n)))
         else:
             ans=gap.eval("NrPartitions(%s,%s)"%(ZZ(n),ZZ(k)))
         return ZZ(ans)
-    if not k is None:
+    
+    if k is not None:
         raise ValueError, "only the GAP algorithm works if k is specified."
-    if algorithm == 'default' and k is None:
+
+    if algorithm == 'bober':
         return partitions_ext.number_of_partitions(n)
-    elif algorithm == 'bober' and k is None:
-        return partitions_ext.number_of_partitions(n)
+        
     elif algorithm == 'pari':
-        if not k is None:
-            raise ValueError, "cannot specify second argument k if the algorithm is PARI"
         return ZZ(pari(ZZ(n)).numbpart())
+    
     raise ValueError, "unknown algorithm '%s'"%algorithm
 
@@ -1300,5 +1943,5 @@
 
     EXAMPLES:
-        sage.: partitions(3)
+        sage: partitions(3)          # random location
         <generator object at 0xab3b3eac>
         sage: list(partitions(3))
@@ -1455,5 +2098,5 @@
 
     """
-    if k==None:
+    if k is None:
         ans=gap.eval("OrderedPartitions(%s)"%(ZZ(n)))
     else:
@@ -1478,5 +2121,5 @@
         16384
     """
-    if k==None:
+    if k is None:
         ans=gap.eval("NrOrderedPartitions(%s)"%(n))
     else:
@@ -1548,5 +2191,5 @@
         [[5, 3], [7, 1]]
     """
-    if k==None:
+    if k is None:
         ans=gap.eval("RestrictedPartitions(%s,%s)"%(n,S))
     else:
@@ -1566,5 +2209,5 @@
 
     """
-    if k==None:
+    if k is None:
         ans=gap.eval("NrRestrictedPartitions(%s,%s)"%(ZZ(n),S))
     else:
@@ -1756,54 +2399,2 @@
     ans=gap.eval("AssociatedPartition(%s)"%(pi))
     return eval(ans)
-
-## related functions
-
-def bernoulli_polynomial(x,n):
-    r"""
-    The generating function for the Bernoulli polynomials is
-    \[
-     \frac{t e^{xt}}{e^t-1}= \sum_{n=0}^\infty B_n(x) \frac{t^n}{n!}. 
-    \]
-
-    One has $B_n(x) = - n\zeta(1 - n,x)$, where $\zeta(s,x)$ is the
-    Hurwitz zeta function.  Thus, in a certain sense, the Hurwitz zeta
-    generalizes the Bernoulli polynomials to non-integer values of n.
-
-    EXAMPLES:
-        sage: y = QQ['y'].0
-        sage: bernoulli_polynomial(y,5)
-        y^5 - 5/2*y^4 + 5/3*y^3 - 1/6*y
-
-    REFERENCES:
-        http://en.wikipedia.org/wiki/Bernoulli_polynomials
-    """
-    return sage_eval(maxima.eval("bernpoly(x,%s)"%n), {'x':x})
-
-
-#def hurwitz_zeta(s,x,N):
-#    """
-#    Returns the value of the $\zeta(s,x)$ to $N$ decimals, where s and x are real.
-#
-#    The Hurwitz zeta function is one of the many zeta functions. It defined as
-#    \[
-#    \zeta(s,x) = \sum_{k=0}^\infty (k+x)^{-s}.
-#    \]
-#    When $x = 1$, this coincides with Riemann's zeta function. The Dirichlet L-functions 
-#    may be expressed as a linear combination of Hurwitz zeta functions.
-#
-#    EXAMPLES:
-#        sage: hurwitz_zeta(3,1/2,6)
-#        '8.41439b0'
-#        sage: hurwitz_zeta(1.1,1/2,6)
-#        'Warning:Floattobigfloatconversionof12.1040625294406841.21041b1'
-#
-#    "b0" can be ignored, but "b1" means that the decimal point was shifted 
-#    1 to the left (so the answer is not 1.21041b1 but 12.10406).
-#
-#    REFERENCES:
-#        http://en.wikipedia.org/wiki/Hurwitz_zeta_function
-#
-#    """
-#    maxima.eval('load ("bffac")')
-#    s = maxima.eval("bfhzeta (%s,%s,%s)"%(s,x,N))
-#    return s  ## returns an odd string
Index: sage/combinat/combination.py
===================================================================
--- sage/combinat/combination.py	(revision 6439)
+++ sage/combinat/combination.py	(revision 6439)
@@ -0,0 +1,179 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from sage.interfaces.all import gap
+from sage.rings.all import QQ, RR, ZZ
+from combinat import CombinatorialObject, CombinatorialClass
+
+def Combinations(mset, k=None):
+    """
+    Returns the combinatorial class of combinations of mset. If
+    k is specified, then it returns the the combintorial class
+    of combinations of mset of size k.
+
+    The combinatorial classes correctly handle the cases where
+    mset has duplicate elements.
+
+    EXAMPLES:
+        sage: C = Combinations(range(4)); C
+        Combinations of [0, 1, 2, 3]
+        sage: C.list()
+        [[],
+         [0],
+         [1],
+         [2],
+         [3],
+         [0, 1],
+         [0, 2],
+         [0, 3],
+         [1, 2],
+         [1, 3],
+         [2, 3],
+         [0, 1, 2],
+         [0, 1, 3],
+         [0, 2, 3],
+         [1, 2, 3],
+         [0, 1, 2, 3]]
+         sage: C.count()
+         16
+         
+         sage: C2 = Combinations(range(4),2); C2
+         Combinations of [0, 1, 2, 3] of length 2
+         sage: C2.list()
+         [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]]
+         sage: C2.count()
+         6
+
+         sage: Combinations([1,2,2,3]).list()
+         [[],
+          [1],
+          [2],
+          [3],
+          [1, 2],
+          [1, 3],
+          [2, 2],
+          [2, 3],
+          [1, 2, 2],
+          [1, 2, 3],
+          [2, 2, 3],
+          [1, 2, 2, 3]]
+    """
+    if k is None:
+        return Combinations_mset(mset)
+    else:
+        return Combinations_msetk(mset,k)
+
+class Combinations_mset(CombinatorialClass):
+    def __init__(self, mset):
+        """
+        TESTS:
+            sage: C = Combinations(range(4))
+            sage: C == loads(dumps(C))
+            True
+        """
+        self.mset = mset
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Combinations(range(4)))
+            'Combinations of [0, 1, 2, 3]'
+        """
+        return "Combinations of %s"%self.mset
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: Combinations([1,2,3]).list() #indirect test
+            [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]
+            sage: Combinations(['a','a','b']).list() #indirect test
+            [[], ['a'], ['b'], ['a', 'a'], ['a', 'b'], ['a', 'a', 'b']]
+        """
+        for k in range(len(self.mset)+1):
+            for comb in Combinations_msetk(self.mset, k):
+                yield comb
+
+    def count(self):
+        """
+        TESTS:
+            sage: Combinations([1,2,3]).count()
+            8
+            sage: Combinations(['a','a','b']).count()
+            6
+        """
+        c = 0
+        for k in range(len(self.mset)+1):
+            c +=  Combinations_msetk(self.mset, k).count()
+        return c
+
+
+class Combinations_msetk(CombinatorialClass):
+    def __init__(self, mset, k):
+        """
+        TESTS:
+            sage: C = Combinations([1,2,3],2)
+            sage: C == loads(dumps(C))
+            True
+        """
+        self.mset = mset
+        self.k = k
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Combinations([1,2,3],2))
+            'Combinations of [1, 2, 3] of length 2'
+        """
+        return "Combinations of %s of length %s"%(self.mset, self.k)
+    
+    def list(self):
+        """
+        Wraps GAP's Combinations.
+        EXAMPLES:
+            sage: Combinations([1,2,3,4,5],3).list()
+            [[1, 2, 3],
+             [1, 2, 4],
+             [1, 2, 5],
+             [1, 3, 4],
+             [1, 3, 5],
+             [1, 4, 5],
+             [2, 3, 4],
+             [2, 3, 5],
+             [2, 4, 5],
+             [3, 4, 5]]
+            sage: Combinations(['a','a','b'],2).list()
+            [['a', 'a'], ['a', 'b']]
+        """
+        def label(x):
+            return self.mset[x]
+
+        items = map(self.mset.index, self.mset)
+        ans=eval(gap.eval("Combinations(%s,%s)"%(items,ZZ(self.k))).replace("\n",""))
+
+        return map(lambda x: map(label, x), ans)
+        
+
+    def count(self):
+        """
+        Returns the size of combinations(mset,k).
+        IMPLEMENTATION: Wraps GAP's NrCombinations.
+
+        EXAMPLES:
+            sage: mset = [1,1,2,3,4,4,5]
+            sage: Combinations(mset,2).count()
+            12
+        """
+        items = map(self.mset.index, self.mset)
+        return ZZ(gap.eval("NrCombinations(%s,%s)"%(items,ZZ(self.k))))
Index: sage/combinat/combinatorial_algebra.py
===================================================================
--- sage/combinat/combinatorial_algebra.py	(revision 6594)
+++ sage/combinat/combinatorial_algebra.py	(revision 6594)
@@ -0,0 +1,384 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from sage.interfaces.all import gap, maxima
+from sage.rings.all import QQ, RR, ZZ
+from sage.rings.arith import binomial
+from sage.misc.sage_eval import sage_eval
+from sage.libs.all import pari
+from sage.rings.all import Ring, factorial, Integer
+from random import randint
+from sage.misc.misc import prod, repr_lincomb
+from sage.structure.sage_object import SageObject
+import __builtin__
+from sage.algebras.algebra import Algebra
+from sage.algebras.algebra_element import AlgebraElement
+import sage.structure.parent_base
+import sage.combinat.partition
+
+
+class CombinatorialAlgebraElement(AlgebraElement):
+    def __init__(self, A, x):
+        """
+        """
+        AlgebraElement.__init__(self, A)
+        self._monomial_coefficients = x
+
+
+    def monomial_coefficients(self):
+        return self._monomial_coefficients
+    
+    def _repr_(self):
+        v = self._monomial_coefficients.items()
+
+        prefix = self.parent().prefix()
+        mons = [ prefix + str(m) for (m, _) in v ]
+        cffs = [ x for (_, x) in v ]
+        x = repr_lincomb(mons, cffs).replace("*1 "," ")
+        if x[len(x)-2:] == "*1":
+            return x[:len(x)-2]
+        else:
+            return x
+
+    def _latex_(self):
+        v = self._monomial_coefficients.items()
+        v.sort()
+        prefix = self.parent().prefix()
+        mons = [ prefix + '_{' + ",".join(map(str, m)) + '}' for (m, _) in v ]
+        cffs = [ x for (_, x) in v ]
+        x = repr_lincomb(mons, cffs, is_latex=True).replace("*1 "," ")
+        if x[len(x)-2:] == "*1":
+            return x[:len(x)-2]
+        else:
+            return x        
+
+    def _eq_(self, right):
+        for b in self.parent()._combinatorial_class:
+            if self.coefficient(b) != right.coefficient(b):
+                return False
+        return True
+
+    def __cmp__(left, right):
+        """
+        The ordering is the one on the underlying sorted list of (monomial,coefficients) pairs.
+        """
+        v = left._monomial_coefficients.items()
+        v.sort()
+        w = right._monomial_coefficients.items()
+        w.sort()
+        return cmp(v, w)
+
+    def _add_(self, y):
+        A = self.parent()
+        BR = A.base_ring()
+        z_elt = dict(self._monomial_coefficients)
+        for m, c in y._monomial_coefficients.iteritems():
+            if z_elt.has_key(m):
+                cm = z_elt[m] + c
+                if cm == 0:
+                    del z_elt[m]
+                else:
+                    z_elt[m] = cm
+            else:
+                z_elt[m] = c
+
+
+        #Remove all entries that are equal to 0
+        del_list = []
+        zero = BR(0)
+        for m, c in z_elt.iteritems():
+            if c == zero:
+                del_list.append(m)
+        for m in del_list:
+            del z_elt[m]
+            
+        z = A(Integer(0))
+        z._monomial_coefficients = z_elt
+        return z
+
+    def _neg_(self):
+        y = self.parent()(0)
+        y_elt = {}
+        for m, c in self._monomial_coefficients.iteritems():
+            y_elt[m] = -c
+        y._monomial_coefficients = y_elt
+        return y
+
+    def _sub_(self, y):
+        A = self.parent()
+        BR = A.base_ring()
+        z_elt = dict(self._monomial_coefficients)
+        for m, c in y._monomial_coefficients.iteritems():
+            if z_elt.has_key(m):
+                cm = z_elt[m] - c
+                if cm == 0:
+                    del z_elt[m]
+                else:
+                    z_elt[m] = cm
+            else:
+                z_elt[m] = -c
+
+        #Remove all entries that are equal to 0
+        zero = BR(0)
+        del_list = []
+        for m, c in z_elt.iteritems():
+            if c == zero:
+                del_list.append(m)
+        for m in del_list:
+            del z_elt[m]
+                
+        z = A(Integer(0))
+        z._monomial_coefficients = z_elt
+        return z
+                        
+    def _mul_(self, y):
+        return self.parent().multiply(self, y)
+
+    def __pow__(self, n):
+        """
+
+        """
+        if not isinstance(n, (int, Integer)):
+            raise TypeError, "n must be an integer"
+        A = self.parent()
+        z = A(Integer(1))
+        for i in range(n):
+            z *= self
+        return z
+
+    def _coefficient_fast(self, m, default):
+        return self._monomial_coefficients.get(m, default)
+
+    def coefficient(self, m):
+        """
+
+        """
+        p = self.parent()
+        if m in p._combinatorial_class:
+            return self._monomial_coefficients.get(p._combinatorial_class.object_class(m), p.base_ring()(0))
+        else:
+            raise TypeError, "you must specify an element of %s"%p._combinatorial_class
+
+    def is_zero(self):
+        BR = self.parent().base_ring()
+        for v in self._monomial_coefficients.values():
+            if v != BR(0):
+                return False
+        return True
+
+    def __len__(self):
+        return self.length()
+    
+    def length(self):
+        """
+        EXAMPLES:
+        """
+        return len( filter(lambda x: self._monomial_coefficients[x] != 0, self._monomial_coefficients) )
+
+    def support(self):
+        """
+        EXAMPLES:
+        """
+        v = self._monomial_coefficients.items()
+        mons = [ m for (m, _) in v ]
+        cffs = [ x for (_, x) in v ]
+        return [mons, cffs]
+    
+class CombinatorialAlgebra(Algebra):
+    """
+    """
+    def __init__(self, R, element_class=None):
+        """
+        INPUT:
+            R -- ring
+        """
+        #Make sure R is a ring with unit element
+        if not isinstance(R, Ring):
+            raise TypeError, "Argument R must be a ring."
+        try:
+            z = R(Integer(1))
+        except:
+            raise ValueError, "R must have a unit element"
+
+        #Check to make sure that the user defines the necessary
+        #attributes / methods to make the combinatorial algebra
+        #work
+        required = ['_combinatorial_class','_one',]
+        for r in required:
+            if not hasattr(self, r):
+                raise ValueError, "%s is required"%r
+        if not hasattr(self, '_multiply') and not hasattr(self, '_multiply_basis'):
+            raise ValueError, "either _multiply or _multiply_basis is required"
+
+        #Create a class for the elements of this combinatorial algebra
+        #We need to do this so to distinguish between element of different
+        #combinatorial algebras
+        if element_class is None:
+            if not hasattr(self, '_element_class'):
+                class CAElement(CombinatorialAlgebraElement):
+                    pass
+                self._element_class = CAElement
+        else:
+            self._element_class = element_class
+
+        #Initialize the base structure
+        sage.structure.parent_base.ParentWithBase.__init__(self, R)
+
+    _prefix = ""
+    _name   = "CombinatorialAlgebra -- change me"
+
+    def basis(self):
+        """
+        Returns a list of the basis elements of self.
+        """
+        return map(self, self._combinatorial_class.list())
+    
+    def __call__(self, x):
+        """
+        Coerce x into self.
+        """
+        R = self.base_ring()
+        eclass = self._element_class
+
+        #Coerce ints to Integers
+        if isinstance(x, int):
+            x = Integer(x)
+
+
+        if hasattr(self, '_coerce_start'):
+            try:
+                return self._coerce_start(x)
+            except:
+                pass
+
+        #x is an element of the same type of combinatorial algebra
+        if hasattr(x, 'parent') and x.parent().__class__ is self.__class__:
+            P = x.parent()
+            #same base ring
+            if P is self:
+                return x
+            #different base ring -- coerce the coefficients from into R
+            else:
+                return eclass(self, dict([ (e1,R(e2)) for e1,e2 in x._monomial_coefficients.items()]))
+        #x is an element of the basis combinatorial class
+        elif x in self._combinatorial_class:
+            return eclass(self, {self._combinatorial_class.object_class(x):R(1)})
+        #Coerce elements of the base ring
+        elif x.parent() is R:
+            if x == R(0):
+                return eclass(self, {})
+            else:
+                return eclass(self, {self._combinatorial_class.object_class(self._one):x})
+        #Coerce things that coerce into the base ring
+        elif R.has_coerce_map_from(x.parent()):
+            rx = R(x)
+            if rx == R(0):
+                return eclass(self, {})
+            else:
+                return eclass(self, {self._combinatorial_class.object_class(self._one):R(x)})
+        else:
+            if hasattr(self, '_coerce_end'):
+                try:
+                    return self._coerce_start(x)
+                except:
+                    pass
+            raise TypeError, "do not know how to make x (= %s) an element of self"%(x)
+
+
+    def _an_element_impl(self):
+        return self._element_class(self, {self._combinatorial_class.object_class(self._one):self.base_ring()(1)})
+
+    def _repr_(self):
+        return self._name + " over %s"%self.base_ring()
+
+    def combintorial_class(self):
+        return self._combinatorial_class
+
+    def _coerce_impl(self, x):
+        try:
+            R = x.parent()
+            if R.__class__ is self.__class__:
+                #Only perform the coercion if we can go from the base
+                #ring of x to the base ring of self
+                if self.base_ring().has_coerce_map_from( R.base_ring() ):
+                    return self(x)
+        except AttributeError:
+            pass
+        
+        # any ring that coerces to the base ring
+        return self._coerce_try(x, [self.base_ring()])
+                                
+    def prefix(self):
+        return self._prefix
+
+    def multiply(self,left,right):
+        A = left.parent()
+        BR = A.base_ring()
+        z_elt = {}
+
+        #Do the case where the user specifies how to multiply basis
+        #elements
+        if hasattr(self, '_multiply_basis'):
+            for (left_m, left_c) in left._monomial_coefficients.iteritems():
+                for (right_m, right_c) in right._monomial_coefficients.iteritems():
+                    res = self._multiply_basis(left_m, right_m)
+                    #Handle the case where the user returns a dictionary
+                    #where the keys are the monomials and the values are
+                    #the coefficients
+                    if isinstance(res, dict):
+                        for m in res:
+                            if m in z_elt:
+                                z_elt[ m ] = z_elt[m] + left_c * right_c * res[m]
+                            else:
+                                z_elt[ m ] = left_c * right_c * res[m]
+                    #Otherwise, res is assumed to be an element of the
+                    #object class
+                    else:
+                        m = res
+                        if m  in z_elt:
+                            z_elt[ m ] = z_elt[m] + left_c * right_c
+                        else:
+                            z_elt[ m ] = left_c * right_c
+        #We assume that the user handles the multiplication correctly on
+        #his or her own, and returns a dict with monomials as keys and
+        #coefficients as values
+        else:
+            z_elt = self._multiply(left, right)
+
+        #Remove all entries that are equal to 0
+        BR = self.base_ring()
+        zero = BR(0)
+        del_list = []
+        for m, c in z_elt.iteritems():
+            if c == zero:
+                del_list.append(m)
+        for m in del_list:
+            del z_elt[m]
+
+        z = A(Integer(0))
+        z._monomial_coefficients = z_elt
+        return z
+
+
+#class TestCA(CombinatorialAlgebra):
+#    _combinatorial_class = partition.Partitions()
+#    _name = "Test Combinatorial Algebra"
+#    _one = partition.Partition([])
+#    def _multiply_basis(self, left_basis, right_basis):
+#        #Append the two lists
+#        m = list(left_basis) + list(right_basis)
+#        #Sort the new lists
+#        m.sort(reverse=True)
+#        return partition.Partition(m)
Index: sage/combinat/composition.py
===================================================================
--- sage/combinat/composition.py	(revision 6594)
+++ sage/combinat/composition.py	(revision 6594)
@@ -0,0 +1,624 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+import sage.combinat.skew_partition
+from combinat import CombinatorialClass, CombinatorialObject
+import __builtin__
+from sage.rings.integer import Integer
+from sage.rings.arith import binomial
+import misc
+
+def Composition(co=None, descents=None, code=None):
+    """
+    Returns a composition object.
+    
+    EXAMPLES:
+      The standard way to create a composition is by specifying it
+      as a list.
+        
+        sage: Composition([3,1,2])
+        [3, 1, 2]
+
+      You can create a composition from a list of its descents.
+        
+        sage: Composition([1, 1, 3, 4, 3]).descents()
+        [0, 1, 4, 8, 11]
+        sage: Composition(descents=[1,0,4,8,11])
+        [1, 1, 3, 4, 3]
+
+      You can also create a composition from its code.
+
+        sage: Composition([4,1,2,3,5]).to_code()
+        [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
+        sage: Composition(code=_)          
+        [4, 1, 2, 3, 5]
+        sage: Composition([3,1,2,3,5]).to_code()
+        [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
+        sage: Composition(code=_)
+        [3, 1, 2, 3, 5]
+    """
+
+    if descents is not None:
+        if isinstance(descents, tuple):
+            return from_descents(descents[0], nps=descents[1])
+        else:
+            return from_descents(descents)
+    elif code is not None:
+        return from_code(code)
+    else:
+        if co not in Compositions():
+            raise ValueError, "invalid composition"
+        else:
+            return Composition_class(co)
+
+class Composition_class(CombinatorialObject):
+    def conjugate(self):
+        r"""
+        Returns the conjugate of the composition comp.
+
+        Algorithm from mupad-combinat.
+
+        EXAMPLES:
+            sage: Composition([1, 1, 3, 1, 2, 1, 3]).conjugate()  
+            [1, 1, 3, 3, 1, 3]
+
+        """
+        comp = self
+        if comp == []:
+            return Composition([])
+        n = len(comp)
+        coofcp = [sum(comp[:j])-j+1 for j in range(1,n+1)]
+
+        cocjg = []
+        for i in range(n-1):
+            cocjg += [i+1 for k in range(0, (coofcp[n-i-1]-coofcp[n-i-2]))]
+        cocjg += [n for j in range(coofcp[0])]
+
+        return Composition([cocjg[0]] + [cocjg[i]-cocjg[i-1]+1 for i in range(1,len(cocjg)) ])
+
+
+    def complement(self):
+        """
+        Returns the complement of the composition co.  The complement
+        is the reverse of co's conjugate composition.
+
+        EXAMPLES:
+            sage: Composition([1, 1, 3, 1, 2, 1, 3]).conjugate()
+            [1, 1, 3, 3, 1, 3]
+            sage: Composition([1, 1, 3, 1, 2, 1, 3]).complement()
+            [3, 1, 3, 3, 1, 1]
+
+        """
+        return Composition([element for element in reversed(self.conjugate())])
+
+    def is_finer(self, co2):
+        """
+        Returns True if the composition self is finer than the composition
+        co2; otherwise, it returns False.
+     
+        EXAMPLES:
+            sage: Composition([4,1,2]).is_finer([3,1,3])
+            False
+            sage: Composition([3,1,3]).is_finer([4,1,2])
+            False
+            sage: Composition([1,2,2,1,1,2]).is_finer([5,1,3])
+            True
+            sage: Composition([2,2,2]).is_finer([4,2])
+            True
+        """
+        co1 = self
+        if sum(co1) != sum(co2):
+            #Error: compositions are not of the same size
+            raise ValueError, "compositions self (= %s) and co2 (= %s) must be of the same size"%(self, co2)
+
+
+        sum1 = 0
+        sum2 = 0
+        i1 = 0
+        for i2 in range(len(co2)):
+            sum2 += co2[i2]
+            while sum1 < sum2:
+                sum1 += co1[i1]
+                i1 += 1
+            if sum1 > sum2:
+                return False
+
+        return True
+
+    def refinement(self, co2):
+        """
+        Returns the refinement composition of self and co2.
+
+        EXAMPLES:
+            sage: Composition([1,2,2,1,1,2]).refinement([5,1,3])
+            [3, 1, 2]
+        """
+        co1 = self
+        if sum(co1) != sum(co2):
+            #Error: compositions are not of the same size
+            raise ValueError, "compositions self (= %s) and co2 (= %s) must be of the same size"%(self, co2)
+
+        sum1 = 0
+        sum2 = 0
+        i1 = -1
+        result = []
+        for i2 in range(len(co2)):
+            sum2 += co2[i2]
+            i_res = 0
+            while sum1 < sum2:
+                i1 += 1
+                sum1 += co1[i1]
+                i_res += 1
+
+            if sum1 > sum2:
+                return None
+
+            result.append(i_res)
+
+        return Composition(result)
+
+    def major_index(self):
+        """
+        Returns the major index of the composition co.  The major index is defined
+        as the sum of the descents.
+   
+        EXAMPLES:
+            sage: Composition([1, 1, 3, 1, 2, 1, 3]).major_index()
+            31
+        """
+        co = self
+        lv = len(co)
+        if lv == 1:
+            return 0
+        else:
+            return sum([(lv-(i+1))*co[i] for i in range(lv)])
+
+   
+    def to_code(self):
+        """
+        Returns the code of the composition self.
+
+        EXAMPLES:
+            sage: Composition([4,1,2,3,5]).to_code()
+            [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
+        """
+
+        if self == []:
+            return [0]
+
+        code = []
+        for i in range(len(self)):
+            code += [1] + [0]*(self[i]-1)
+
+        return code 
+
+
+    def descents(self, final_descent=False):
+        """
+        Returns the list of descents of the composition co.
+
+        EXAMPLES:
+            sage: Composition([1, 1, 3, 1, 2, 1, 3]).descents()
+            [0, 1, 4, 5, 7, 8, 11]
+        """
+        s = -1
+        d = []
+        for i in range(len(self)):
+            s += self[i]
+            d += [s]
+        if len(self) != 0 and final_descent:
+            d += [len(self)-1]
+        return d
+
+
+    def peaks(self):
+        """
+        Returns a list of the peaks of the composition self.
+
+        The peaks are the positions i in the compositions such that
+        self[i-1] < self[i] > self[i+1].  Note that len(self)-1 is
+        never a peak.
+
+        EXAMPLES:
+            sage: Composition([1, 1, 3, 1, 2, 1, 3]).peaks()
+            [2, 4]
+
+        """
+        n = sum(self)
+        p = []
+        for i in range(1,len(self)-1):
+            if self[i-1] < self[i] and self[i] > self[i+1]:
+                p += [i]
+
+        return p
+
+    def to_skew_partition(self, overlap=1):
+        """
+        Returns the skew partition obtained from the composition co.
+        The parameter overlap indicates the number of boxes that are
+        covered by boxes of the previous line.
+
+        EXAMPLES:
+            sage: Composition([3,4,1]).to_skew_partition()
+            [[6, 6, 3], [5, 2]]
+            sage: Composition([3,4,1]).to_skew_partition(overlap=0)
+            [[8, 7, 3], [7, 3]]
+
+        """
+        co = self
+        outer = []
+        inner = []
+        sum_outer = -1*overlap
+
+        for k in range(len(self)-1):
+            outer += [ self[k]+sum_outer+overlap  ]
+            sum_outer += self[k]-overlap
+            inner += [ sum_outer + overlap ]
+
+        if self != []:
+            outer += [self[-1]+sum_outer+overlap]
+        else:
+            return [[],[]]
+
+        return sage.combinat.skew_partition.SkewPartition(
+            [ filter(lambda x: x != 0, [l for l in reversed(outer)]),
+              filter(lambda x: x != 0, [l for l in reversed(inner)])])
+    
+
+
+##############################################################
+
+
+def Compositions(n=None, **kwargs):
+    """
+    Returns the combinatorial class of compositions.
+
+    EXAMPLES:
+      If n is not specificied, it returns the combinatorial
+      class of all (non-negative) integer compositions.
+
+        sage: Compositions()
+        Compositions of non-negative integers
+        sage: [] in Compositions()
+        True
+        sage: [2,3,1] in Compositions()
+        True
+        sage: [-2,3,1] in Compositions()
+        False
+
+      If n is specified, it returns the class of compositions
+      of n.
+
+        sage: Compositions(3)
+        Compositions of 3
+        sage: Compositions(3).list()
+        [[1, 1, 1], [1, 2], [2, 1], [3]]
+        sage: Compositions(3).count()
+        4
+
+      In addition, the following constaints can be put on the
+      compositions: length, min_part, max_part, min_length,
+      max_length, min_slope, max_slope, inner, and outer.
+      For example,
+
+        sage: Compositions(3, length=2).list()
+        [[1, 2], [2, 1]]
+        sage: Compositions(4, max_slope=0).list()
+        [[1, 1, 1, 1], [2, 1, 1], [2, 2], [3, 1], [4]]
+    """
+    if n is None:
+        return Compositions_all()
+    else:
+        if kwargs:
+            return Compositions_constraints(n, **kwargs)
+        else:
+            return Compositions_n(n)
+
+class Compositions_all(CombinatorialClass):
+    def __init__(self):
+        """
+        TESTS:
+            sage: C = Compositions()
+            sage: C == loads(dumps(C))
+            True
+        """
+        pass
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Compositions())
+            'Compositions of non-negative integers'
+        """
+        return "Compositions of non-negative integers"
+
+    object_class = Composition_class
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: [2,1,3] in Compositions()
+            True
+            sage: [] in Compositions()
+            True
+            sage: [-2,-1] in Compositions()
+            False
+            sage: [0,0] in Compositions()
+            True
+        """
+        if isinstance(x, Composition_class):
+            return True
+        elif isinstance(x, __builtin__.list):
+            for i in range(len(x)):
+                if not isinstance(x[i], (int, Integer)):
+                    return False
+                if x[i] < 0:
+                    return False
+            return True
+        else:
+            return False
+
+    def list(self):
+        """
+        TESTS:
+            sage: Compositions().list()
+            Traceback (most recent call last):
+            ...
+            NotImplementedError
+        """
+        raise NotImplementedError
+
+class Compositions_n(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: C = Compositions(3)
+            sage: C == loads(dumps(C))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Compositions(3))
+            'Compositions of 3'
+        """
+        return "Compositions of %s"%self.n
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: [2,1,3] in Compositions(6)
+            True
+            sage: [2,1,2] in Compositions(6)
+            False
+            sage: [] in Compositions(0)
+            True
+            sage: [0] in Compositions(0)
+            True
+        """
+        return x in Compositions() and sum(x) == self.n
+
+    def count(self):
+        """
+        TESTS:
+            sage: Compositions(3).count()
+            4
+            sage: Compositions(0).count()
+            1
+        """
+        if self.n >= 1:
+            return 2**(self.n-1)
+        elif self.n == 0:
+            return 1
+        else:
+            return 0
+
+    def list(self):
+        """
+        TESTS:
+            sage: Compositions(4).list()
+            [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
+            sage: Compositions(0).list()
+            [[]]
+        """
+        if self.n == 0:
+            return [Composition_class([])]
+        
+        result = []
+        for i in range(1,self.n+1):
+            result += map(lambda x: [i]+x[:], Compositions_n(self.n-i).list())
+
+        return [Composition_class(r) for r in result]
+
+
+class Compositions_constraints(CombinatorialClass):
+    object_class = Composition_class
+
+    def __init__(self, n, **kwargs):
+        """
+            sage: C = Compositions(4, length=2)
+            sage: C == loads(dumps(C))
+            True
+        """
+        self.n = n
+        self.constraints = kwargs
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Compositions(6, min_part=2, length=3))
+            'Compositions of 6 with constraints length=3, min_part=2'
+        """
+        return "Compositions of %s with constraints %s"%(self.n, ", ".join( ["%s=%s"%(key, self.constraints[key]) for key in sorted(self.constraints.keys())] ))
+    
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: [2, 1] in Compositions(3, length=2)
+            True
+            sage: [2,1,2] in Compositions(5, min_part=1)
+            True
+            sage: [2,1,2] in Compositions(5, min_part=2)
+            False
+        """
+        return x in Compositions() and sum(x) == self.n and misc.check_integer_list_constraints(x, singleton=True, **self.constraints)
+    
+
+    def count(self):
+        """
+         EXAMPLES:
+            sage: Compositions(4, length=2).count()
+            3
+            sage: Compositions(4, min_length=2).count()
+            7
+            sage: Compositions(4, max_length=2).count()
+            4
+            sage: Compositions(4, max_part=2).count()
+            5
+            sage: Compositions(4, min_part=2).count()
+            2
+            sage: Compositions(4, outer=[3,1,2]).count()
+            3       
+        """
+        if len(self.constraints) == 1 and 'length' in self.constraints:
+            if self.n >= 1:
+                return binomial(self.n-1, self.constraints['length'] - 1)
+            elif self.n == 0:
+                if self.constraints['length'] == 0:
+                    return 1
+                else:
+                    return 0
+            else:
+                return 0
+        return len(self.list())
+
+
+
+    def list(self):
+        """
+        Returns a list of all the compositions of n.
+
+        EXAMPLES:
+            sage: Compositions(4, length=2).list()
+            [[1, 3], [2, 2], [3, 1]]
+            sage: Compositions(4, min_length=2).list()
+            [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1]]
+            sage: Compositions(4, max_length=2).list()
+            [[1, 3], [2, 2], [3, 1], [4]]
+            sage: Compositions(4, max_part=2).list()
+            [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2]]
+            sage: Compositions(4, min_part=2).list()
+            [[2, 2], [4]]
+            sage: Compositions(4, outer=[3,1,2]).list()
+            [[1, 1, 2], [2, 1, 1], [3, 1]]
+            sage: Compositions(4, outer=[1,'inf',1]).list()
+            [[1, 2, 1], [1, 3]]
+            sage: Compositions(4, inner=[1,1,1]).list()
+            [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1]]
+            sage: Compositions(4, min_slope=0).list()
+            [[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2], [4]]
+            sage: Compositions(4, min_slope=-1, max_slope=1).list()
+            [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2], [4]]
+            sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list()
+            [[1, 1, 1, 2],
+             [1, 1, 2, 1],
+             [1, 2, 1, 1],
+             [1, 2, 2],
+             [2, 1, 1, 1],
+             [2, 1, 2],
+             [2, 2, 1],
+             [2, 3],
+             [3, 1, 1],
+             [3, 2]]
+            sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list()
+            [[1, 2, 2], [2, 1, 2], [2, 2, 1], [2, 3]]
+
+        """
+        n = self.n
+
+        if n == 0:
+            return [Composition_class([])]
+
+        result = []
+        for i in range(1,n+1):
+            result += map(lambda x: [i]+x[:], Compositions_constraints(n-i).list())
+
+        if self.constraints:
+            result = misc.check_integer_list_constraints(result, **self.constraints)
+
+        result = [Composition_class(r) for r in result]
+
+        return result
+
+
+
+
+def from_descents(descents, nps=None):
+    """
+    Returns a composition from the list of descents.
+
+    EXAMPLES:
+        sage: Composition([1, 1, 3, 4, 3]).descents()
+        [0, 1, 4, 8, 11]
+        sage: sage.combinat.composition.from_descents([1,0,4,8],12)
+        [1, 1, 3, 4, 3]
+        sage: sage.combinat.composition.from_descents([1,0,4,8,11])
+        [1, 1, 3, 4, 3]
+    """
+
+    d = [x+1 for x in descents]
+    d.sort()
+
+    if d == []:
+        if nps == 0:
+            return []
+        else:
+            return [nps]
+
+    if nps is not None:
+        if nps < max(d):
+            #Error: d is not included in [1,...,nps-1]
+            return None
+        elif nps > max(d):
+            d.append(nps)
+
+    co = [d[0]]
+    for i in range(len(d)-1):
+        co += [ d[i+1]-d[i] ]
+
+    return Composition(co)
+
+def from_code(code):
+    """
+    Return the composition from its code.
+
+    EXAMPLES:
+    sage: Composition([4,1,2,3,5]).to_code()
+    [1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
+    sage: composition.from_code(_)          
+    [4, 1, 2, 3, 5]
+    sage: Composition([3,1,2,3,5]).to_code()
+    [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
+    sage: composition.from_code(_)          
+    [3, 1, 2, 3, 5]
+
+    """
+    if code == [0]:
+        return []
+
+    L = filter(lambda x: code[x]==1, range(len(code))) #the positions of the letter 1
+    return Composition([L[i]-L[i-1] for i in range(1, len(L))] + [len(code)-L[-1]])
+
Index: sage/combinat/composition_signed.py
===================================================================
--- sage/combinat/composition_signed.py	(revision 6439)
+++ sage/combinat/composition_signed.py	(revision 6439)
@@ -0,0 +1,134 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from combinat import CombinatorialObject, CombinatorialClass
+import composition
+import cartesian_product
+import itertools
+from sage.rings.all import binomial, Integer
+import __builtin__
+
+def SignedCompositions(n):
+    """
+    Returns the combinatorial class of signed compositions of
+    n.
+
+    EXAMPLES:
+        sage: SC3 = SignedCompositions(3); SC3
+        Signed compositions of 3
+        sage: SC3.count()
+        18
+        sage: len(SC3.list())
+        18
+        sage: SC3.first()
+        [1, 1, 1]
+        sage: SC3.last()
+        [-3]
+        sage: SC3.random() #random
+        [-1, -2]
+        sage: SC3.list()
+        [[1, 1, 1],
+         [1, 1, -1],
+         [1, -1, 1],
+         [1, -1, -1],
+         [-1, 1, 1],
+         [-1, 1, -1],
+         [-1, -1, 1],
+         [-1, -1, -1],
+         [1, 2],
+         [1, -2],
+         [-1, 2],
+         [-1, -2],
+         [2, 1],
+         [2, -1],
+         [-2, 1],
+         [-2, -1],
+         [3],
+         [-3]]
+    """
+    return SignedCompositions_n(n)
+
+class SignedCompositions_n(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: SC3 = SignedCompositions(3)
+            sage: SC3 == loads(dumps(SC3))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SignedCompositions(3))
+            'Signed compositions of 3'
+        """
+        return "Signed compositions of %s"%self.n
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: [] in SignedCompositions(0)
+            True
+            sage: [0] in SignedCompositions(0)
+            False
+            sage: [2,1,3] in SignedCompositions(6)
+            True
+            sage: [-2, 1, -3] in SignedCompositions(6)
+            True
+        """
+        if x == []:
+            return True
+        
+        if isinstance(x, __builtin__.list):
+            for i in range(len(x)):
+                if not isinstance(x[i], (int, Integer)):
+                    return False
+                if x[i] == 0:
+                    return False
+                return True
+        else:
+            return False
+
+        return sum([abs(i) for i in x]) == self.n
+        
+    def count(self):
+        """
+        TESTS:
+            sage: SC4 = SignedCompositions(4)
+            sage: SC4.count() == len(SC4.list())
+            True
+            sage: SignedCompositions(3).count()
+            18
+        """
+        return sum([ binomial(self.n-1, i-1)*2**(i) for i in range(1, self.n+1)])
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: SignedCompositions(0).list()   #indirect test
+            [[]]
+            sage: SignedCompositions(1).list()   #indirect test
+            [[1], [-1]]
+            sage: SignedCompositions(2).list()   #indirect test
+            [[1, 1], [1, -1], [-1, 1], [-1, -1], [2], [-2]]
+        """
+        for comp in composition.Compositions(self.n):
+            l = len(comp)
+            a = [[1,-1] for i in range(l)]
+            for sign in cartesian_product.CartesianProduct(*a):
+                yield [ sign[i]*comp[i] for i in range(l)]
+
Index: sage/combinat/dyck_word.py
===================================================================
--- sage/combinat/dyck_word.py	(revision 6594)
+++ sage/combinat/dyck_word.py	(revision 6594)
@@ -0,0 +1,715 @@
+import sage.combinat.misc as misc
+from combinat import catalan_number
+import __builtin__
+from sage.sets.set import Set
+from combinat import CombinatorialClass, CombinatorialObject
+import tableau
+
+open_symbol = 1
+close_symbol = 0
+
+    
+def DyckWord(dw=None, noncrossing_partition=None):
+    """
+    Returns a Dyck word object
+
+    EXAMPLES:
+        sage: dw = DyckWord([1, 0, 1, 0]); dw
+        [1, 0, 1, 0]
+        sage: print dw
+        ()()
+        sage: print dw.height()
+        1
+        sage: dw.to_noncrossing_partition()
+        [[1], [2]]
+
+        sage: DyckWord('()()')
+        [1, 0, 1, 0]
+
+        sage: DyckWord(noncrossing_partition=[[1],[2]])
+        [1, 0, 1, 0]
+    """
+    global open_symbol, close_symbol
+    
+    if noncrossing_partition is not None:
+        return from_noncrossing_partition(noncrossing_partition)
+    
+    elif isinstance(dw, str):
+        def replace(x):
+            if x == '(':
+                return open_symbol
+            elif x == ')':
+                return close_symbol
+            else:
+                raise ValueError, "we should only have open and close symbols, not %s"%x
+        l = map(replace, dw)
+    else:
+        l = dw
+        
+    if l in DyckWords() or is_a_prefix(l): 
+        return DyckWord_class(l)
+    else:
+        raise ValueError, "invalid Dyck word"
+
+class DyckWord_class(CombinatorialObject):
+    def __str__(self):
+        """
+        Returns a string consisting of matched parenteses corresponding to
+        the Dyck word.
+        
+        EXAMPLES:
+            sage: print DyckWord([1, 0, 1, 0])
+            ()()
+            sage: print DyckWord([1, 1, 0, 0])
+            (())
+        """
+        global open_symbol, close_symbol
+        def replace(x):
+            if x == open_symbol:
+                return '('
+            elif x == close_symbol:
+                return ')'
+            else:
+                raise ValueError, "we should only have open and close symbols, not %s"%x
+
+        return "".join(map(replace, [x for x in self]))
+
+
+    def size(self):
+        """
+        Returns the size of the Dyck word, which is the number
+        of opening parentheses in the Dyck word.
+
+        EXAMPLES:
+            sage: DyckWord([1, 0, 1, 0]).size()
+            2
+            sage: DyckWord([1, 0, 1, 1, 0]).size()
+            3
+        """
+        global open_symbol
+        return len(filter(lambda x: x == open_symbol, self))
+
+    def height(self):
+        """
+        Returns the height of the Dyck word.
+        
+        EXAMPLES:
+            sage: DyckWord([]).height()
+            0
+            sage: DyckWord([1,0]).height()
+            1
+            sage: DyckWord([1, 1, 0, 0]).height()
+            2
+            sage: DyckWord([1, 1, 0, 1, 0]).height()
+            2
+            sage: DyckWord([1, 1, 0, 0, 1, 0]).height()
+            2
+            sage: DyckWord([1, 0, 1, 0]).height()
+            1
+            sage: DyckWord([1, 1, 0, 0, 1, 1, 1, 0, 0, 0]).height()
+            3
+        """
+        global open_symbol, close_symbol
+        
+        height = 0
+        height_max = 0
+        for letter in self:
+            if letter == open_symbol:
+                height += 1
+                height_max = max(height, height_max)
+            elif letter == close_symbol:
+                height -= 1
+        return height_max
+
+    def associated_parenthesis(self, pos):
+        """
+        EXAMPLES:
+            sage: DyckWord([1, 0]).associated_parenthesis(0)
+            1
+            sage: DyckWord([1, 0, 1, 0]).associated_parenthesis(0)
+            1
+            sage: DyckWord([1, 0, 1, 0]).associated_parenthesis(1)
+            0
+            sage: DyckWord([1, 0, 1, 0]).associated_parenthesis(2)
+            3
+            sage: DyckWord([1, 0, 1, 0]).associated_parenthesis(3)
+            2
+            sage: DyckWord([1, 1, 0]).associated_parenthesis(1)
+            2
+            sage: DyckWord([1, 1]).associated_parenthesis(0)
+        """
+        global open_symbol, close_symbol
+        d = 0
+        height = 0
+        if pos >= len(self):
+            raise ValueError, "invalid index"
+        
+        if self[pos] == open_symbol:
+            d += 1
+            height += 1
+        elif self[pos] == close_symbol:
+            d -= 1
+            height -= 1
+        else:
+            raise ValueError, "unknown symbol %s"%self[pos-1]
+
+        while height != 0:
+            pos += d
+            if pos < 0 or pos >= len(self):
+                return None
+            if self[pos] == open_symbol:
+                height += 1
+            elif self[pos] == close_symbol:
+                height -= 1
+
+        return pos
+            
+    def to_noncrossing_partition(self):
+        """
+        Bijection of Biane from Dyck words to non crossing partitions
+        Thanks to Mathieu Dutour for describing the bijection.
+
+        EXAMPLES:
+            sage: DyckWord([1, 0]).to_noncrossing_partition()
+            [[1]]
+            sage: DyckWord([1, 1, 0, 0]).to_noncrossing_partition()
+            [[1, 2]]
+            sage: DyckWord([1, 1, 1, 0, 0, 0]).to_noncrossing_partition()
+            [[1, 2, 3]]
+            sage: DyckWord([1, 0, 1, 0, 1, 0]).to_noncrossing_partition()
+            [[1], [2], [3]]
+            sage: DyckWord([1, 1, 0, 1, 0, 0]).to_noncrossing_partition()
+            [[2], [1, 3]]
+        """
+        global open_symbol, close_symbol
+        
+        partition = [] 
+        stack = []
+        i = 0
+        p = 1
+
+        #Invariants:
+        # - self[i] = 0
+        # - p is the number of opening parens at position i
+
+        while i < len(self):
+            stack.append(p)
+            j = i + 1
+            while j < len(self) and self[j] == close_symbol:
+                j += 1
+
+            #Now j points to the next 1 or past the end of self
+            nz = j - (i+1) # the number of )'s between i and j
+            if nz > 0:
+                # Remove the nz last elements of stack and
+                # make a new part in partition
+                if nz > len(stack):
+                    raise ValueError, "incorrect dyck word"
+
+                partition.append( stack[-nz:] )
+
+                stack = stack[: -nz]
+            i = j
+            p += 1
+            
+        if len(stack) > 0:
+            raise ValueError, "incorrect dyck word"
+
+        return partition
+
+    def to_ordered_tree(self):
+        """
+        TESTS:
+            sage: DyckWord([1, 1, 0, 0]).to_triangulation()
+            Traceback (most recent call last):
+            ...
+            NotImplementedError: TODO
+        """
+        raise NotImplementedError, "TODO"
+
+    def to_triangulation(self):
+        """
+        TESTS:
+            sage: DyckWord([1, 1, 0, 0]).to_triangulation()
+            Traceback (most recent call last):
+            ...
+            NotImplementedError: TODO
+        """
+        raise NotImplementedError, "TODO"
+
+    def peaks(self):
+        """
+        EXAMPLES:
+            sage: DyckWord([1, 0, 1, 0]).peaks()
+            [0, 2]
+            sage: DyckWord([1, 1, 0, 0]).peaks()
+            [1]
+        """
+        global open_symbol, close_symbol
+        return filter(lambda i: self[i] == open_symbol and self[i+1] == close_symbol, range(len(self)-1))
+
+    def to_tableau(self):
+        """
+        EXAMPLES:
+            sage: DyckWord([]).to_tableau()
+            []
+            sage: DyckWord([1, 0]).to_tableau()
+            [[2], [1]]
+            sage: DyckWord([1, 1, 0, 0]).to_tableau()
+            [[3, 4], [1, 2]]
+            sage: DyckWord([1, 0, 1, 0]).to_tableau()
+            [[2, 4], [1, 3]]
+            sage: DyckWord([1]).to_tableau()
+            [[1]]
+            sage: DyckWord([1, 0, 1]).to_tableau()
+            [[2], [1, 3]]
+        """
+        global open_symbol, close_symbol
+        open_positions = []
+        close_positions = []
+
+        for i in range(len(self)):
+            if self[i] == open_symbol:
+                open_positions.append(i+1)
+            else:
+                close_positions.append(i+1)
+        return filter(lambda x: x != [],  [ close_positions, open_positions ])
+
+    def a_statistic(self):
+        """
+        Returns the a-statistic for the Dyck word.  When viewed as a lattice
+        path, the Dyck word's a-statistic is the number of boxes
+        above the main diagonal.
+
+        EXAMPLES:
+            sage: dw = DyckWord([1,1,1,0,1,1,1,0,0,0,1,1,0,0,1,0,0,0])
+            sage: dw.a_statistic()
+            19
+
+            sage: DyckWord([1,1,1,1,0,0,0,0]).a_statistic()
+            6
+            sage: DyckWord([1,1,1,0,1,0,0,0]).a_statistic()
+            5
+            sage: DyckWord([1,1,1,0,0,1,0,0]).a_statistic()
+            4
+            sage: DyckWord([1,1,1,0,0,0,1,0]).a_statistic()
+            3
+            sage: DyckWord([1,0,1,1,0,1,0,0]).a_statistic()
+            2
+            sage: DyckWord([1,1,0,1,1,0,0,0]).a_statistic()
+            4
+            sage: DyckWord([1,1,0,0,1,1,0,0]).a_statistic()
+            2
+            sage: DyckWord([1,0,1,1,1,0,0,0]).a_statistic()
+            3
+            sage: DyckWord([1,0,1,1,0,0,1,0]).a_statistic()
+            1
+            sage: DyckWord([1,0,1,0,1,1,0,0]).a_statistic()
+            1
+            sage: DyckWord([1,1,0,0,1,0,1,0]).a_statistic()
+            1
+            sage: DyckWord([1,1,0,1,0,0,1,0]).a_statistic()
+            2
+            sage: DyckWord([1,1,0,1,0,1,0,0]).a_statistic()
+            3
+            sage: DyckWord([1,0,1,0,1,0,1,0]).a_statistic()
+            0
+        """
+        above = 0
+        diagonal = 0
+        a = 0
+        for move in self:
+            if move == 1:
+                above += 1
+            elif move == 0:
+                diagonal += 1
+                a += above - diagonal
+        return a
+
+    def b_statistic(self):
+        """
+        Returns the b-statistic for the Dyck word.
+
+        EXAMPLES:
+            sage: dw = DyckWord([1,1,1,0,1,1,1,0,0,0,1,1,0,0,1,0,0,0])
+            sage: dw.b_statistic()
+            7
+
+            sage: DyckWord([1,1,1,1,0,0,0,0]).b_statistic()
+            0
+            sage: DyckWord([1,1,1,0,1,0,0,0]).b_statistic()
+            1
+            sage: DyckWord([1,1,1,0,0,1,0,0]).b_statistic()
+            2
+            sage: DyckWord([1,1,1,0,0,0,1,0]).b_statistic()
+            3
+            sage: DyckWord([1,0,1,1,0,1,0,0]).b_statistic()
+            3
+            sage: DyckWord([1,1,0,1,1,0,0,0]).b_statistic()
+            1
+            sage: DyckWord([1,1,0,0,1,1,0,0]).b_statistic()
+            2
+            sage: DyckWord([1,0,1,1,1,0,0,0]).b_statistic()
+            1
+            sage: DyckWord([1,0,1,1,0,0,1,0]).b_statistic()
+            4
+            sage: DyckWord([1,0,1,0,1,1,0,0]).b_statistic()
+            3
+            sage: DyckWord([1,1,0,0,1,0,1,0]).b_statistic()
+            5
+            sage: DyckWord([1,1,0,1,0,0,1,0]).b_statistic()
+            4
+            sage: DyckWord([1,1,0,1,0,1,0,0]).b_statistic()
+            2
+            sage: DyckWord([1,0,1,0,1,0,1,0]).b_statistic()
+            6
+
+        """
+        x_pos = len(self)/2
+        y_pos = len(self)/2
+        
+        b = 0
+
+        mode = "left"
+        makeup_steps = 0
+        l = self.list[:]
+        l.reverse()
+        
+        for move in l:
+            #print x_pos, y_pos, mode, move
+            if mode == "left":
+                if move == 0:
+                    x_pos -= 1
+                elif move == 1:
+                    y_pos -= 1
+                    if x_pos == y_pos:
+                        b += x_pos
+                    else:
+                        mode = "drop"
+            elif mode == "drop":
+                if move == 0:
+                    makeup_steps += 1
+                elif move == 1:
+                    y_pos -= 1
+                    if x_pos == y_pos:
+                        b += x_pos
+                        mode = "left"
+                        x_pos -= makeup_steps
+                        makeup_steps = 0
+            
+        return b
+        
+
+def DyckWords(k1=None, k2=None):
+    """
+    Returns the combinatorial class of Dyck words.
+
+    EXAMPLES:
+      If neither k1 nor k2 are specified, then it returns
+      the combinatorial class of all Dyck words.
+      
+        sage: DW = DyckWords(); DW
+        Dyck words
+        sage: [] in DW
+        True
+        sage: [1, 0, 1, 0] in DW
+        True
+        sage: [1, 1, 0] in DW
+        False
+
+      If just k1 is specified, then it returns the combinatorial
+      class of Dyck words with k1 opening parentheses and k1
+      closing parentheses.
+        sage: DW2 = DyckWords(2); DW2
+        Dyck words with 2 opening parentheses and 2 closing parentheses
+        sage: DW2.first()
+        [1, 1, 0, 0]
+        sage: DW2.last()
+        [1, 0, 1, 0]
+        sage: DW2.count()
+        2
+
+      If k2 is specified in addition to k1, then it returns
+      the combinatorial class of Dyck words with k1 opening
+      parentheses and k2 closing parentheses.
+        sage: DW32 = DyckWords(3,2); DW32
+        Dyck words with 3 opening parentheses and 2 closing parentheses
+        sage: DW32.list()
+        [[1, 1, 1, 0, 0],
+         [1, 1, 0, 1, 0],
+         [1, 1, 0, 0, 1],
+         [1, 0, 1, 1, 0],
+         [1, 0, 1, 0, 1]]
+    """
+    if k1 is None and k2 is None:
+        return DyckWords_all()
+    else:
+        if k2 is not None and k1 < k2:
+            raise ValueError, "k1 (= %s) must be >= k2 (= %s)"%(k1, k2)
+        if k2 is None:
+            return DyckWords_size(k1, k1)
+        else:
+            return DyckWords_size(k1, k2)
+
+class DyckWords_all(CombinatorialClass):
+    def __init__(self):
+        """
+        TESTS:
+            sage: DW = DyckWords()
+            sage: DW == loads(dumps(DW))
+            True
+        """
+        pass
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(DyckWords())
+            'Dyck words'
+        """
+        return "Dyck words"
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: [] in DyckWords()
+            True
+            sage: [1] in DyckWords()
+            False
+            sage: [0] in DyckWords()
+            False 
+            sage: [1, 0] in DyckWords()
+            True
+        """
+        global open_symbol, close_symbol
+        if isinstance(x, DyckWord_class):
+            return True
+
+        if not isinstance(x, __builtin__.list):
+            return False
+
+        if len(x) % 2 != 0:
+            return False
+
+        return is_a(x)
+
+    def list(self):
+        """
+        TESTS:
+            sage: DyckWords().list()
+            Traceback (most recent call last):
+            ...
+            NotImplementedError
+        """
+        raise NotImplementedError
+
+class DyckWords_size(CombinatorialClass):
+    def __init__(self, k1, k2=None):
+        """
+        TESTS:
+            sage: DW4 = DyckWords(4)
+            sage: DW4 == loads(dumps(DW4))
+            True
+            sage: DW42 = DyckWords(4,2)
+            sage: DW42 == loads(dumps(DW42))
+            True
+            
+        """
+        self.k1 = k1
+        self.k2 = k2
+
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(DyckWords(4))
+            'Dyck words with 4 opening parentheses and 4 closing parentheses'
+        """
+        return "Dyck words with %s opening parentheses and %s closing parentheses"%(self.k1, self.k2)
+    
+    def count(self):
+        """
+        Returns the number of Dyck words of size n, i.e. the n-th Catalan number.
+        
+        EXAMPLES:
+            sage: DyckWords(4).count()
+            14
+            sage: ns = range(9)
+            sage: dws = [DyckWords(n) for n in ns]
+            sage: all([ dw.count() == len(dw.list()) for dw in dws])
+            True
+        """
+        if self.k2 == self.k1:
+            return catalan_number(self.k1)
+        else:
+            return len(self.list())
+
+    def __contains__(self, x):
+        """
+        EXAMPLES:
+             sage: [1, 0] in DyckWords(1)
+             True
+             sage: [1, 0] in DyckWords(2)
+             False
+             sage: [1, 1, 0, 0] in DyckWords(2)
+             True
+             sage: [1, 0, 0, 1] in DyckWords(2)
+             False
+             sage: [1, 0, 0, 1] in DyckWords(2,2)
+             False
+             sage: [1, 0, 1, 0] in DyckWords(2,2)
+             True
+             sage: [1, 0, 1, 0, 1] in DyckWords(3,2)
+             True
+             sage: [1, 0, 1, 1, 0] in DyckWords(3,2)
+             True
+             sage: [1, 0, 1, 1] in DyckWords(3,1)
+             True
+        """
+        return is_a(x, self.k1, self.k2)
+
+    def list(self):
+        """
+        Returns a list of all the Dyck words of size n.
+
+        EXAMPLES:
+            sage: DyckWords(0).list()
+            [[]]
+            sage: DyckWords(1).list()
+            [[1, 0]]
+            sage: DyckWords(2).list()
+            [[1, 1, 0, 0], [1, 0, 1, 0]]
+        """
+        global open_symbol, close_symbol
+        k1 = self.k1
+        k2 = self.k2
+
+        if k1 == 0:
+            return [ DyckWord_class([]) ]
+        if k2 == 0:
+            return [ DyckWord_class([ open_symbol for x in range(k1) ]) ]
+        if k1 == 1:
+            return [ DyckWord_class([ open_symbol, close_symbol ]) ]
+
+        dycks = []
+        if k1 > k2:
+            dycks +=  map( lambda x: [open_symbol] + x.list, DyckWords_size(k1-1, k2).list() )
+
+        for i in range(k2):
+            for d1 in DyckWords_size(i,i).list():
+                for d2 in DyckWords_size(k1-i-1, k2-i-1).list():
+                    dycks.append( [open_symbol] + d1.list + [close_symbol] + d2.list)
+
+        dycks.sort()
+        dycks.reverse()
+        return map(lambda x: DyckWord_class(x), dycks)
+
+
+
+
+
+def is_a_prefix(obj, k1 = None, k2 = None):
+    """
+
+    If k1 is specificied, then the object must have exactly k1 open
+    symbols.  If k2 is also specified, then obj must have exactly
+    k2 close symbols.
+
+    EXAMPLES:
+    
+    """
+    global open_symbol, close_symbol
+    
+    if k1 is not None and k2 is None:
+        k2 = k1
+    if k1 is not None and k1 < k2:
+        raise ValueError, "k1 (= %s) must be >= k2 (= %s)"%(k1, k2)
+
+
+    n_opens = 0
+    n_closes = 0
+
+    for p in obj:
+        if p == open_symbol:
+            n_opens += 1
+        elif p == close_symbol:
+            n_closes += 1
+        else:
+            return False
+
+        if n_opens < n_closes:
+            return False
+
+        if k1 is None and k2 is None:
+            return True
+        elif k2 is None:
+            return n_opens == k1
+        else:
+            return n_opens == k1 and n_closes == k2
+
+
+def is_a(obj, k1 = None, k2 = None):
+    """
+    """
+    global open_symbol, close_symbol
+    
+    if k1 is not None and k2 is None:
+        k2 = k1
+    if k1 is not None and k1 < k2:
+        raise ValueError, "k1 (= %s) must be >= k2 (= %s)"%(k1, k2)
+
+
+    n_opens = 0
+    n_closes = 0
+
+    for p in obj:
+        if p == open_symbol:
+            n_opens += 1
+        elif p == close_symbol:
+            n_closes += 1
+        else:
+            return False
+
+        if n_opens < n_closes:
+            return False
+
+    if k1 is None and k2 is None:
+        return n_opens == n_closes
+    elif k2 is None:
+        return n_opens == n_closes and n_opens == k1
+    else:
+        return n_opens == k1 and n_closes == k2
+
+def from_noncrossing_partition(ncp):
+    """
+    TESTS:
+        sage: DyckWord(noncrossing_partition=[[1,2]])
+        [1, 1, 0, 0]
+        sage: DyckWord(noncrossing_partition=[[1],[2]])
+        [1, 0, 1, 0]
+
+        sage: dws = DyckWords(5).list()
+        sage: ncps = map( lambda x: x.to_noncrossing_partition(), dws)
+        sage: dws2 = map( lambda x: DyckWord(noncrossing_partition=x), ncps)
+        sage: dws == dws2
+        True
+    """
+    global open_symbol, close_symbol
+    
+    l = [ 0 ] * int( sum( [ len(v) for v in ncp ] ) )
+    for v in ncp:
+        l[v[-1]-1] = len(v)
+
+    res = []
+    for i in l:
+        res += [ open_symbol ] + [close_symbol]*int(i)
+    return DyckWord(res)
+
+def from_ordered_tree(tree):
+    """
+    TESTS:
+        sage: sage.combinat.dyck_word.from_ordered_tree(1)
+        Traceback (most recent call last):
+        ...
+        NotImplementedError: TODO
+    """
+    raise NotImplementedError, "TODO"
Index: sage/combinat/generator.py
===================================================================
--- sage/combinat/generator.py	(revision 6439)
+++ sage/combinat/generator.py	(revision 6439)
@@ -0,0 +1,94 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+def concat(gens):
+    r"""
+    Returns a generator that is the concatenation
+    of the generators in the list.
+
+    EXAMPLES:
+        sage: list(sage.combinat.generator.concat([[1,2,3],[4,5,6]]))
+        [1, 2, 3, 4, 5, 6]
+    """
+
+    for gen in gens:
+        for element in gen:
+            yield element
+
+
+def map(f, gen):
+    """
+    Returns a generator that returns f(g) for
+    g in gen.
+
+    EXAMPLES:
+        sage: f = lambda x: x*2
+        sage: list(sage.combinat.generator.map(f,[4,5,6]))
+        [8, 10, 12]
+    """
+    for element in gen:
+        yield f(element)
+
+def element(element, n = 1):
+    """
+    Returns a generator that yield a single element
+    n times.
+
+    EXAMPLES:
+        sage: list(sage.combinat.generator.element(1))
+        [1]
+        sage: list(sage.combinat.generator.element(1, n=3))
+        [1, 1, 1]
+    """
+    for i in range(n):
+        yield element
+
+def select(f, gen):
+    """
+    Returns a generator for all the elements g of gen
+    such that f(g) is True.
+
+    EXAMPLES:
+        sage: f = lambda x: x % 2 == 0
+        sage: list(sage.combinat.generator.select(f,range(7)))
+        [0, 2, 4, 6]
+    """
+    for element in gen:
+        if f(element):
+            yield element
+
+
+def successor(initial, succ):
+    """
+    Given an initial value and a successor function,
+    yeild the initial value and each following successor.
+    The generator will continue to generate values until
+    the successor function yields None.
+
+    EXAMPLES:
+        sage: def f(x):
+        ...       if x < 10:
+        ...           return x+1
+        sage: list(sage.combinat.generator.successor(0,f))
+        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+    """
+    yield initial
+
+    s = succ(initial)
+    while s:
+        yield s
+        s = succ(s)
+
+        
Index: sage/combinat/graph_path.py
===================================================================
--- sage/combinat/graph_path.py	(revision 6594)
+++ sage/combinat/graph_path.py	(revision 6594)
@@ -0,0 +1,317 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+from combinat import CombinatorialClass
+import sage.graphs.graph as graph
+
+
+def GraphPaths(g, source=None, target=None):
+    """
+    Returns the combinatorial class of paths in the
+    directed graph g.
+
+    EXAMPLES:
+        sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+
+      If source and target are not given, then the returned class contains all
+      paths (including trivial paths containing only one vertex).
+      
+        sage: p = GraphPaths(G); p
+        Paths in Multi-digraph on 5 vertices
+        sage: p.count()
+        37
+        sage: p.random() #random
+        [3, 4, 5]
+        
+        
+      If the source is specified, then the returned class contains all of the paths
+      starting at the vertex source (including the trivial path).
+
+         sage: p = GraphPaths(G, source=3); p
+         Paths in Multi-digraph on 5 vertices starting at 3
+         sage: p.list()
+         [[3], [3, 4], [3, 4, 5], [3, 4, 5]]
+
+
+      If the target is specified, then the returned class contains all of the paths
+      ending at the vertex target (including the trivial path).
+
+        sage: p = GraphPaths(G, target=3); p
+        Paths in Multi-digraph on 5 vertices ending at 3
+        sage: p.count()
+        5
+        sage: p.list()
+        [[3], [1, 3], [2, 3], [1, 2, 3], [1, 2, 3]]
+
+
+      If both the target and source are specified, then the returned class
+      contains all of the paths from source to target.
+
+        sage: p = GraphPaths(G, source=1, target=3); p
+        Paths in Multi-digraph on 5 vertices starting at 1 and ending at 3
+        sage: p.count()
+        3
+        sage: p.list()
+        [[1, 2, 3], [1, 2, 3], [1, 3]]
+         
+    """
+    if not isinstance(g, graph.DiGraph):
+        raise TypeError, "g must be a DiGraph"
+    if source is None and target is None:
+        return GraphPaths_all(g)
+    elif source is not None and target is None:
+        if source not in g:
+            raise ValueError, "source must be in g"
+        return GraphPaths_s(g, source)
+    elif source is None and target is not None:
+        if target not in g:
+            raise ValueError, "target must be in g"
+        return GraphPaths_t(g, target)
+    else:
+        if source not in g:
+            raise ValueError, "source must be in g"       
+        if target not in g:
+            raise ValueError, "target must be in g"
+        return GraphPaths_st(g, source, target)
+    
+class GraphPaths_common:
+    def outgoing_edges(self, v):
+        """
+        Returns a list of v's outgoing edges.
+
+        EXAMPLES:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G)
+            sage: p.outgoing_edges(2)
+            [(2, 3, None), (2, 4, None)]
+        """
+        return [i for i in self.graph.outgoing_edge_iterator(v)]
+
+    def incoming_edges(self, v):
+        """
+        Returns a list of v's incoming edges.
+
+        EXAMPLES:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G)
+            sage: p.incoming_edges(2)
+            [(1, 2, None), (1, 2, None)]
+        """
+        return [i for i in self.graph.incoming_edge_iterator(v)]
+
+    def outgoing_paths(self, v):
+        """
+        Returns a list of the paths that start at v.
+        """
+        source = v
+        source_paths = [ [v] ]
+        for e in self.outgoing_edges(v):
+            target = e[1]
+            target_paths = self.outgoing_paths(target)
+            target_paths = [ [v]+path  for path in target_paths]
+
+            source_paths += target_paths
+
+        return source_paths
+
+
+    def incoming_paths(self, v):
+        """
+        Returns a list of paths that end at v.
+        """
+        target = v
+        target_paths = [ [v] ]
+        for e in self.incoming_edges(v):
+            source = e[0]
+            source_paths = self.incoming_paths(source)
+            source_paths = [ path + [v] for path in source_paths ]
+            target_paths += source_paths
+        return target_paths
+
+    def paths_from_source_to_target(self, source, target):
+        """
+        Returns a list of paths from source to target.
+        """
+        source_paths = self.outgoing_paths(source)
+        paths = []
+        for path in source_paths:
+            if path[-1] == target:
+                paths.append(path)
+        return paths
+
+    def paths(self):
+        paths = []
+        for source in self.graph.vertices():
+            paths += self.outgoing_paths(source)
+        return paths
+                
+class GraphPaths_all(CombinatorialClass, GraphPaths_common):
+    """
+    EXAMPLES:
+        sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+        sage: p = GraphPaths(G)
+        sage: p.count()
+        37
+    """
+    def __init__(self, g):
+        """
+        TESTS:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G)
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.graph = g
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G)
+            sage: repr(p)
+            'Paths in Multi-digraph on 5 vertices'
+        """
+        return "Paths in %s"%repr(self.graph)
+
+    def list(self):
+        return self.paths()
+
+class GraphPaths_t(CombinatorialClass, GraphPaths_common):
+    def __init__(self, g, target):
+        """
+        TESTS:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G, target=4)
+            sage: p == loads(dumps(p))
+            True        
+        """
+        self.graph = g
+        self.target = target
+        
+    def __repr__(self):
+        """
+        TESTS:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G, target=4)
+            sage: repr(p)
+            'Paths in Multi-digraph on 5 vertices ending at 4'
+        """
+        return "Paths in %s ending at %s"%(repr(self.graph), self.target)
+
+    def list(self):
+        """
+        EXAMPLES:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G, target=4)
+            sage: p.list()
+            [[4],
+             [2, 4],
+             [1, 2, 4],
+             [1, 2, 4],
+             [3, 4],
+             [1, 3, 4],
+             [2, 3, 4],
+             [1, 2, 3, 4],
+             [1, 2, 3, 4]]
+        """
+        return self.incoming_paths(self.target)
+
+class GraphPaths_s(CombinatorialClass, GraphPaths_common):
+    def __init__(self, g, source):
+        """
+        TESTS:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G, 4)
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.graph = g
+        self.source = source
+        
+    def __repr__(self):
+        """
+        TESTS:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G, 4)
+            sage: repr(p)
+            'Paths in Multi-digraph on 5 vertices starting at 4'
+        """
+        return "Paths in %s starting at %s"%(repr(self.graph), self.source)
+
+    def list(self):
+        """
+        EXAMPLES:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G, 4)
+            sage: p.list()
+            [[4], [4, 5], [4, 5]]
+        """
+        return self.outgoing_paths(self.source)
+
+class GraphPaths_st(CombinatorialClass, GraphPaths_common):
+    """
+    EXAMPLES:
+        sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+        sage: GraphPaths(G,1,2).count()
+        2
+        sage: GraphPaths(G,1,3).count()
+        3
+        sage: GraphPaths(G,1,4).count()
+        5
+        sage: GraphPaths(G,1,5).count()
+        10
+        sage: GraphPaths(G,2,3).count()
+        1
+        sage: GraphPaths(G,2,4).count()
+        2
+        sage: GraphPaths(G,2,5).count()
+        4
+        sage: GraphPaths(G,3,4).count()
+        1
+        sage: GraphPaths(G,3,5).count()
+        2
+        sage: GraphPaths(G,4,5).count()
+        2
+    """
+    def __init__(self, g, source, target):
+        """
+        TESTS:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G,1,2)
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.graph = g
+        self.source = source
+        self.target = target
+        
+    def __repr__(self):
+        """
+        TESTS:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G,1,2)
+            sage: repr(p)
+            'Paths in Multi-digraph on 5 vertices starting at 1 and ending at 2'
+        """
+        return "Paths in %s starting at %s and ending at %s"%(repr(self.graph), self.source, self.target)
+
+    def list(self):
+        """
+        EXAMPLES:
+            sage: G = DiGraph({1:[2,2,3], 2:[3,4], 3:[4], 4:[5,5]}, multiedges=True)
+            sage: p = GraphPaths(G,1,2)
+            sage: p.list()
+            [[1, 2], [1, 2]]
+        """
+        return self.paths_from_source_to_target(self.source, self.target)
Index: sage/combinat/hall_littlewood.py
===================================================================
--- sage/combinat/hall_littlewood.py	(revision 6594)
+++ sage/combinat/hall_littlewood.py	(revision 6594)
@@ -0,0 +1,413 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from combinat import CombinatorialClass
+from sage.libs.symmetrica.all import hall_littlewood
+from combinatorial_algebra import CombinatorialAlgebra, CombinatorialAlgebraElement
+import sfa
+import partition
+from sage.matrix.all import matrix, MatrixSpace
+from sage.rings.all import ZZ, QQ
+
+
+##################################
+#Still under major development!!!#
+##################################
+
+class HallLittlewood_generic(CombinatorialAlgebra):
+    pass
+
+
+###########
+# P basis #
+###########
+p_to_m_cache = {}
+m_to_p_cache = {}
+
+class HallLittlewoodElement_p(CombinatorialAlgebraElement):
+    pass
+
+class HallLittlewood_p(HallLittlewood_generic):
+    def __init__(self, R):
+        Rt = R['t'].fraction_field()
+        self.t = Rt.gen()
+        self._combinatorial_class = partition.Partitions()
+        self._name = "Hall-Littlewood polynomials in the P basis"
+        self._one = partition.Partition([])
+        self._prefix = "P"
+        self._element_class = HallLittlewoodElement_p
+
+        self._m = sfa.SFAMonomial(Rt)
+
+        self._p_to_m_cache = p_to_m_cache
+        self._m_to_p_cache = m_to_p_cache
+
+        CombinatorialAlgebra.__init__(self, Rt)
+
+    def _multiply(self, left, right):
+        """
+        Convert to the monomials, do the multiplication there, and
+        convert back to the P basis.
+        """
+        return self( self._m(left) * self._m(right) )
+
+ 
+    def _coerce_start(self, x):
+        """
+        Coerce things into the Hall-Littlewood P basis.
+
+        EXAMPLES:
+          1) Hall-Littlewood polynomials in the Q basis
+
+          2) Monomial symmetric functions
+        """
+
+        if isinstance(x, HallLittlewoodElement_q):
+            BR = self.base_ring()
+            t = self.t
+            z_elt = {}
+
+            #(1-Sym::vHL)^nops(part)*_mult(_mult((1-(Sym::vHL)^j)/(1-Sym::vHL) $j=1..i)
+            # $i in combinat::partitions::toExp(part))*HallLittlewood::P(part)
+            for m, c in x._monomial_coefficients.iteritems():
+                coeff = (1-t)**len(m)
+                for i in m.to_exp():
+                    for j in range(1,i+1):
+                        coeff *= (1-t**j)/(1-t)
+                z_elt[m] = BR( c*coeff )
+
+            z = self(0)
+            z._monomial_coefficients = z_elt
+            return z
+        else:
+            raise TypeError
+
+    def _scalar_hl_part(part1, part2):
+        return self._m(part1).scalar_hl(part2, t=self.t)
+
+    def _m_cache(self, n):
+        if n in p_to_m_cache:
+            return
+
+        #All the coefficients stored will be in
+        #Zt even though we need to do the computations
+        #in Ztff
+        Qt = QQ['t']
+        Qtff = Qt.fraction_field()
+        t = Qtff.gen()
+        m = sfa.SFAMonomial(QQ)
+        one = Qt(1)
+        zero = Qtff(0)
+
+        pn = partition.Partitions(n)
+        len_pn = pn.count()
+        pn = pn.list()
+        mpn = map(m, pn)
+
+        p2m_n = {}
+        m2p_n = {}
+
+        #Store the list of scalar products <P_mu, P_lambda>_t
+        p_scalars = [None]*len_pn
+
+        ################################
+        #Compute the expansions of HL  #
+        #from [1,...,1] to [n]         #
+        ################################
+        
+        #The coefficient of the all ones partition is 1
+        p2m_n[pn[-1]] = {pn[-1]: one}
+        p_scalars[-1] = mpn[-1].scalar_hl(mpn[-1], t=t)
+    
+
+        M = sfa.SFAMonomial(Qt)
+        def convert_to_m( i):
+            res = M(0)
+            res._monomial_coefficients = p2m_n[ pn[i] ]
+            return res
+        
+        for i in range(len_pn-2,-1,-1):
+            p2m_n[pn[i]] = {}
+            mi = mpn[ i ]
+
+            #Coefficient on mu = lambda is 1
+            p2m_n[ pn[i] ][ pn[i] ] = one
+            
+            for j in range(i+1, len_pn):
+                mj = mpn[ j ]
+                #Calculate <m_i, P_j>_t and store it in value
+                Pj = convert_to_m(j)
+                value = M(pn[i]).scalar_hl(Pj, t=t)
+                p2m_n[ pn[i] ][ pn[j] ]  = (-value/p_scalars[j])
+                #p2m_n[ pn[i] ][ pn[j] ] = p2m_n[ pn[i] ][ pn[j] ]
+
+            Pi = convert_to_m(i)
+            p_scalars[i] = Pi.scalar_hl(Pi, t=t)
+            
+        p_to_m_cache[n] = p2m_n
+
+        print p_scalars
+        
+        
+
+###########
+# Q basis #
+###########
+class HallLittlewoodElement_q(CombinatorialAlgebraElement):
+    pass
+
+class HallLittlewood_q(HallLittlewood_generic):
+    def __init__(self, R):
+        Rt = R['t'].fraction_field()
+        self.t = Rt.gen()
+        self._combinatorial_class = partition.Partitions()
+        self._name = "Hall-Littlewood polynomials in the Q basis"
+        self._one = partition.Partition([])
+        self._prefix = "Q"
+        self._element_class = HallLittlewoodElement_q
+
+        self._P = HallLittlewood_p(R)
+
+        CombinatorialAlgebra.__init__(self,Rt)
+
+    def _multiply(self, left, right):
+        """
+        Converts to the P basis, does the multiplication there, and
+        converts back to the Q basis.
+        
+        """
+        return self( self._P(left) * self._P(right) )
+
+
+    def _coerce_start(self, x):
+        """
+        Coerce things into the Hall-Littlewood Q basis.
+
+        1) Hall-Littlewood polynomials in the P basis
+        """
+
+        if isinstance(x, HallLittlewoodElement_p):
+            BR = self.base_ring()
+            t = self.t
+            z_elt = {}
+
+            #(1/(1-Sym::vHL)^nops(part))*_mult(_mult((1-Sym::vHL)/(1-Sym::vHL^j) $j=1..i)
+            # $i in combinat::partitions::toExp(part))*HallLittlewood::Q(part)
+            for m, c in x._monomial_coefficients.iteritems():
+                coeff = 1/(1-t)**len(m)
+                for i in m.to_exp():
+                    for j in range(1,i+1):
+                        coeff *= (1-t)/(1-t**j)
+                z_elt[m] = BR( c*coeff )
+
+            z = self(0)
+            z._monomial_coefficients = z_elt
+            return z
+        else:
+            raise TypeError
+
+
+############
+# Qp basis #
+############
+qp_to_s_cache = {}
+s_to_qp_cache = {}
+
+class HallLittlewoodElement_qp(CombinatorialAlgebraElement):
+    def expand(self, n, alphabet='x'):
+        return self.parent()._s(self).expand(n, alphabet=alphabet)
+
+class HallLittlewood_qp(HallLittlewood_generic):
+    def __init__(self, R):
+        Rt = R['t'].fraction_field()
+        self.t = Rt.gen()
+        self._combinatorial_class = partition.Partitions()
+        self._name = "Hall-Littlewood polynomials in the Qp basis"
+        self._one = partition.Partition([])
+        self._prefix = "Qp"
+        self._element_class = HallLittlewoodElement_qp
+
+        self._s = sfa.SFASchur(Rt)
+
+        self._qp_to_s_cache = qp_to_s_cache
+        self._s_to_qp_cache = s_to_qp_cache
+
+        CombinatorialAlgebra.__init__(self,Rt)
+
+
+    def _coerce_start(self, x):
+        """
+        Coerce things into the Hall-Littlewood Qp basis.
+
+        1) Symmetric Functions
+        """
+        if isinstance(x, sfa.SymmetricFunctionAlgebraElement_generic):
+            sx = self._s( x )
+            BR = self.base_ring()
+            zero = BR(0)
+
+            z_elt = {}
+            for m, c in sx._monomial_coefficients.iteritems():
+                n = sum(m)
+                self._s_cache(n)
+                for part in self._s_to_qp_cache[n][m]:
+                    z_elt[part] = z_elt.get(part, zero) + BR(c*self._s_to_qp_cache[n][m][part])
+
+            z = self(0)
+            z._monomial_coefficients = z_elt
+            return z
+
+        raise TypeError
+    
+    def _multiply(self, left, right):
+        """
+        Converts the Hall-Littlewood polynomial in the Qp basis
+        to a Schur function, performs the multiplication there,
+        and converts it back to the Qp basis.
+        """
+        return self( self._s(left)*self._s(right) )._monomial_coefficients
+
+    def _get_hl_matrix(self, n, pn):
+        #Univariate polynomial arithmetic is faster
+        #over ZZ.  Since that is all we need to compute
+        #the transition matrices between S and Qp, we
+        #should use that.        
+        Zt = ZZ['t']
+        t = Zt.gen()
+
+        #Generate the expansions of the Qp polynomials in terms
+        #of the Schur functions.
+        hlqpn = [ hall_littlewood(p) for p in pn ]
+
+        #Since the coefficients returned by hall_littlewood are in ZZ['x'], we
+        #need to replace the x's with t's.
+        hlqpn_m = [[ x.coefficient(p).subs(x=t) for p in pn ] for x in hlqpn ]
+        
+        return hlqpn_m
+    
+
+    def _s_cache_local(self, n):
+        #Compute the generic transition matrices
+        #if needed
+        self._s_cache_generic(n)
+
+        #Convert the generic transition matrices to matrices in
+        #our self's base ring
+        self._qp_to_s_cache[n] = {}
+        self._s_to_qp_cache[n] = {}
+
+        BR = self.base_ring()
+
+        coerce = True
+        if BR.base() == ZZ['t']:
+            coerce=False
+
+        for part1 in qp_to_s_cache[n]:
+            self._qp_to_s_cache[n][part1] = {}
+            self._s_to_qp_cache[n][part1] = {}
+            for part2 in qp_to_s_cache[n][part1]:
+                self._qp_to_s_cache[n][part1][part2] = BR(qp_to_s_cache[n][part1][part2], coerce=coerce)
+            for part2 in s_to_qp_cache[n][part1]:
+                self._s_to_qp_cache[n][part1][part2] = BR(s_to_qp_cache[n][part1][part2], coerce=coerce)
+    
+    def _s_cache(self, n):
+        """
+        Computes the change of basis between the Qp polynomials and
+        the Schur functions for partitions of size n.
+
+        Uses the fact that the transformation matrix is lower-triangular
+        in order to obtain the inverse transformation.
+        
+        """
+        global qp_to_s_cache, s_to_qp_cache
+
+        #Do nothing if we've already computed the transition matrices
+        #for degree n.
+        if n in qp_to_s_cache:
+            return
+
+        #Univariate polynomial arithmetic is faster
+        #over ZZ.  Since that is all we need to compute
+        #the transition matrices between S and Qp, we
+        #should use that.
+        Zt = ZZ['t']
+        t = Zt.gen()
+
+        #We have to handle the case where n == 0 seperately
+        #since symmetrica.hall_littlewood does not like
+        #the empty partition.
+        if n == 0:
+            p = partition.Partition_class([])
+            qp_to_s_cache[ n ] = {p: {p: Zt(1)}}
+            s_to_qp_cache[ n ] = {p: {p: Zt(1)}}
+            return
+
+
+        #Make sure we don't need to spend extra time
+        #coercing things into Zt
+        one = Zt(1)
+        zero = Zt(0)
+        def delta(i):
+            def f(j):
+                if i == j:
+                    return one
+                else:
+                    return zero
+            return f
+
+        #Get and store the list of partition we'll need
+        pn = partition.Partitions_n(n).list()
+
+        #Get the matrix with all the coefficients of the
+        #expansions of the Qp polynomials in S.
+        #Note: The function should probably be written so
+        #that we don't need to store all of these in memory
+        #at once
+        hlqpn_m = self._get_hl_matrix(n, pn)
+
+
+        #Create the initial cache dictionaries
+        qp2s_n = {}
+        s2qp_n = {}
+        for i in range(len(pn)):
+            qp2s_part = {}
+            s2qp_part = {}
+            #Since we already have to coefficients from
+            #Qp -> S, we can store them here.
+            for j in range(i+1):
+                if hlqpn_m[i][j] != zero:
+                    qp2s_part[ pn[ j ] ] = hlqpn_m[i][j]
+            qp2s_n[ pn[i] ] = qp2s_part
+            s2qp_n[ pn[i] ] = s2qp_part
+
+
+        #Compute the inverse of hlqpn_m by using forward
+        #substitution.  We solve a len(pn) systems of 
+        #equations hlqpn_m*x = b_i for x, where e_i
+        #is the ith standard basis vector
+        for column in range(len(pn)):
+            e = delta(column)
+            x = []
+            for i in range(len(pn)):
+                value = e(i)
+                for j in range(len(x)):
+                    value -= hlqpn_m[i][j]*x[j]
+                x.append(value)
+            for j in range(column,len(x)):
+                if x[j] != zero:
+                    s2qp_n[ pn[j] ][ pn[column] ] = x[ j ]
+
+        qp_to_s_cache[ n ] = qp2s_n
+        s_to_qp_cache[ n ] = s2qp_n
Index: sage/combinat/integer_list.py
===================================================================
--- sage/combinat/integer_list.py	(revision 6439)
+++ sage/combinat/integer_list.py	(revision 6439)
@@ -0,0 +1,559 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+import generator
+from sage.calculus.calculus import Function_floor
+from sage.rings.arith import binomial
+from sage.rings.infinity import PlusInfinity
+import __builtin__
+
+flr = Function_floor()
+infinity = PlusInfinity()
+
+def first(n, min_length, max_length, floor, ceiling, min_slope, max_slope):
+    """
+    Returns the lexicographically smallest valid composition of n
+    satisfying the conditions.
+
+    Preconditions:
+    //  - minslope < maxslope
+    //  - floor and ceiling need to satisfy the slope constraints
+    //    e.g. be obtained from comp2floor or comp2ceil
+    //  - floor must be below ceiling to ensure the existence a
+    //    valid composition
+
+    EXAMPLES:
+
+
+    TESTS:
+        sage: import sage.combinat.integer_list as integer_list
+        sage: f = lambda l: lambda i: l[i-1]
+        sage: f([0,1,2,3,4,5])(1)
+        0
+        sage: integer_list.first(12, 4, 4, f([0,0,0,0]), f([4,4,4,4]), -1, 1)
+        [4, 3, 3, 2]
+        sage: integer_list.first(36, 9, 9, f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -1, 1)
+        [7, 6, 5, 5, 4, 3, 3, 2, 1]
+        sage: integer_list.first(25, 9, 9, f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1)
+        [7, 6, 5, 4, 2, 1, 0, 0, 0]
+        sage: integer_list.first(36, 9, 9, f([3,3,3,2,1,4,2,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1)
+        [7, 6, 5, 5, 5, 4, 3, 1, 0]
+
+    """
+
+    #Increase minl until n <= sum([ceiling(i) for i in range(min_length)])
+    #This may run forever!
+    N = sum([ceiling(i) for i in range(1,min_length+1)])
+    while N < n:
+        min_length += 1
+        if min_length > max_length:
+            return None
+            raise ValueError, "min length > max length"
+
+        if ceiling(min_length) == 0 and max_slope <= 0:
+            return None
+            raise ValueError, "N will never increase again"
+
+        N += ceiling(min_length)
+
+
+    #This is the place where it's required that floor(i)
+    #respects the floor conditions.
+    n -= sum([floor(i) for i in range(1, min_length+1)])
+    if n < 0:
+        return None
+        raise ValueError
+
+    #Now we know that we can build the composition inside
+    #the "tube" [1 ... min_length] * [floor, ceiling]
+
+    if min_slope == -infinity:
+        #Easy case: min_slope == -infinity
+        result = []
+        i = min_length
+        for i in range(1,min_length+1):
+            if n <= ceiling(i) - floor(i):
+                result.append(floor(i) + n)
+                break
+            else:
+                result.append(ceiling(i))
+                n -= ceiling(i) - floor(i)
+
+        result += [floor(j) for j in range(i+1,min_length+1)]
+        return result
+
+    else:
+        if n == 0 and min_length == 0:
+            return []
+
+        low_x = 1
+        low_y = floor(1)
+        high_x = 1
+        high_y = floor(1)
+
+        while n > 0:
+            #invariant after each iteration of the loop:
+            #[low_x, low_y] is the coordinate of the rightmost point of the
+            #current diagonal s.t. floor(low_x) < low_y
+            low_y += 1
+            while low_x < min_length and low_y+min_slope > floor(low_x + 1):
+                low_x += 1
+                low_y += min_slope
+
+            high_y += 1
+            while high_y > ceiling(high_x):
+                high_x += 1
+                high_y += min_slope
+
+            n -= low_x - high_x + 1
+
+        #print "lx, ly, hw, hy, n", low_x, low_y, high_x, high_y, n
+        #print (high_x-1 - 1 + 1)  + (n + 1 - 0 + 1) + ( low_x-high_x - n + 1) + (min_length - (low_x + 1) +1)
+        result = []
+        result += [ ceiling(j) for j in range(1,high_x)] 
+        result += [ high_y + min_slope*i - 1 for i in range(0, -n) ] 
+        result += [ high_y + min_slope*i for i in range(-n, low_x-high_x+1)]
+        result += [ floor(j) for j in range(low_x+1,min_length+1) ]
+
+        return result
+
+
+def lower_regular(comp, min_slope, max_slope):
+    """
+    Returns the uppest regular composition below comp
+
+    TESTS:
+        sage: import sage.combinat.integer_list as integer_list
+        sage: integer_list.lower_regular([4,2,6], -1, 1)
+        [3, 2, 3]
+        sage: integer_list.lower_regular([4,2,6], -1, infinity)
+        [3, 2, 6]
+        sage: integer_list.lower_regular([1,4,2], -1, 1)
+        [1, 2, 2]
+        sage: integer_list.lower_regular([4,2,6,3,7], -2, 1)
+        [4, 2, 3, 3, 4]
+        sage: integer_list.lower_regular([4,2,infinity,3,7], -2, 1)
+        [4, 2, 3, 3, 4]
+        sage: integer_list.lower_regular([1, infinity, 2], -1, 1)
+        [1, 2, 2]
+        sage: integer_list.lower_regular([infinity, 4, 2], -1, 1)
+        [4, 3, 2]
+    """
+
+    new_comp = comp[:]
+    for i in range(1, len(new_comp)):
+        new_comp[i] = min(new_comp[i], new_comp[i-1] + max_slope)
+
+    for i in reversed(range(len(new_comp)-1)):
+        new_comp[i] = min( new_comp[i], new_comp[i+1] - min_slope)
+
+    return new_comp
+
+def rightmost_pivot(comp, min_length, max_length, floor, ceiling, min_slope, max_slope):
+    """
+
+    TESTS:
+        sage: import sage.combinat.integer_list as integer_list
+        sage: f = lambda l: lambda i: l[i-1]
+        sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9, f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -1, 0)
+        [7, 2]
+        sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 0)
+        [7, 1]
+        sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 4)
+        [8, 1]
+        sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1)
+        [8, 1]
+        sage: integer_list.rightmost_pivot([7,6,5,5,5,5,5,4,4], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1)
+        sage: integer_list.rightmost_pivot([3,3,3,2,1,1,0,0,0], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1)
+        sage: g = lambda x: lambda i: x
+        sage: integer_list.rightmost_pivot([1],1,1,g(0),g(2),-10, 10)
+        sage: integer_list.rightmost_pivot([1,2],2,2,g(0),g(2),-10, 10)
+        sage: integer_list.rightmost_pivot([1,2],2,2,g(1),g(2), -10, 10)
+        sage: integer_list.rightmost_pivot([1,2],2,3,g(1),g(2), -10, 10)
+        [2, 1]
+        sage: integer_list.rightmost_pivot([2,2],2,3,g(2),g(2),-10, 10)
+        sage: integer_list.rightmost_pivot([2,3],2,3,g(2),g(2),-10,+10)
+        sage: integer_list.rightmost_pivot([3,2],2,3,g(2),g(2),-10,+10)
+        sage: integer_list.rightmost_pivot([3,3],2,3,g(2),g(2),-10,+10)
+        [1, 2]
+        sage: integer_list.rightmost_pivot([6],1,3,g(0),g(6),-1,0)
+        [1, 0]
+        sage: integer_list.rightmost_pivot([6],1,3,g(0),g(6),-2,0)
+        [1, 0]
+        sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(0),g(10),-1,10)
+        [2, 6]
+        sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(5),g(10),-10,10)
+        [3, 5]
+        sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(5),g(10),-1,10)
+        [2, 6]
+        sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(4),g(10),-2,10)
+        [3, 7]
+        sage: integer_list.rightmost_pivot([9,8,7],1,4,g(4),g(10),-2,0)
+        [1, 4]
+        sage: integer_list.rightmost_pivot([1,3],1,5,lambda i: i,g(10),-10,10)
+        sage: integer_list.rightmost_pivot([1,4],1,5,lambda i: i,g(10),-10,10)
+        sage: integer_list.rightmost_pivot([2,4],1,5,lambda i: i,g(10),-10,10)
+        [1, 1]
+
+
+    """
+    
+    y = len(comp) + 1
+    while y <= max_length:
+        if ceiling(y) > 0:
+            break
+        if maxSlope <= 0:
+            y = max_length + 1
+            break
+        y += 1
+
+    x = len(comp)
+    if x == 0:
+        return None
+
+    ceilingx_x = comp[x-1]-1
+    floorx_x = floor(x)
+    if x > 1:
+        floorx_x = max(floorx_x, comp[x-2]+min_slope)
+
+    F = comp[x-1] - floorx_x
+    G = ceilingx_x - comp[x-1] #this is -1
+
+    highX = x
+    lowX  = x
+  
+    while not (ceilingx_x >= floorx_x and
+               (G >= 0 or
+               ( y < max_length +1 and
+                 F - max(floor(y), floorx_x + (y-x)*min_slope) >= 0 and
+                 G + min(ceiling(y), ceilingx_x + (y-x)*max_slope) >= 0 ))):
+
+        if x == 1:
+            return None
+
+        x -= 1
+
+        old_ceilingx_x = ceilingx_x
+        oldfloorx_x    = floorx_x
+        ceilingx_x = comp[x-1] - 1
+        floorx_x   = floor(x)
+        if x > 1:
+            floorx_x = max(floorx_x, comp[x-2]+min_slope)
+
+        min_slope_lowX  = min_slope*(lowX - x)
+        max_slope_highX = max_slope*(highX - x)
+
+
+        #Update G
+        if max_slope == infinity:
+            #In this case, we have
+            #  -- ceiling_x(i) = ceiling(i) for i > x
+            #  --G >= 0 or G = -1
+            G += ceiling(x+1)-comp[x]
+        else:
+            G += (highX - x)*( (comp[x-1]+max_slope) - comp[x]) - 1
+            temp = (ceilingx_x + max_slope_highX) - ceiling(highX)
+            while highX > x and ( temp >= 0 ):
+                G  -= temp
+                highX -= 1
+                max_slope_highX = max_slope*(highX-x)
+                temp = (ceilingx_x + max_slope_highX) - ceiling(highX)
+
+        if G >= 0 and comp[x-1] > floorx_x:
+            #By case 1, x is at the rightmost pivot position
+            break
+
+        #Update F
+        if y < max_length+1:
+            F += comp[x-1] - floorx_x
+            if min_slope != -infinity:
+                F += (lowX - x) * (oldfloorx_x - (floorx_x + min_slope))
+                temp = floor(lowX) - (floorx_x + min_slope_lowX)
+                while lowX > x and temp >= 0:
+                    F -= temp
+                    lowX -= 1
+                    min_slope_lowX = min_slope*(lowX-x)
+                    temp = floor(lowX) - (floorx_x + min_slope_lowX)
+
+    return [x, floorx_x]
+
+def next(comp, min_length, max_length, floor, ceiling, min_slope, max_slope):
+    """
+    Returns the next integer list after comp that satisfies the contraints.        
+    """
+
+    x = rightmost_pivot( comp, min_length, max_length, floor, ceiling, min_slope, max_slope)
+    if x == None:
+        return None
+    [x, low] = x
+    high = comp[x-1]-1
+
+##     // Build wrappers around floor and ceiling to take into
+##     // account the new constraints on the value of compo[x].
+##     //
+##     // Efficiency note: they are not wrapped more than once, since
+##     // the method Next calls first, but not the converse.
+
+    if min_slope == -infinity:
+        new_floor = lambda i: floor(x+(i-1))
+    else:
+        new_floor = lambda i: max(floor(x+(i-1)), low+(i-1)*min_slope)
+
+    if max_slope == infinity:
+        def new_ceiling(i):
+            if i == 1:
+                return comp[x-1] - 1
+            else:
+                return ceiling(x+(i-1))
+    else:
+        new_ceiling = lambda i: min(ceiling(x+(i-1)), high+(i-1)*max_slope)
+
+
+    res = []
+    res += comp[:x-1]
+    res += first(sum(comp[x-1:]), max(min_length-x+1, 0), max_length-x+1,
+                 new_floor, new_ceiling, min_slope, max_slope)
+    return res
+
+                                  
+         
+
+
+def iterator(n, min_length, max_length, floor, ceiling, min_slope, max_slope):
+    """
+
+    """
+
+    succ = lambda x: next(x, min_length, max_length, floor, ceiling, min_slope, max_slope)
+
+    #Handle the case where n is a list of integers
+    if isinstance(n, __builtin__.list):
+        iterators = [iterator(i, min_length, max_length, floor, ceiling, min_slope, max_slope) for i in range(n[0], min(n[1]+1,upper_bound(min_length, max_length, floor, ceiling, min_slope, max_slope)))]
+        
+        return generator.concat(iterators)
+    else:
+        f =  first(n, min_length, max_length, floor, ceiling, min_slope, max_slope)
+        if f == None:
+            return generator.element(None, 0)
+        return generator.successor(f, succ)
+
+def list(n, min_length, max_length, floor, ceiling, min_slope, max_slope):
+    """
+
+    EXAMPLES:
+        sage: import sage.combinat.integer_list as integer_list
+        sage: g = lambda x: lambda i: x
+        sage: integer_list.list(0,0,infinity,g(1),g(infinity),0,infinity)
+        [[]]
+        sage: integer_list.list(0,0,infinity,g(1),g(infinity),0,0)
+        [[]]
+        sage: integer_list.list(0, 0, 0, g(1), g(infinity), 0, 0)
+        [[]]
+        sage: integer_list.list(0, 0, 0, g(0), g(infinity), 0, 0)
+        [[]]
+        sage: integer_list.list(0, 0, infinity, g(1), g(infinity), 0, infinity)
+        [[]]
+        sage: integer_list.list(1, 0, infinity, g(1), g(infinity), 0, infinity)
+        [[1]]
+        sage: integer_list.list(0, 1, infinity, g(1), g(infinity), 0, infinity)
+        []
+        sage: integer_list.list(0, 1, infinity, g(0), g(infinity), 0, infinity)
+        [[0]]
+        sage: integer_list.list(3, 0, 2, g(0), g(infinity), -infinity, infinity)
+        [[3], [2, 1], [1, 2], [0, 3]]
+        sage: partitions = (0, infinity, g(0), g(infinity), -infinity, 0)
+        sage: partitions_min_2 = (0, infinity, g(2), g(infinity), -infinity, 0)
+        sage: compositions = (0, infinity, g(1), g(infinity), -infinity, infinity)
+        sage: integer_vectors = lambda l: (l, l, g(0), g(infinity), -infinity, infinity)
+        sage: lower_monomials = lambda c: (len(c), len(c), g(0), lambda i: c[i], -infinity, infinity)
+        sage: upper_monomials = lambda c: (len(c), len(c), g(0), lambda i: c[i], -infinity, infinity)
+        sage: constraints = (0, infinity, g(1), g(infinity), -1, 0)
+        sage: integer_list.list(6, *partitions)
+        [[6],
+         [5, 1],
+         [4, 2],
+         [4, 1, 1],
+         [3, 3],
+         [3, 2, 1],
+         [3, 1, 1, 1],
+         [2, 2, 2],
+         [2, 2, 1, 1],
+         [2, 1, 1, 1, 1],
+         [1, 1, 1, 1, 1, 1]]
+        sage: integer_list.list(6, *constraints)
+        [[6],
+         [3, 3],
+         [3, 2, 1],
+         [2, 2, 2],
+         [2, 2, 1, 1],
+         [2, 1, 1, 1, 1],
+         [1, 1, 1, 1, 1, 1]]
+        sage: integer_list.list(1, *partitions_min_2)
+        []
+        sage: integer_list.list(2, *partitions_min_2)
+        [[2]]
+        sage: integer_list.list(3, *partitions_min_2)
+        [[3]]
+        sage: integer_list.list(4, *partitions_min_2)
+        [[4], [2, 2]]
+        sage: integer_list.list(5, *partitions_min_2)
+        [[5], [3, 2]]
+        sage: integer_list.list(6, *partitions_min_2)
+        [[6], [4, 2], [3, 3], [2, 2, 2]]
+        sage: integer_list.list(7, *partitions_min_2)
+        [[7], [5, 2], [4, 3], [3, 2, 2]]
+        sage: integer_list.list(9, *partitions_min_2)
+        [[9], [7, 2], [6, 3], [5, 4], [5, 2, 2], [4, 3, 2], [3, 3, 3], [3, 2, 2, 2]]
+        sage: integer_list.list(10, *partitions_min_2)
+        [[10],
+         [8, 2],
+         [7, 3],
+         [6, 4],
+         [6, 2, 2],
+         [5, 5],
+         [5, 3, 2],
+         [4, 4, 2],
+         [4, 3, 3],
+         [4, 2, 2, 2],
+         [3, 3, 2, 2],
+         [2, 2, 2, 2, 2]]
+        sage: integer_list.list(4, *compositions)
+        [[4], [3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
+    """
+    return __builtin__.list(iterator(n, min_length, max_length, floor, ceiling, min_slope, max_slope))
+
+def upper_regular(comp, min_slope, max_slope):
+    """
+    Returns the uppest regular composition above comp.
+
+    TESTS:
+        sage: import sage.combinat.integer_list as integer_list
+        sage: integer_list.upper_regular([4,2,6],-1,1)
+        [4, 5, 6]
+        sage: integer_list.upper_regular([4,2,6],-2, 1)
+        [4, 5, 6]
+        sage: integer_list.upper_regular([4,2,6,3,7],-2, 1)
+        [4, 5, 6, 6, 7]
+        sage: integer_list.upper_regular([4,2,6,1], -2, 1)
+        [4, 5, 6, 4]
+    """
+
+    new_comp = comp[:]
+    for i in range(1, len(new_comp)):
+        new_comp[i] = max(new_comp[i], new_comp[i-1] + min_slope)
+
+    for i in reversed(range(len(new_comp)-1)):
+        new_comp[i] = max( new_comp[i], new_comp[i+1] - max_slope)
+
+    return new_comp
+
+def comp2floor(f, min_slope, max_slope):
+    """
+    Given a composition, returns the lowest regular function N->N above
+    it
+    """
+
+    if len(f) == 0:
+        def res(i):
+            return 0
+        return res
+
+
+    floor = upper_regular(f, min_slope, max_slope)
+
+    def res(i):
+        if i < len(floor):
+            return floor[i]
+        else:
+            return max(0, floor[-1]-(i-len(floor))*min_slope)
+
+    return res
+
+
+        
+    
+def comp2ceil(c, min_slope, max_slope):
+    """
+    Given a composition, returns the lowest regular function N->N below
+    it
+    """
+
+    if len(c) == 0:
+        def res(i):
+            return 0
+        return res
+
+
+    ceil = lower_regular(c, min_slope, max_slope)
+
+    def res(i):
+        if i < len(ceil):
+            return ceil[i]
+        else:
+            return max(0, ceil[-1]-(i-len(ceil))*min_slope)
+
+    return res
+
+
+def upper_bound(min_length, max_length, floor, ceiling, min_slope, max_slope):
+    """
+    Compute a coarse upper bound on the size of a vector satisfying
+    the constraints.
+
+    TESTS:
+        sage: import sage.combinat.integer_list as integer_list
+        sage: f = lambda x: lambda i: x
+        sage: integer_list.upper_bound(0,4,f(0), f(1),-infinity,infinity)
+        4
+        sage: integer_list.upper_bound(0, infinity, f(0), f(1), -infinity, infinity)
+        +Infinity
+        sage: integer_list.upper_bound(0, infinity, f(0), f(1), -infinity, -1)
+        1
+        sage: integer_list.upper_bound(0, infinity, f(0), f(5), -infinity, -1)
+        15
+        sage: integer_list.upper_bound(0, infinity, f(0), f(5), -infinity, -2)
+        9
+
+    """
+
+    if max_length < infinity:
+        return sum( [ ceiling(j) for j in range(max_length)] )
+    elif max_slope < 0 and ceiling(1) < infinity:
+        maxl = flr(-ceiling(1)/max_slope)
+        return ceiling(1)*(maxl+1) + binomial(maxl+1,2)*max_slope
+    #FIXME: only checking the first 10000 values, but that should generally
+    #be enough
+    elif [ceiling(j) for j in range(10000)] == [0 for x in range(10000)]:
+        return 0
+    else:
+        return infinity
+    
+
+
+def is_a(comp, min_length, max_length, floor, ceiling, min_slope, max_slope):
+    """
+    """
+    if len(comp) < min_length or len(comp) > max_length:
+        return False
+    for i in range(len(comp)):
+        if comp[i] < floor(i+1):
+            return False
+        if comp[i] > ceiling(i+1):
+            return False
+    for i in range(len(comp)-1):
+        slope = comp[i+1] - comp[i]
+        if slope < min_slope or slope > max_slope:
+            return False
+    return True
Index: sage/combinat/integer_vector.py
===================================================================
--- sage/combinat/integer_vector.py	(revision 6594)
+++ sage/combinat/integer_vector.py	(revision 6594)
@@ -0,0 +1,509 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from combinat import CombinatorialClass, CombinatorialObject
+from __builtin__ import list as builtinlist
+from sage.rings.integer import Integer
+from sage.rings.arith import binomial
+import misc
+from sage.rings.infinity import PlusInfinity
+import integer_list
+import cartesian_product
+
+infinity = PlusInfinity()
+def list2func(l, default=None):
+    """
+    Given a list l, return a function that takes in a value
+    i and return l[i-1].  If default is not None, then the function
+    will return the default value for out of range i's.
+
+    EXAMPLES:
+        sage: f = sage.combinat.integer_vector.list2func([1,2,3])
+        sage: f(1)
+        1
+        sage: f(2)
+        2
+        sage: f(3)
+        3
+        sage: f(4)
+        Traceback (most recent call last):
+        ...
+        IndexError: list index out of range
+
+        sage: f = sage.combinat.integer_vector.list2func([1,2,3], 0)
+        sage: f(3)
+        3
+        sage: f(4)
+        0
+    """
+    if default is None:
+        return lambda i: l[i-1]
+    else:
+        def f(i):
+            try:
+                return l[i-1]
+            except IndexError:
+                return default
+        return f
+       
+def constant_func(i):
+    """
+    Returns the constant function i.
+
+    EXAMPLES:
+        sage: f = sage.combinat.integer_vector.constant_func(3)
+        sage: f(-1)
+        3
+        sage: f('asf')
+        3
+    """
+    return lambda x: i
+
+def IntegerVectors(n=None, k=None, **kwargs):
+    """
+    Returns the combinatorial class of integer vectors.
+
+    EXAMPLES:
+      If n is not specified, it returns the class of all
+      integer vectors.
+      
+        sage: IntegerVectors()
+        Integer vectors
+        sage: [] in IntegerVectors()
+        True
+        sage: [1,2,1] in IntegerVectors()
+        True
+        sage: [1, 0, 0] in IntegerVectors()
+        True
+
+      If n is specified, then it returns the class of all
+      integer vectors which sum to n.
+      
+        sage: IV3 = IntegerVectors(3); IV3
+        Integer vectors that sum to 3
+
+      Note that trailing zeros are ignored so that [3, 0]
+      does not show up in the following list (since [3] does)
+      
+        sage: IntegerVectors(3, max_length=2).list()
+        [[3], [2, 1], [1, 2], [0, 3]]
+
+      If n and k are both specified, then it returns the class
+      of integer vectors that sum to n and are of length k.
+
+        sage: IV53 = IntegerVectors(5,3); IV53
+        Integer vectors of length 3 that sum to 5
+        sage: IV53.count()
+        21
+        sage: IV53.first()
+        [5, 0, 0]
+        sage: IV53.last()
+        [0, 0, 5]
+        sage: IV53.random() #random
+        [0, 1, 4]
+
+    """
+    if n is None:
+        return IntegerVectors_all()
+    elif k is None:
+        return IntegerVectors_nconstraints(n,kwargs)
+    else:
+        if isinstance(k, builtinlist):
+            return IntegerVectors_nnondescents(n,k)
+        else:
+            return IntegerVectors_nkconstraints(n,k,kwargs)
+
+
+class IntegerVectors_all(CombinatorialClass):
+    def __repr__(self):
+        return "Integer vectors"
+    
+    def __contains__(self, x):
+        """
+        EXAMPLES:
+            sage: [] in IntegerVectors()
+            True
+            sage: [3,2,2,1] in IntegerVectors()
+            True
+  
+        """
+        if not isinstance(x, builtinlist):
+            return False
+        for i in x:
+            if not isinstance(i, (int, Integer)):
+                return False
+            if i < 0:
+                return False
+
+        return True
+
+    def list(self):
+        raise NotImplementedError
+
+    def count(self):
+        return infinity
+
+class IntegerVectors_nkconstraints(CombinatorialClass):
+    def __init__(self, n, k, constraints):
+        """
+
+        """
+        self.n = n
+        self.k = k
+        self.constraints = constraints
+
+        #n, min_length, max_length, floor, ceiling, min_slope, max_slope
+        if k == -1:
+            min_length = constraints.get('min_length', 0)
+            max_length = constraints.get('max_length', infinity)
+        else:
+            min_length = k
+            max_length = k
+        min_part = constraints.get('min_part', 0)
+        max_part = constraints.get('max_part', infinity)
+        min_slope = constraints.get('min_slope', -infinity)
+        max_slope = constraints.get('max_slope', infinity)
+        if 'outer' in self.constraints:
+            ceiling = list2func( map(lambda i: min(max_part, i), self.constraints['outer']), default=max_part )
+        else:
+            ceiling = constant_func(max_part)
+
+        if 'inner' in self.constraints:
+            floor = list2func( map(lambda i: max(min_part, i), self.constraints['outer']), default=min_part )
+        else:
+            floor = constant_func(min_part)
+
+
+        self._parameters = (min_length, max_length, floor, ceiling, min_slope, max_slope)
+
+    def __repr__(self):
+        if self.constraints:
+            return "Integer vectors of length %s that sum to %s with constraints %s"%(self.k, self.n, ", ".join( ["%s=%s"%(key, self.constraints[key]) for key in sorted(self.constraints.keys())] ))
+        else:
+            return "Integer vectors of length %s that sum to %s"%(self.k, self.n)
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: [0] in IntegerVectors(0)
+            True
+            sage: [0] in IntegerVectors(0, 1)
+            True
+            sage: [] in IntegerVectors(0, 0)
+            True
+            sage: [] in IntegerVectors(0, 1)
+            False
+            sage: [] in IntegerVectors(1, 0)
+            False
+            sage: [3] in IntegerVectors(3)
+            True
+            sage: [3] in IntegerVectors(2,1)
+            False
+            sage: [3] in IntegerVectors(2)
+            False
+            sage: [3] in IntegerVectors(3,1)
+            True
+            sage: [3,2,2,1] in IntegerVectors(9)
+            False
+            sage: [3,2,2,1] in IntegerVectors(9,5)
+            False            
+            sage: [3,2,2,1] in IntegerVectors(8)
+            True
+            sage: [3,2,2,1] in IntegerVectors(8,5)
+            False
+            sage: [3,2,2,1] in IntegerVectors(8,4)
+            True
+            sage: [3,2,2,1] in IntegerVectors(8,4, min_part = 1)
+            True
+            sage: [3,2,2,1] in IntegerVectors(8,4, min_part = 2)
+            False
+        """
+        if x not in IntegerVectors():
+            return False
+
+        if sum(x) != self.n:
+            return False
+
+        if len(x) != self.k:
+            return False
+
+        if self.constraints:
+            if not misc.check_integer_list_constraints(x, singleton=True, **self.constraints):
+                return False
+
+        return True
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: IntegerVectors(0,0).count()
+            1
+            sage: IntegerVectors(1,0).count()
+            0
+            sage: IntegerVectors(2,2).count()
+            3
+            sage: IntegerVectors(3,3).count()
+            10
+            sage: IntegerVectors(-1,0).count()
+            0
+            sage: IntegerVectors(-1,2).count()
+            0
+            sage: IntegerVectors(3,3, min_part=1).count()
+            1
+            sage: IntegerVectors(5,3, min_part=1).count()
+            6
+            sage: IntegerVectors(13, 4, min_part=2, max_part=4).count()
+            16
+        """
+        if not self.constraints:
+            if self.n >= 0:
+                return binomial(self.n+self.k-1,self.n)
+            else:
+                return 0
+        else:
+            if len(self.constraints) == 1 and 'max_part' in self.constraints and self.constraints['max_part'] != infinity:
+                m = self.constraints['max_part']
+                if m >= self.n:
+                    return binomial(self.n+self.k-1,self.n)
+                else: #do by inclusion / exclusion on the number
+                      #i of parts greater than m
+                    return sum( [(-1)**i * binomial(self.n+self.k-1-i*(m+1), self.k-1)*binomial(self.k,i) for i in range(0, self.n/(m+1)+1)])
+            else:
+                return len(self.list())
+
+    def first(self):
+        """
+        TESTS:
+           
+        """
+        return integer_list.first(self.n, *self._parameters)
+    
+    def next(self, x):
+        """
+        TESTS:
+        """
+        return integer_list.next(x, *self._parameters)
+
+    def iterator(self):
+        """
+
+        TESTS:
+            sage: IntegerVectors(0,0).list()
+            [[]]
+            sage: IntegerVectors(1,0).list()
+            []
+            sage: IntegerVectors(0,1).list()
+            [[0]]
+            sage: IntegerVectors(2,2).list()
+            [[2, 0], [1, 1], [0, 2]]
+            sage: IntegerVectors(-1,0).list()
+            []
+            sage: IntegerVectors(-1,2).list()
+            []
+
+            
+            sage: IntegerVectors(-1, 0, min_part = 1).list()
+            []
+            sage: IntegerVectors(-1, 2, min_part = 1).list()
+            []
+            sage: IntegerVectors(0, 0, min_part=1).list()
+            [[]]
+            sage: IntegerVectors(3, 0, min_part=1).list()
+            []
+            sage: IntegerVectors(0, 1, min_part=1).list()
+            []
+            sage: IntegerVectors(2, 2, min_part=1).list()
+            [[1, 1]]
+            sage: IntegerVectors(2, 3, min_part=1).list()
+            []
+            sage: IntegerVectors(4, 2, min_part=1).list()
+            [[3, 1], [2, 2], [1, 3]]
+
+            sage: IntegerVectors(0, 3, outer=[0,0,0]).list()
+            [[0, 0, 0]]
+            sage: IntegerVectors(1, 3, outer=[0,0,0]).list()
+            []
+            sage: IntegerVectors(2, 3, outer=[0,2,0]).list()
+            [[0, 2, 0]]
+            sage: IntegerVectors(2, 3, outer=[1,2,1]).list()
+            [[1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1]]
+            sage: IntegerVectors(2, 3, outer=[1,1,1]).list()
+            [[1, 1, 0], [1, 0, 1], [0, 1, 1]]
+            sage: IntegerVectors(2, 5, outer=[1,1,1,1,1]).list()
+            [[1, 1, 0, 0, 0],
+             [1, 0, 1, 0, 0],
+             [1, 0, 0, 1, 0],
+             [1, 0, 0, 0, 1],
+             [0, 1, 1, 0, 0],
+             [0, 1, 0, 1, 0],
+             [0, 1, 0, 0, 1],
+             [0, 0, 1, 1, 0],
+             [0, 0, 1, 0, 1],
+             [0, 0, 0, 1, 1]]
+
+            sage: iv = [ IntegerVectors(n,k) for n in range(-2, 7) for k in range(7) ]
+            sage: all(map(lambda x: x.count() == len(x.list()), iv))
+            True
+            sage: essai = [[1,1,1], [2,5,6], [6,5,2]]
+            sage: iv = [ IntegerVectors(x[0], x[1], max_part = x[2]-1) for x in essai ]
+            sage: all(map(lambda x: x.count() == len(x.list()), iv))
+            True
+                        
+        """
+        return integer_list.iterator(self.n, *self._parameters)
+
+class IntegerVectors_nconstraints(IntegerVectors_nkconstraints):
+    def __init__(self, n, constraints):
+        """
+        TESTS:
+            #sage: IV = IntegerVectors(3)
+            #sage: IV == loads(dumps(IV))
+            #True
+            #sage: IV = IntegerVectors(3, max_length=2)
+            #sage: IV == loads(dumps(IV))
+            #True
+        """
+        IntegerVectors_nkconstraints.__init__(self, n, -1, constraints)
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(IntegerVectors(3))
+            'Integer vectors that sum to 3'
+            sage: repr(IntegerVectors(3, max_length=2))
+            'Integer vectors that sum to 3 with constraints max_length=2'
+        """
+        if self.constraints:
+            return "Integer vectors that sum to %s with constraints %s"%(self.n,", ".join( ["%s=%s"%(key, self.constraints[key]) for key in sorted(self.constraints.keys())] ))
+        else:
+            return "Integer vectors that sum to %s"%(self.n,)
+
+    def __contains__(self, x):
+        """
+        EXAMPLES:
+            sage: [0,3,0,1,2] in IntegerVectors(6)
+            True
+            sage: [0,3,0,1,2] in IntegerVectors(6, max_length=3)
+            False
+        """
+        if self.constraints:
+            return x in IntegerVectors_all() and misc.check_integer_list_constraints(x, singleton=True, **self.constraints)
+        else:
+            return x in IntegerVectors_all() and sum(x) == self.n
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: IntegerVectors(3).count()
+            +Infinity
+        """
+        return infinity
+
+    def list(self):
+        """
+        EXAMPLES:
+            sage: IntegerVectors(3, max_length=2).list()
+            [[3], [2, 1], [1, 2], [0, 3]]
+            sage: IntegerVectors(3).list()
+            Traceback (most recent call last):
+            ...
+            NotImplementedError: infinite list
+        """
+        if 'max_length' not in self.constraints:
+            raise NotImplementedError, "infinite list"
+        else:
+            return list(self.iterator())
+
+
+class IntegerVectors_nnondescents(CombinatorialClass):
+    r"""
+    The combinatorial class of integer vectors v graded by two parameters:
+     - n: the sum of the parts of v
+     - comp: the non descents composition of v
+    
+    In other words: the length of v equals c[1]+...+c[k], and v is
+    descreasing in the consecutive blocs of length c[1], ..., c[k]
+    
+    Those are the integer vectors of sum n which are lexicographically
+    maximal (for the natural left->right reading) in their orbit by the
+    young subgroup S_{c_1} x \dots x S_{c_k}.  In particular, they form
+    a set of orbit representative of integer vectors w.r.t. this young
+    subgroup.
+    """
+    def __init__(self, n, comp):
+        self.n = n
+        self.comp = comp
+
+    def __repr__(self):
+        return "Integer vectors of %s with non-descents composition %s"%(self.n, self.comp)
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: IntegerVectors(0, []).list()
+            [[]]
+            sage: IntegerVectors(5, []).list()
+            []
+            sage: IntegerVectors(0, [1]).list()
+            [[0]]
+            sage: IntegerVectors(4, [1]).list()
+            [[4]]
+            sage: IntegerVectors(4, [2]).list()
+            [[4, 0], [3, 1], [2, 2]]
+            sage: IntegerVectors(4, [2,2]).list()
+             [[4, 0, 0, 0],
+             [3, 0, 1, 0],
+             [2, 0, 2, 0],
+             [2, 0, 1, 1],
+             [1, 0, 3, 0],
+             [1, 0, 2, 1],
+             [0, 0, 4, 0],
+             [0, 0, 3, 1],
+             [0, 0, 2, 2]]
+            sage: IntegerVectors(5, [1,1,1]).list()
+            [[5, 0, 0],
+             [4, 1, 0],
+             [4, 0, 1],
+             [3, 2, 0],
+             [3, 1, 1],
+             [3, 0, 2],
+             [2, 3, 0],
+             [2, 2, 1],
+             [2, 1, 2],
+             [2, 0, 3],
+             [1, 4, 0],
+             [1, 3, 1],
+             [1, 2, 2],
+             [1, 1, 3],
+             [1, 0, 4],
+             [0, 5, 0],
+             [0, 4, 1],
+             [0, 3, 2],
+             [0, 2, 3],
+             [0, 1, 4],
+             [0, 0, 5]]
+            sage: IntegerVectors(0, [2,3]).list()
+            [[0, 0, 0, 0, 0]]
+
+         """
+        for iv in IntegerVectors(self.n, len(self.comp)):
+            blocks = [ IntegerVectors(iv[i], self.comp[i], max_slope=0).iterator() for i in range(len(self.comp))]
+            for parts in cartesian_product.CartesianProduct(*blocks):
+                res = []
+                for part in parts:
+                    res += part
+                yield res
+
+    
Index: sage/combinat/integer_vector_weighted.py
===================================================================
--- sage/combinat/integer_vector_weighted.py	(revision 6439)
+++ sage/combinat/integer_vector_weighted.py	(revision 6439)
@@ -0,0 +1,144 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from combinat import CombinatorialClass, CombinatorialObject
+from __builtin__ import list as builtinlist
+from sage.rings.integer import Integer
+import word
+from permutation import Permutation_class
+
+def WeightedIntegerVectors(n, weight):
+    """
+    Returns the combinatorial class of integer vectors of n
+    weighted by weight.
+
+    EXAMPLES:
+        sage: WeightedIntegerVectors(8, [1,1,2])
+        Integer vectors of 8 weighted by [1, 1, 2]
+        sage: WeightedIntegerVectors(8, [1,1,2]).first()
+        [0, 0, 4]
+        sage: WeightedIntegerVectors(8, [1,1,2]).last()
+        [8, 0, 0]
+        sage: WeightedIntegerVectors(8, [1,1,2]).count()
+        25
+        sage: WeightedIntegerVectors(8, [1,1,2]).random() #random
+        [2, 0, 3]
+    """
+    return WeightedIntegerVectors_nweight(n, weight)
+
+class WeightedIntegerVectors_nweight(CombinatorialClass):
+    def __init__(self, n, weight):
+        """
+        TESTS:
+            sage: WIV = WeightedIntegerVectors(8, [1,1,2])
+            sage: WIV == loads(dumps(WIV))
+            True
+        """
+        self.n = n
+        self.weight = weight
+        
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(WeightedIntegerVectors(8, [1,1,2]))
+            'Integer vectors of 8 weighted by [1, 1, 2]'
+        """
+        return "Integer vectors of %s weighted by %s"%(self.n, self.weight)
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: [] in WeightedIntegerVectors(0, [])
+            True
+            sage: [] in WeightedIntegerVectors(1, [])
+            False
+            sage: [3,0,0] in WeightedIntegerVectors(6, [2,1,1])
+            True
+            sage: [1] in WeightedIntegerVectors(1, [1])
+            True
+            sage: [1] in WeightedIntegerVectors(2, [2])
+            True
+            sage: [2] in WeightedIntegerVectors(4, [2])
+            True
+            sage: [2, 0] in WeightedIntegerVectors(4, [2, 2])
+            True
+            sage: [2, 1] in WeightedIntegerVectors(4, [2, 2])
+            False
+            sage: [2, 1] in WeightedIntegerVectors(6, [2, 2])
+            True
+            sage: [2, 1, 0] in WeightedIntegerVectors(6, [2, 2])
+            False
+            sage: [0] in WeightedIntegerVectors(0, [])
+            False
+        """
+        if not isinstance(x, builtinlist):
+            return False
+        if len(self.weight) != len(x):
+            return False
+        s = 0
+        for i in range(len(x)):
+            if not isinstance(x[i], (int, Integer)):
+                return False
+            s += x[i]*self.weight[i]
+        if s != self.n:
+            return False
+
+        return True
+
+    def list(self):
+        """
+        TESTS:
+            sage: WeightedIntegerVectors(7, [2,2]).list()
+            []
+            sage: WeightedIntegerVectors(3, [2,1,1]).list()
+            [[1, 0, 1], [1, 1, 0], [0, 0, 3], [0, 1, 2], [0, 2, 1], [0, 3, 0]]
+
+            sage: ivw = [ WeightedIntegerVectors(k, [1,1,1]) for k in range(11) ]
+            sage: iv  = [ IntegerVectors(k, 3) for k in range(11) ]
+            sage: all( [ sorted(iv[k].list()) == sorted(ivw[k].list()) for k in range(11) ] )
+            True
+
+            sage: ivw = [ WeightedIntegerVectors(k, [2,3,7]) for k in range(11) ]
+            sage: all( [ i.count() == len(i.list()) for i in ivw] )
+            True
+        """
+
+        if len(self.weight) == 0:
+            if n == 0:
+                return [[]]
+            else:
+                return []
+
+        perm = word.standard(self.weight)
+        l = [x for x in sorted(self.weight)]
+
+        def recfun(n, l):
+            result = []
+            w = l[-1]
+            l = l[:-1]
+            if l == []:
+                d = int(n) / int(w)
+                if n%w == 0:
+                    return [[d]]
+                else:
+                    return [] #bad branch...
+
+            for d in range(int(n)/int(w), -1, -1):
+                result += map( lambda x: x + [d], recfun(n-d*w, l) )
+
+            return result
+
+        return map( lambda x: Permutation_class(perm)._left_to_right_multiply_on_right(Permutation_class(x)), recfun(self.n,l) )
+            
Index: sage/combinat/lyndon_word.py
===================================================================
--- sage/combinat/lyndon_word.py	(revision 6439)
+++ sage/combinat/lyndon_word.py	(revision 6439)
@@ -0,0 +1,364 @@
+"""
+
+A fast algorithm to generate necklaces with fixed content
+Source 	Theoretical Computer Science archive
+Volume 301 ,  Issue 1-3  (May 2003) table of contents
+Pages: 477 - 489  
+Year of Publication: 2003
+ISSN:0304-3975
+Author 	
+Joe Sawada 	 Department of Computer Science, University of Toronto, 10 King's College Road, Toronto, Ont. Canada M5S 1A4
+Publisher 	
+Elsevier Science Publishers Ltd.   Essex, UK
+
+"""
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from combinat import CombinatorialClass, CombinatorialObject
+from sage.combinat.composition import Composition, Compositions
+from sage.rings.all import euler_phi,factorial, divisors, gcd, moebius, Integer
+from sage.misc.misc import prod
+from sage.combinat.misc import DoublyLinkedList
+import __builtin__
+import itertools
+import necklace
+from integer_vector import IntegerVectors
+import word
+
+def LyndonWords(e, k=None):
+    """
+    Returns the combinatorial class of Lyndon words.
+
+    EXAMPLES:
+      If e is an integer, then e specifies the length of the
+      alphabet; k must also be specified in this case.
+      
+        sage: LW = LyndonWords(3,3); LW
+        Lyndon words from an alphabet of size 3 of length 3
+        sage: LW.first()
+        [1, 1, 2]
+        sage: LW.last()
+        [2, 3, 3]
+        sage: LW.random() #
+        [1, 1, 2]
+        sage: LW.count()
+        8
+
+      If e is a (weak) composition, then it returns the class of
+      Lyndon words that have evaluation e.
+
+        sage: LyndonWords([2, 0, 1]).list()
+        [[1, 1, 3]]
+        sage: LyndonWords([2, 0, 1, 0, 1]).list()
+        [[1, 1, 3, 5], [1, 1, 5, 3], [1, 3, 1, 5]]
+        sage: LyndonWords([2, 1, 1]).list()
+        [[1, 1, 2, 3], [1, 1, 3, 2], [1, 2, 1, 3]]
+    """
+    if isinstance(e, (int, Integer)):
+        if e > 0:
+            if not isinstance(k, (int, Integer)):
+                raise TypeError, "k must be a non-negative integer"
+            if k < 0:
+                raise TypeError, "k must be a non-negative integer"
+            return LyndonWords_nk(e, k)
+    elif e in Compositions():
+        return LyndonWords_evaluation(e)
+    
+    raise TypeError, "e must be a positive integer or a composition"
+
+class LyndonWords_evaluation(CombinatorialClass):
+    def __init__(self, e):
+        """
+        TESTS:
+            sage: LW21 = LyndonWords([2,1]); LW21
+            Lyndon words with evaluation [2, 1]
+            sage: LW21 == loads(dumps(LW21))
+            True
+        """
+        self.e = Composition(e)
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(LyndonWords([2,1,1]))
+            'Lyndon words with evaluation [2, 1, 1]'
+        """
+        return "Lyndon words with evaluation %s"%self.e
+
+    def __contains__(self, x):
+        """
+        EXAMPLES:
+            sage: [1,2,1,2] in LyndonWords([2,2])
+            False
+            sage: [1,1,2,2] in LyndonWords([2,2])
+            True
+            sage: all([ lw in LyndonWords([2,1,3,1]) for lw in LyndonWords([2,1,3,1])])
+            True
+        """
+        if x not in necklace.Necklaces(self.e):
+            return False
+        
+        #Check to make sure that x is aperiodic
+        xl = list(x)
+        n = sum(self.e)
+        cyclic_shift = xl[:]
+        for i in range(n - 1):
+            cyclic_shift = cyclic_shift[1:] + cyclic_shift[:1]
+            if cyclic_shift == xl:
+                return False
+
+        return True
+
+    def count(self):
+        """
+        Returns the number of Lyndon words with the
+        evaluation e.
+
+        EXAMPLES:
+            sage: LyndonWords([]).count()
+            0
+            sage: LyndonWords([2,2]).count()
+            1
+            sage: LyndonWords([2,3,2]).count()
+            30
+
+          Check to make sure that the count matches up with the
+          number of Lyndon words generated.
+
+            sage: comps = [[],[2,2],[3,2,7],[4,2]]+Compositions(4).list()
+            sage: lws = [ LyndonWords(comp) for comp in comps]
+            sage: all( [ lw.count() == len(lw.list()) for lw in lws] )
+            True
+
+        """
+        evaluation = self.e
+        le = __builtin__.list(evaluation)
+        if len(evaluation) == 0:
+            return 0
+
+        n = sum(evaluation)
+
+        return sum([moebius(j)*factorial(n/j) / prod([factorial(ni/j) for ni in evaluation]) for j in divisors(gcd(le))])/n
+
+
+    def iterator(self):
+        """
+        An iterator for the Lyndon words with evaluation e.
+
+        EXAMPLES:
+            sage: LyndonWords([1]).list()    #indirect test
+            [[1]]
+            sage: LyndonWords([2]).list()    #indirect test
+            []
+            sage: LyndonWords([3]).list()    #indirect test
+            []
+            sage: LyndonWords([3,1]).list()  #indirect test
+            [[1, 1, 1, 2]]
+            sage: LyndonWords([2,2]).list()  #indirect test
+            [[1, 1, 2, 2]]
+            sage: LyndonWords([1,3]).list()  #indirect test
+            [[1, 2, 2, 2]]
+            sage: LyndonWords([3,3]).list()  #indirect test
+            [[1, 1, 1, 2, 2, 2], [1, 1, 2, 1, 2, 2], [1, 1, 2, 2, 1, 2]]
+            sage: LyndonWords([4,3]).list()  #indirect test
+            [[1, 1, 1, 1, 2, 2, 2],
+             [1, 1, 1, 2, 1, 2, 2],
+             [1, 1, 1, 2, 2, 1, 2],
+             [1, 1, 2, 1, 1, 2, 2],
+             [1, 1, 2, 1, 2, 1, 2]]
+             
+        """
+        if self.e == []:
+            return
+
+        for z in necklace._sfc(self.e, equality=True):
+            yield map(_add_one, z)
+
+
+def _add_one(x):
+    return x+1
+
+class LyndonWords_nk(CombinatorialClass):
+    def __init__(self, n, k):
+        """
+        TESTS:
+            sage: LW23 = LyndonWords(2,3); LW23
+            Lyndon words from an alphabet of size 2 of length 3
+            sage: LW23== loads(dumps(LW23))
+            True
+        """
+        self.n = Integer(n)
+        self.k = Integer(k)
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(LyndonWords(2, 3))
+            'Lyndon words from an alphabet of size 2 of length 3'
+        """
+        return "Lyndon words from an alphabet of size %s of length %s"%(self.n, self.k)
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: LW33 = LyndonWords(3,3)
+            sage: all([lw in LW33 for lw in LW33])
+            True
+        """
+
+        #Get the content of x and create
+        c = filter(lambda x: x!=0, word.evaluation(x))
+
+        #Change x to the "standard form"
+        d = {}
+        for i in x:
+            d[i] = 1
+        temp = [i for i in sorted(d.keys())]
+        new_x = map( lambda i: temp.index(i)+1, x )
+
+        #Check to see if it is in the Lyndon
+        return new_x in LyndonWords_evaluation(c)
+
+    def count(self):
+        """
+        TESTS:
+            sage: [ LyndonWords(3,i).count() for i in range(1, 11) ]
+            [3, 3, 8, 18, 48, 116, 312, 810, 2184, 5880]
+        """
+        if self.k == 0:
+            return 1
+        else:
+            s = 0
+            for d in divisors(self.k):
+                s += moebius(d)*(self.n**(self.k/d))
+        return s/self.k
+
+    def iterator(self):
+        """
+        TESTS:
+           sage: LyndonWords(3,3).list()
+           [[1, 1, 2],
+            [1, 1, 3],
+            [1, 2, 2],
+            [1, 2, 3],
+            [1, 3, 2],
+            [1, 3, 3],
+            [2, 2, 3],
+            [2, 3, 3]]
+        """
+        for c in IntegerVectors(self.k, self.n):
+            cf = filter(lambda x: x != 0, c)
+            nonzero_indices = []
+            for i in range(len(c)):
+                if c[i] != 0:
+                    nonzero_indices.append(i)
+            for lw in LyndonWords_evaluation(cf):
+                yield map(lambda x: nonzero_indices[x-1]+1, lw)
+
+
+def StandardBracketedLyndonWords(n, k):
+    """
+    Returns the combinatorial class of standard bracketed Lyndon
+    words from [1, ..., n] of length k.  These are in one to one
+    correspondence with the Lyndon words and form a basis for
+    the subspace of degree k of the free Lie algebra of rank n.
+
+    EXAMPLES:
+        sage: SBLW33 = StandardBracketedLyndonWords(3,3); SBLW33
+        Standard bracketed Lyndon words from an alphabet of size 3 of length 3  
+        sage: SBLW33.first()
+        [1, [1, 2]]
+        sage: SBLW33.last()
+        [[2, 3], 3]
+        sage: SBLW33.count()
+        8
+        sage: SBLW33.random() #random
+        [2, [2, 3]]
+    """
+    return StandardBracketedLyndonWords_nk(n,k)
+
+class StandardBracketedLyndonWords_nk(CombinatorialClass):
+    def __init__(self, n, k):
+        """
+        TESTS:
+            sage: SBLW = StandardBracketedLyndonWords(3, 2)
+            sage: SBLW == loads(dumps(SBLW))
+            True
+        """
+        self.n = Integer(n)
+        self.k = Integer(k)
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(StandardBracketedLyndonWords(3, 3))
+            'Standard bracketed Lyndon words from an alphabet of size 3 of length 3'
+        """
+        return "Standard bracketed Lyndon words from an alphabet of size %s of length %s"%(self.n, self.k)
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: StandardBracketedLyndonWords(3, 3).count()
+            8
+            sage: StandardBracketedLyndonWords(3, 4).count()
+            18
+        """
+        return LyndonWords_nk(self.n,self.k).count()
+
+    def iterator(self):
+        """
+        EXAMPLES:
+            sage: StandardBracketedLyndonWords(3, 3).list()
+            [[1, [1, 2]],
+             [1, [1, 3]],
+             [[1, 2], 2],
+             [1, [2, 3]],
+             [[1, 3], 2],
+             [[1, 3], 3],
+             [2, [2, 3]],
+             [[2, 3], 3]]
+        """
+        for lw in LyndonWords_nk(self.n, self.k):
+            yield standard_bracketing(lw)
+            
+
+def standard_bracketing(lw):
+    """
+    Returns the standard bracketing of a Lyndon word lw.
+
+    EXAMPLES:
+        sage: import sage.combinat.lyndon_word as lyndon_word
+        sage: map( lyndon_word.standard_bracketing, LyndonWords(3,3) )
+        [[1, [1, 2]],
+         [1, [1, 3]],
+         [[1, 2], 2],
+         [1, [2, 3]],
+         [[1, 3], 2],
+         [[1, 3], 3],
+         [2, [2, 3]],
+         [[2, 3], 3]]
+    """
+    n = max(lw)
+    k = len(lw)
+    
+    if len(lw) == 1:
+        return lw[0]
+        
+    for i in range(1,len(lw)):
+        if lw[i:] in LyndonWords(n,k):
+            return [ standard_bracketing( lw[:i] ), standard_bracketing(lw[i:]) ]
+        
Index: sage/combinat/misc.py
===================================================================
--- sage/combinat/misc.py	(revision 6594)
+++ sage/combinat/misc.py	(revision 6594)
@@ -0,0 +1,222 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+
+class DoublyLinkedList():
+    """
+    A doubly linked list class that provides constant time hiding and unhiding
+    of entries.
+
+    Note that this list's indexing is 1-based.
+    
+    EXAMPLES:
+        sage: dll = sage.combinat.misc.DoublyLinkedList([1,2,3]); dll
+        Doubly linked list of [1, 2, 3]: [1, 2, 3]
+        sage: dll.hide(1); dll
+        Doubly linked list of [1, 2, 3]: [2, 3]
+        sage: dll.unhide(1); dll
+        Doubly linked list of [1, 2, 3]: [1, 2, 3]
+        sage: dll.hide(2); dll
+        Doubly linked list of [1, 2, 3]: [1, 3]
+        sage: dll.unhide(2); dll
+        Doubly linked list of [1, 2, 3]: [1, 2, 3]
+    """
+    def __init__(self, l):
+        """
+        TESTS:
+            sage: dll = sage.combinat.misc.DoublyLinkedList([1,2,3])
+            sage: dll == loads(dumps(dll))
+            True
+        """
+        n = len(l)
+        self.l = l
+        self.next_value = {}
+        self.next_value['begin'] = l[0]
+        self.next_value[l[n-1]] = 'end'
+        for i in xrange(n-1):
+            self.next_value[l[i]] = l[i+1]
+        
+        self.prev_value = {}
+        self.prev_value['end'] = l[-1]
+        self.prev_value[l[0]] = 'begin'
+        for i in xrange(1,n):
+            self.prev_value[l[i]] = l[i-1]        
+
+    def __cmp__(self, x):
+        """
+        TESTS:
+            sage: dll = sage.combinat.misc.DoublyLinkedList([1,2,3])
+            sage: dll2 = sage.combinat.misc.DoublyLinkedList([1,2,3])
+            sage: dll == dll2
+            True
+            sage: dll.hide(1)
+            sage: dll == dll2
+            False
+        """
+        if not isinstance(x, DoublyLinkedList):
+            return -1
+        if self.l != x.l:
+            return -1
+        if self.next_value != x.next_value:
+            return -1
+        if self.prev_value != x.prev_value:
+            return -1
+        return 0
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(sage.combinat.misc.DoublyLinkedList([1,2,3]))
+            'Doubly linked list of [1, 2, 3]: [1, 2, 3]'
+        """
+        return "Doubly linked list of %s: %s"%(self.l, list(self))
+    
+    def __iter__(self):
+        """
+        TESTS:
+            sage: dll = sage.combinat.misc.DoublyLinkedList([1,2,3])
+            sage: list(dll)
+            [1, 2, 3]
+        """
+        j = self.next_value['begin']
+        while j != 'end':
+            yield j
+            j = self.next_value[j]
+
+    def hide(self, i):
+        """
+        TESTS:
+            sage: dll = sage.combinat.misc.DoublyLinkedList([1,2,3])
+            sage: dll.hide(1)
+            sage: list(dll)
+            [2, 3]
+        """
+        self.next_value[self.prev_value[i]] = self.next_value[i]
+        self.prev_value[self.next_value[i]] = self.prev_value[i]
+
+    def unhide(self,i):
+        """
+        TESTS:
+            sage: dll = sage.combinat.misc.DoublyLinkedList([1,2,3])
+            sage: dll.hide(1); dll.unhide(1)
+            sage: list(dll)
+            [1, 2, 3]
+        """
+        self.next_value[self.prev_value[i]] = i
+        self.prev_value[self.next_value[i]] = i
+
+    def head(self):
+        """
+        TESTS:
+            sage: dll = sage.combinat.misc.DoublyLinkedList([1,2,3])
+            sage: dll.head()
+            1
+            sage: dll.hide(1)
+            sage: dll.head()
+            2
+        """
+        return self.next_value['begin']
+    
+    def next(self, j):
+        """
+        TESTS:
+            sage: dll = sage.combinat.misc.DoublyLinkedList([1,2,3])
+            sage: dll.next(1)
+            2
+            sage: dll.hide(2)
+            sage: dll.next(1)
+            3
+        """
+        return self.next_value[j]
+
+    def prev(self, j):
+        """
+        TESTS:
+            sage: dll = sage.combinat.misc.DoublyLinkedList([1,2,3])
+            sage: dll.prev(3)
+            2
+            sage: dll.hide(2)
+            sage: dll.prev(3)
+            1
+        """
+        return self.prev_value[j]
+
+    
+
+def check_integer_list_constraints(l, **kwargs):
+    if 'singleton' in kwargs and kwargs['singleton']:
+        singleton = True
+        result = [ l ]
+        n = sum(l)
+        del kwargs['singleton']
+    else:
+        singleton = False
+        if len(l) > 0:
+            n = sum(l[0])
+            result = l
+        else:
+            return []
+
+    
+    min_part = kwargs.get('min_part', None)
+    max_part = kwargs.get('max_part', None)
+
+    min_length = kwargs.get('min_length', None)
+    max_length = kwargs.get('max_length', None)
+
+    min_slope = kwargs.get('min_slope', None)
+    max_slope = kwargs.get('max_slope', None)
+
+    length = kwargs.get('length', None)
+
+    inner = kwargs.get('inner', None)
+    outer = kwargs.get('outer', None)
+    
+    #Preprocess the constraints
+    if outer is not None:
+        max_length = len(outer)
+        for i in range(max_length):
+            if outer[i] == "inf":
+                outer[i] = n+1
+    if inner is not None:
+        min_length = len(inner)
+   
+    if length is not None:
+        max_length = length
+        min_length = length
+
+    filters = {}
+    filters['length'] = lambda x: len(x) == length
+    filters['min_part'] = lambda x: min(x) >= min_part
+    filters['max_part'] = lambda x: max(x) <= max_part
+    filters['min_length'] = lambda x: len(x) >= min_length
+    filters['max_length'] = lambda x: len(x) <= max_length
+    filters['min_slope'] = lambda x: min([x[i+1]-x[i] for i in
+                                       range(len(x)-1)]+[min_slope+1]) >= min_slope
+    filters['max_slope'] = lambda x: max([x[i+1]-x[i] for i in
+                                       range(len(x)-1)]+[max_slope-1]) <= max_slope
+    filters['outer'] = lambda x: len(outer) >= len(x) and min([outer[i]-x[i] for i in range(len(x))]) >= 0
+    filters['inner'] = lambda x: len(x) >= len(inner) and min([inner[i]-x[i] for i in range(len(inner))]) <= 0
+
+    for key in kwargs:
+        result = filter( filters[key], result )
+
+    if singleton:
+        try:
+            return result[0]
+        except IndexError:
+            return None
+    else:
+        return result
Index: sage/combinat/multichoose_nk.py
===================================================================
--- sage/combinat/multichoose_nk.py	(revision 6439)
+++ sage/combinat/multichoose_nk.py	(revision 6439)
@@ -0,0 +1,100 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from sage.rings.arith import binomial
+import random as rnd
+
+def count(n,k):
+    """
+    Returns the number of multichoices of k things from a list
+    of n things.
+
+    EXAMPLES:
+        sage: multichoose_nk.count(3,2)
+        6
+    """
+    return binomial(n+k-1,k)
+
+def iterator(n,k):
+    """
+    An iterator for all multichoies of k thinkgs from range(n).
+
+    EXAMPLES:
+        sage: [c for c in multichoose_nk.iterator(3,2)]
+        [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
+ 
+    """
+    dif = 0
+    if k == 0:
+        yield []
+        return
+
+    if n < 1+(k-1)*dif:
+        return
+    else:
+        subword = [ i*dif for i in range(k) ]
+
+    yield subword[:]
+    finished = False
+
+    while not finished:    
+        #Find the biggest element that can be increased
+        if subword[-1] < n-1:
+            subword[-1] += 1
+            yield subword[:]
+            continue
+
+        finished = True
+        for i in reversed(range(k-1)):
+            if subword[i]+dif < subword[i+1]:
+                subword[i] += 1
+                #Reset the bigger elements
+                for j in range(1,k-i):
+                    subword[i+j] = subword[i]+j*dif
+                yield subword[:]
+                finished = False
+                break
+
+    return 
+        
+def list(n,k,repitition=False):
+    """
+    Returns a list of all the multichoices of k things from range(n).
+
+    EXAMPLES:
+        sage: multichoose_nk.list(3,2)
+        [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
+
+    """
+
+    return [c for c in iterator(n,k)]
+
+def random(n,k):
+    """
+    Returns a random multichoice of k things from range(n).
+
+    EXAMPLES:
+        sage: multichoose_nk.random(5,2) #random
+        [0,3]
+        sage: multichoose_nk.random(5,2) #random
+        [2,2]   
+    """
+    rng = range(n)
+    r = []
+    for i in range(k):
+        r.append( rnd.choice(rng))
+        
+    r.sort()
+    return r
Index: sage/combinat/necklace.py
===================================================================
--- sage/combinat/necklace.py	(revision 6439)
+++ sage/combinat/necklace.py	(revision 6439)
@@ -0,0 +1,393 @@
+"""
+
+A fast algorithm to generate necklaces with fixed content
+Source 	Theoretical Computer Science archive
+Volume 301 ,  Issue 1-3  (May 2003) table of contents
+Pages: 477 - 489  
+Year of Publication: 2003
+ISSN:0304-3975
+Author 	
+Joe Sawada 	 Department of Computer Science, University of Toronto, 10 King's College Road, Toronto, Ont. Canada M5S 1A4
+Publisher 	
+Elsevier Science Publishers Ltd.   Essex, UK
+
+"""
+
+
+
+    
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+
+from sage.combinat.composition import Composition, Composition_class
+from combinat import CombinatorialClass, CombinatorialObject
+from sage.rings.arith import euler_phi,factorial, divisors, gcd
+from sage.rings.integer import Integer
+from sage.misc.misc import prod
+from sage.combinat.misc import DoublyLinkedList
+import __builtin__
+import itertools
+
+
+
+def Necklaces(e):
+    """
+    Returns the combinatorial class of necklaces with
+    evaluation e.
+
+    EXAMPLES:
+        sage: Necklaces([2,1,1])
+        Necklaces with evaluation [2, 1, 1]
+        sage: Necklaces([2,1,1]).count()
+        3
+        sage: Necklaces([2,1,1]).first()
+        [1, 1, 2, 3]
+        sage: Necklaces([2,1,1]).last()
+        [1, 2, 1, 3]
+        sage: Necklaces([2,1,1]).list()
+        [[1, 1, 2, 3], [1, 1, 3, 2], [1, 2, 1, 3]]
+        
+    """
+    return Necklaces_evaluation(e)
+
+class Necklaces_evaluation(CombinatorialClass):
+    def __init__(self, e):
+        """
+        TESTS:
+            sage: N = Necklaces([2,2,2])
+            sage: N == loads(dumps(N))
+            True
+        """
+        if isinstance(e, Composition_class):
+            self.e = e
+        else:
+            self.e = Composition(e)
+            
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Necklaces([2,1,1]))
+            'Necklaces with evaluation [2, 1, 1]'
+        """
+        return "Necklaces with evaluation %s"%self.e
+
+    def __contains__(self, x):
+        """
+        EXAMPLES:
+            sage: [2,1,2,1] in Necklaces([2,2])
+            False
+            sage: [1,2,1,2] in Necklaces([2,2])
+            True
+            sage: [1,1,2,2] in Necklaces([2,2])
+            True
+            sage: all([ n in Necklaces([2,1,3,1]) for n in Necklaces([2,1,3,1])])
+            True
+        """
+        xl = list(x)
+        n = sum(self.e)
+        e = [0]*len(self.e)
+        if len(xl) != n:
+            return False
+
+        #Check to make sure xl is a list of integers
+        for i in xl:
+            if not isinstance(i, (int, Integer)):
+                return False
+            if i <= 0:
+                return False
+            if i > n:
+                return False
+            e[i-1] += 1
+
+        #Check to make sure the evaluation is the same
+        if e != self.e:
+            return False
+
+        #Check to make sure that x is lexicographically less
+        #than all of its cyclic shifts
+        cyclic_shift = xl[:]
+        for i in range(n - 1):
+            cyclic_shift = cyclic_shift[1:] + cyclic_shift[:1]
+            if cyclic_shift < xl:
+                return False
+
+        return True
+    
+    def count(self):
+        """
+        Returns the number of integer necklaces with the
+        evaluation e.
+
+        EXAMPLES:
+            sage: Necklaces([]).count()
+            0
+            sage: Necklaces([2,2]).count()
+            2
+            sage: Necklaces([2,3,2]).count()
+            30
+
+          Check to make sure that the count matches up with the
+          number of Lyndon words generated.
+
+            sage: comps = [[],[2,2],[3,2,7],[4,2]]+Compositions(4).list()
+            sage: ns = [ Necklaces(comp) for comp in comps]
+            sage: all( [ n.count() == len(n.list()) for n in ns] )
+            True       
+        """
+        evaluation = self.e
+        le = __builtin__.list(evaluation)
+        if len(evaluation) == 0:
+            return 0
+
+        n = sum(evaluation)
+
+        return sum([euler_phi(j)*factorial(n/j) / prod([factorial(ni/j) for ni in evaluation]) for j in divisors(gcd(le))])/n
+
+
+    def iterator(self):
+        """
+        An iterator for the integer necklaces iwth evaluation e.
+
+        EXAMPLES:
+            sage: Necklaces([]).list()    #indirect test
+            []
+            sage: Necklaces([1]).list()   #indirect test
+            [[1]]
+            sage: Necklaces([2]).list()   #indirect test
+            [[1, 1]]
+            sage: Necklaces([3]).list()   #indirect test
+            [[1, 1, 1]]
+            sage: Necklaces([3,3]).list() #indirect test
+            [[1, 1, 1, 2, 2, 2],
+             [1, 1, 2, 1, 2, 2],
+             [1, 1, 2, 2, 1, 2],
+             [1, 2, 1, 2, 1, 2]]
+            sage: Necklaces([2,1,3]).list() #indirect test
+            [[1, 1, 2, 3, 3, 3],
+             [1, 1, 3, 2, 3, 3],
+             [1, 1, 3, 3, 2, 3],
+             [1, 1, 3, 3, 3, 2],
+             [1, 2, 1, 3, 3, 3],
+             [1, 2, 3, 1, 3, 3],
+             [1, 2, 3, 3, 1, 3],
+             [1, 3, 1, 3, 2, 3],
+             [1, 3, 1, 3, 3, 2],
+             [1, 3, 2, 1, 3, 3]]
+        """
+        if self.e == []:
+            return 
+        for z in _sfc(self.e):
+            yield map(lambda x: x+1, z)
+
+            
+
+##############################
+#Fast Fixed Content Algorithm#
+##############################
+def _ffc(content, equality=False):
+    e = list(content)
+    a = [len(e)-1]*sum(e)
+    r = [0] * sum(e)
+    a[0] = 0
+    e[0] -= 1
+    k = len(e)
+    l = range(k)
+    
+    rng_k = range(k)
+    rng_k.reverse()
+    dll = DoublyLinkedList(rng_k)
+    if e[0] == 0:
+        dll.hide(0)
+        
+    j = dll.head()
+    for x in _fast_fixed_content(a, e, 2, 1, k, r, 2, dll, equality=equality):
+        yield x
+    
+def _fast_fixed_content(a, content, t, p, k, r, s, dll, equality=False):
+    n = len(a)
+    if content[k-1] == n - t + 1:
+        if content[k-1] == r[t-p-1]:
+            if equality:
+                if n == p:
+                    yield a
+            else:
+                if n % p == 0:
+                    yield a
+        elif content[k-1] > r[t-p-1]:
+            yield a
+    elif content[0] != n-t+1:
+        j = dll.head()
+        sp = s
+        while j != 'end' and j >= a[t-p-1]:
+            #print s, j
+            r[s-1] = t-s
+            a[t-1] = j
+            content[j] -= 1
+
+            if content[j] == 0:
+                dll.hide(j)
+
+            if j != k-1:
+                sp = t+1
+                
+            if j == a[t-p-1]:
+                for x in _fast_fixed_content(a[:], content, t+1, p+0, k, r, sp, dll, equality=equality):
+                    yield x
+            else:
+                for x in _fast_fixed_content(a[:], content, t+1, t+0, k, r, sp, dll, equality=equality):
+                    yield x
+
+            if content[j] == 0:
+                dll.unhide(j)
+                
+            content[j] += 1
+            j = dll.next(j)
+        a[t-1] = k-1
+    return
+
+
+################################
+# List Fixed Content Algorithm #
+################################
+def _lfc(content, equality=False):
+    content = list(content)
+    a = [0]*sum(content)
+    content[0] -= 1
+    k = len(content)
+    l = range(k)
+
+    rng_k = range(k)
+    rng_k.reverse()
+    dll = DoublyLinkedList(rng_k)
+
+    if content[0] == 0:
+        dll.hide(0)
+
+    j = dll.head()
+    for z in _list_fixed_content(a, content, 2, 1, k, dll, equality=equality):
+        yield z
+
+def _list_fixed_content(a, content, t, p, k, dll, equality=False):
+    n = len(a)
+    if t > n:
+        if equality:
+            if n == p:
+                yield a
+        else:
+            if n % p == 0:
+                yield a
+    else:
+        j = dll.head()
+        while j != 'end' and j >= a[t-p-1]:
+            a[t-1] = j
+            content[j] -= 1
+
+            if content[j] == 0:
+                dll.hide(j)
+                
+            if j == a[t-p-1]:
+                for z in _list_fixed_content(a[:], content[:], t+1, p+0, k, dll, equality=equality):
+                    yield z
+            else:
+                for z in _list_fixed_content(a[:], content[:], t+1, t+0, k, dll, equality=equality):
+                    yield z
+
+            if content[j] == 0:
+                dll.unhide(j)
+                
+            content[j] += 1
+            j = dll.next(j)
+                
+
+
+################################
+#Simple Fixed Content Algorithm#
+################################
+def _sfc(content, equality=False):
+    """
+    TESTS:
+        sage: import sage.combinat.necklace as necklace
+        sage: list(necklace._sfc([3,3]))
+        [[0, 0, 0, 1, 1, 1],
+         [0, 0, 1, 0, 1, 1],
+         [0, 0, 1, 1, 0, 1],
+         [0, 1, 0, 1, 0, 1]]
+    """
+    content = list(content)
+    a = [0]*sum(content)
+    content[0] -= 1
+    k = len(content)
+    return _simple_fixed_content(a, content, 2, 1, k, equality=equality)
+
+def _simple_fixed_content(a, content, t, p, k, equality=False):
+    n = len(a)
+    if t > n:
+        if equality:
+            if n == p:
+                yield a
+        else:
+            if n % p == 0:
+                yield a
+    else:
+        r = range(a[t-p-1],k)
+        for j in r:
+            if content[j] > 0:
+                a[t-1] = j
+                content[j] -= 1
+                if j == a[t-p-1]:
+                    for z in _simple_fixed_content(a[:], content, t+1, p+0, k, equality=equality):
+                        yield z
+                else:
+                    for z in _simple_fixed_content(a[:], content, t+1, t+0, k, equality=equality):
+                        yield z
+                content[j] += 1
+            
+
+def _lyn(w):
+    """
+    Returns the length of the longest prefix of w that
+    is a Lyndon word.
+
+    From Theorem 1.
+
+    EXAMPLES:
+        sage: import sage.combinat.necklace as necklace
+        sage: necklace._lyn([0,1,1,0,0,1,2])
+        3
+        sage: necklace._lyn([0,0,0,1])
+        4
+        sage: necklace._lyn([2,1,0,0,2,2,1])
+        1
+    """
+
+    p = 1
+    k = max(w)+1
+    for i in range(1, len(w)):
+        b = w[i]
+        a = w[:i]
+        #print "a, b, a[i-p]:", a, b, a[i-p]
+        if b < a[i-p] or b > k-1:
+            return p
+        elif b == a[i-p]:
+            pass
+        else:
+            p = i+1
+    return p
+        
+
+
+
Index: sage/combinat/partition.py
===================================================================
--- sage/combinat/partition.py	(revision 6959)
+++ sage/combinat/partition.py	(revision 6959)
@@ -0,0 +1,1830 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from sage.interfaces.all import gap, maxima
+from sage.rings.all import QQ, RR, ZZ
+from sage.misc.all import prod, sage_eval
+from sage.rings.arith import factorial, gcd
+from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
+from sage.calculus.calculus import Function_ceil, log, SymbolicVariable, Function_sinh
+from sage.calculus.functional import diff
+import sage.combinat.generator as generator
+import sage.combinat.misc as misc
+import sage.combinat.skew_partition
+from sage.rings.integer import Integer
+from UserList import UserList
+import __builtin__
+from sage.functions.constants import pi
+ceil = Function_ceil()
+sinh = Function_sinh()
+from combinat import CombinatorialClass, CombinatorialObject, number_of_partitions
+import partitions as partitions_ext
+from sage.libs.all import pari
+
+def Partition(l=None, exp=None, core_and_quotient=None):
+    """
+    Returns a partition object.
+
+    EXAMPLES:
+        sage: Partition(exp=[2,1,1])
+        [3, 2, 1, 1]
+        sage: Partition(core_and_quotient=([2,1], [[2,1],[3],[1,1,1]]))
+        [11, 5, 5, 3, 2, 2, 2]
+        sage: Partition([3,2,1])
+        [3, 2, 1]
+    """
+    number_of_arguments = 0
+    for arg in ['l', 'exp', 'core_and_quotient']:
+        if eval(arg) is not None:
+            number_of_arguments += 1
+
+    if number_of_arguments != 1:
+        raise ValueError, "you must specify exactly one argument"
+
+    if l is not None:
+        if sum(l) == 0:
+            l = []
+        return Partition_class(l)
+    elif exp is not None:
+        return from_exp(exp)
+    else:
+        return from_core_and_quotient(*core_and_quotient)
+    
+
+def from_exp(a):
+    """
+    Returns a partition from its list of multiplicities.
+
+    EXAMPLES:
+        sage: partition.from_exp([1,2,1])
+        [3, 2, 2, 1]
+    """
+
+    p = []
+    for i in reversed(range(len(a))):
+        p += [i+1]*a[i]
+
+    return Partition(p)
+
+
+    
+def from_core_and_quotient(core, quotient):
+    """
+    Returns a partition from its r-core and r-quotient.
+
+    Algorithm from mupad-combinat.
+
+    EXAMPLES:
+        sage: partition.from_core_and_quotient([2,1], [[2,1],[3],[1,1,1]])
+        [11, 5, 5, 3, 2, 2, 2]
+    """
+    length = len(quotient)
+    k = length*max( [ceil(len(core)/length),len(core)] + [len(q) for q in quotient] ) + length
+    v = [ core[i]-(i+1)+1 for i in range(len(core))] + [ -i + 1 for i in range(len(core)+1,k+1) ]
+    w = [ filter(lambda x: (x-i) % length == 0, v) for i in range(1, length+1) ]
+    new_w = []
+    for i in range(length):
+        new_w += [ w[i][j] + length*quotient[i][j] for j in range(len(quotient[i]))]
+        new_w += [ w[i][j] for j in range(len(quotient[i]), len(w[i])) ]
+    new_w.sort()
+    new_w.reverse()
+    return filter(lambda x: x != 0, [new_w[i-1]+i-1 for i in range(1, len(new_w)+1)])
+
+    
+class Partition_class(CombinatorialObject):
+    def ferrers_diagram(self):
+        """
+        Return the Ferrers diagram of pi.
+
+        INPUT:
+            pi -- a partition, given as a list of integers. 
+
+        EXAMPLES:
+            sage: print Partition([5,5,2,1]).ferrers_diagram()
+            *****
+            *****
+            **
+            *        
+            sage: pi = Partitions(10).list()[11] ## [6,1,1,1,1]
+            sage: print pi.ferrers_diagram()
+            ******
+            *
+            *
+            *
+            *
+            sage: pi = Partitions(10).list()[8] ## [6, 3, 1]
+            sage: print pi.ferrers_diagram()
+            ******
+            ***
+            *
+        """
+        return '\n'.join(['*'*p for p in self])
+
+
+    def __div__(self, p):
+        """
+        Returns the skew partition self/p.
+
+        EXAMPLES:
+            sage: p = Partition([3,2,1])
+            sage: p/[1,1]
+            [[3, 2, 1], [1, 1]]
+            sage: p/[3,2,1]
+            [[3, 2, 1], [3, 2, 1]]
+            
+        """
+        if not self.dominates(Partition_class(p)):
+            raise ValueError, "the partition must dominate p"
+
+        return sage.combinat.skew_partition.SkewPartition([self[:], p])
+        
+    def power(self,k):
+        """
+        partition_power( pi, k ) returns the partition corresponding to the 
+        $k$-th power of a permutation with cycle structure pi 
+        (thus describes the powermap of symmetric groups).
+
+        Wraps GAP's PowerPartition.
+
+        EXAMPLES:
+            sage: p = Partition([5,3])
+            sage: p.power(1)
+            [5, 3]
+            sage: p.power(2)
+            [5, 3]
+            sage: p.power(3)
+            [5, 1, 1, 1]
+            sage: p.power(4)
+            [5, 3]
+
+         Now let us compare this to the power map on $S_8$:
+
+            sage: G = SymmetricGroup(8)
+            sage: g = G([(1,2,3,4,5),(6,7,8)])
+            sage: g
+            (1,2,3,4,5)(6,7,8)
+            sage: g^2
+            (1,3,5,2,4)(6,8,7)
+            sage: g^3
+            (1,4,2,5,3)
+            sage: g^4
+            (1,5,4,3,2)(6,7,8)
+
+        """
+        ans=gap.eval("PowerPartition(%s,%s)"%(self,ZZ(k)))
+        return Partition_class(eval(ans))
+
+    def next(self):
+        """
+        Returns the partition that lexicographically follows
+        the partition p.  If p is the last partition, then
+        it returns False.
+
+        EXAMPLES:
+            sage: Partition([4]).next()
+            [3, 1]
+            sage: Partition([1,1,1,1]).next()
+            False
+        """
+        p = self
+        n = 0
+        m = 0
+        for i in p:
+            n += i
+            m += 1
+        
+        next_p = p[:] + [1]*(n - len(p))
+
+        #Check to see if we are at the last (all ones) partition
+        if p == [1]*n:
+            return False
+
+        #
+        #If we are not, then run the ZS1 algorithm.
+        #
+
+        #Let h be the number of non-one  entries in the
+        #partition
+        h = 0 
+        for i in next_p:
+            if i != 1:
+                h += 1
+
+        if next_p[h-1] == 2:
+            m += 1
+            next_p[h-1] = 1
+            h -= 1
+        else:
+            r = next_p[h-1] - 1
+            t = m - h + 1
+            next_p[h-1] = r
+
+            while t >= r :
+                h += 1
+                next_p[h-1] = r
+                t -= r
+
+            if t == 0:
+                m = h
+            else:
+                m = h + 1
+                if t > 1:
+                    h += 1
+                    next_p[h-1] = t
+
+        return Partition_class(next_p[:m])
+
+    def size(self):
+        """
+        Returns the size of partition p.
+
+        EXAMPLES:
+            sage: Partition([2,2]).size()
+            4
+            sage: Partition([3,2,1]).size()
+            6
+        """
+        return sum(self)
+
+    def sign(self):
+        r"""
+        partition_sign( pi ) returns the sign of a permutation with cycle structure 
+        given by the partition pi.
+
+        This function corresponds to a homomorphism from the symmetric group 
+        $S_n$ into the cyclic group of order 2, whose kernel is exactly the 
+        alternating group $A_n$. Partitions of sign $1$ are called {\it even partitions} 
+        while partitions of sign $-1$ are called {\it odd}.
+
+        Wraps GAP's SignPartition.
+
+        EXAMPLES:
+            sage: Partition([5,3]).sign()
+            1
+            sage: Partition([5,2]).sign()
+            -1
+
+        {\it Zolotarev's lemma} states that the Legendre symbol
+        $ \left(\frac{a}{p}\right)$ for an integer $a \pmod p$ ($p$ a prime number), 
+        can be computed as sign(p_a), where sign denotes the sign of a permutation
+        and p_a the permutation of the residue classes $\pmod p$ induced by 
+        modular multiplication by $a$, provided $p$ does not divide $a$.
+
+        We verify this in some examples.
+
+            sage: F = GF(11)
+            sage: a = F.multiplicative_generator();a
+            2
+            sage: plist = [int(a*F(x)) for x in range(1,11)]; plist
+            [2, 4, 6, 8, 10, 1, 3, 5, 7, 9]
+
+        This corresponds ot the permutation (1, 2, 4, 8, 5, 10, 9, 7, 3, 6)
+        (acting the set $\{1,2,...,10\}$) and to the partition [10].
+
+            sage: p = PermutationGroupElement('(1, 2, 4, 8, 5, 10, 9, 7, 3, 6)')
+            sage: p.sign()
+            -1
+            sage: Partition([10]).sign()
+            -1
+            sage: kronecker_symbol(11,2)
+            -1
+
+        Now replace $2$ by $3$:
+
+            sage: plist = [int(F(3*x)) for x in range(1,11)]; plist
+            [3, 6, 9, 1, 4, 7, 10, 2, 5, 8]
+            sage: range(1,11)
+            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+            sage: p = PermutationGroupElement('(3,4,8,7,9)')
+            sage: p.sign()
+            1
+            sage: kronecker_symbol(3,11)
+            1
+            sage: Partition([5,1,1,1,1,1]).sign()
+            1
+
+        In both cases, Zolotarev holds.
+
+        REFERENCES:
+            http://en.wikipedia.org/wiki/Zolotarev's_lemma
+        """
+        ans=gap.eval("SignPartition(%s)"%(self))
+        return sage_eval(ans)
+
+
+    def up(self):
+        r"""
+        Returns a generator for partitions that can be obtained from pi
+        by adding a box.
+
+        EXAMPLES:
+            sage: [p for p in Partition([2,1,1]).up()]
+            [[3, 1, 1], [2, 2, 1], [2, 1, 1, 1]]
+            sage: [p for p in Partition([3,2]).up()]
+            [[4, 2], [3, 3], [3, 2, 1]]
+        """
+        p = self
+        previous = p[0] + 1
+        for i, current in enumerate(p):
+            if current < previous:
+                yield Partition(p[:i] + [ p[i] + 1 ] + p[i+1:])
+            previous = current
+        else:
+            yield Partition(p + [1])
+
+    def up_list(self):
+        """
+        Returns a list of the partitions that can be formed from the partition
+        p by adding a box.
+
+        EXAMPLES:
+            sage: Partition([2,1,1]).up_list()
+            [[3, 1, 1], [2, 2, 1], [2, 1, 1, 1]]
+            sage: Partition([3,2]).up_list()
+            [[4, 2], [3, 3], [3, 2, 1]]
+        """
+        return [p for p in self.up()]
+
+    def down(self):
+        r"""
+        Returns a generator for partitions that can be obtained from
+        p by removing a box.
+
+        EXAMPLES:
+            sage: [p for p in Partition([2,1,1]).down()]
+            [[1, 1, 1], [2, 1]]
+            sage: [p for p in Partition([3,2]).down()]
+            [[2, 2], [3, 1]]
+            sage: [p for p in Partition([3,2,1]).down()]
+            [[2, 2, 1], [3, 1, 1], [3, 2]]
+        """
+        p = self
+        for i in range(len(p)-1):
+            if p[i] > p[i+1]:
+                yield Partition(p[:i] + [ p[i]-1 ] + p[i+1:])
+
+        last = p[-1]
+        if last == 1:
+            yield Partition(p[:-1])
+        else:
+            yield Partition(p[:-1] + [ p[-1] - 1 ])
+
+
+    def down_list(self):
+        """
+        Returns a list of the partitions that can be obtained from
+        the partition p by removing a box.
+
+        EXAMPLES:
+            sage: Partition([2,1,1]).down_list()
+            [[1, 1, 1], [2, 1]]
+            sage: Partition([3,2]).down_list()
+            [[2, 2], [3, 1]]
+            sage: Partition([3,2,1]).down_list()
+            [[2, 2, 1], [3, 1, 1], [3, 2]]
+        """
+        return [p for p in self.down()]
+
+    def dominates(self, p2):
+        r"""
+        Returns True if partition p1 dominates partitions p2. Otherwise,
+        it returns False.
+
+        EXAMPLES:
+            sage: p = Partition([3,2])
+            sage: p.dominates([3,1])
+            True
+            sage: p.dominates([2,2])
+            True
+            sage: p.dominates([2,1,1])
+            False
+            sage: p.dominates([3,3])
+            False
+        """
+        p1 = self
+        sum1 = 0
+        sum2 = 0
+        if len(p2) > len(p1):
+            return False
+        for i in range(max(len(p1), len(p2))):
+            if i < len(p1):
+                sum1 += p1[i]
+            if i < len(p2):
+                sum2 += p2[i]
+            if sum2 > sum1:
+                return False
+            sum1 = 0
+            sum2 = 0
+        return True
+
+    def conjugate(self):
+        """
+        conjugate() returns the ``conjugate'' (also called 
+        ``associated'' in the literature) partition of the partition pi which is 
+        obtained by transposing the corresponding Ferrers diagram.
+
+        EXAMPLES:
+            sage: Partition([2,2]).conjugate()
+            [2, 2]
+            sage: Partition([6,3,1]).conjugate()
+            [3, 2, 2, 1, 1, 1]
+            sage: print Partition([6,3,1]).ferrers_diagram()
+            ******
+            ***
+            *
+            sage: print Partition([6,3,1]).conjugate().ferrers_diagram()
+            ***
+            **
+            **
+            *
+            *
+            *
+
+        """
+        p = self
+        if p == []:
+            return Partition([])
+        else:
+            l = len(p)
+            conj =  [l]*p[l-1]
+            for i in range(2,l+1):
+                conj += [l-i+1]*(p[l-i] - p[l-i+1])
+
+            return Partition(conj)
+
+
+    def associated(self):
+        """
+        An alias for partition.conjugate(pi).
+
+        EXAMPLES:
+            sage: Partition([4,1,1]).associated()
+            [3, 1, 1, 1]
+            sage: Partition([4,1,1]).conjugate()
+            [3, 1, 1, 1]
+            sage: Partition([5,4,2,1,1,1]).associated().associated()
+            [5, 4, 2, 1, 1, 1]
+        """
+
+        return self.conjugate()
+
+    def arm(self, i, j):
+        """
+        Returns the arm of cell (i,j) in partition p.  The arm of cell (i,j)
+        is the number of boxes that appear to the right of cell (i,j).
+        Note that i and j are 0-based indices.
+
+        EXAMPLES:
+            sage: p = Partition([2,2,1])
+            sage: p.arm(0, 0)
+            1
+            sage: p.arm(0, 1)
+            0
+            sage: p.arm(2, 0)
+            0        
+            sage: Partition([3,3]).arm(0, 0)
+            2
+        """
+        p = self
+        if i < len(p) and j < p[i]:
+            return p[i]-(j+1)
+        else:
+            #Error: invalid coordinates
+            pass
+
+    def arm_lengths(self):
+        """
+        Returns a tableau of shape p where each box is filled its arm.
+
+        EXAMPLES: 
+            sage: Partition([2,2,1]).arm_lengths()
+            [[1, 0], [1, 0], [0]]
+            sage: Partition([3,3]).arm_lengths()
+            [[2, 1, 0], [2, 1, 0]]
+        """
+        p = self
+        return [[p[i]-(j+1) for j in range(p[i])] for i in range(len(p))]
+
+
+    def leg(self, i, j):
+        """
+        Returns the leg of box (i,j) in partition p. The leg of box (i,j)
+        is defined to be the number of boxes below it in partition p.
+
+
+        EXAMPLES:
+            sage: p = Partition([2,2,1])
+            sage: p.leg(0, 0)
+            2
+            sage: p.leg(0,1)
+            1
+            sage: p.leg(2,0)
+            0        
+            sage: Partition([3,3]).leg(0, 0)
+            1        
+        """
+       
+        conj = self.conjugate()
+        if j < len(conj) and i < conj[j]:
+            return conj[j]-(i+1)
+        else:
+            #Error: invalid coordinates
+            pass
+
+    def leg_lengths(self):
+        """
+        Returns a tableau of shape p with each box filled in with
+        its leg.
+
+        EXAMPLES:
+            sage: Partition([2,2,1]).leg_lengths()
+            [[2, 1], [1, 0], [0]]
+            sage: Partition([3,3]).leg_lengths()
+            [[1, 1, 1], [0, 0, 0]]
+        """
+        p = self
+        conj = p.conjugate()
+        return [[conj[j]-(i+1) for j in range(p[i])] for i in range(len(p))]
+
+    def hook(self, i, j):
+        """
+        Returns the hook of box (i,j) in the partition p.  The hook of box
+        (i,j) is defined to be one more than the sum of number of boxes
+        to the right and the number of boxes below.
+
+        EXAMPLES:
+            sage: p = Partition([2,2,1])
+            sage: p.hook(0, 0)
+            4
+            sage: p.hook(0, 1)
+            2
+            sage: p.hook(2, 0)
+            1        
+            sage: Partition([3,3]).hook(0, 0)
+            4        
+        """
+        return self.leg(i,j)+self.arm(i,j)+1
+
+
+    def hook_lengths(self):
+        r"""
+        Returns a tableau of shape pi with the boxes filled in with the
+        hook lengths
+
+        In each box, put the sum of one plus the number of boxes horizontally to the right
+        and vertically below the box (the hook length).
+
+
+        For example, consider the partition [3,2,1] of 6 with Ferrers Diagram
+        * * *
+        * *
+        *
+        When we fill in the boxes with the hook lengths, we obtain
+        5 3 1
+        3 1
+        1
+
+        EXAMPLES:
+            sage: Partition([2,2,1]).hook_lengths()
+            [[4, 2], [3, 1], [1]]
+            sage: Partition([3,3]).hook_lengths()
+            [[4, 3, 2], [3, 2, 1]]
+            sage: Partition([3,2,1]).hook_lengths()
+            [[5, 3, 1], [3, 1], [1]]
+            sage: Partition([2,2]).hook_lengths()
+            [[3, 2], [2, 1]]
+            sage: Partition([5]).hook_lengths()
+            [[5, 4, 3, 2, 1]]
+
+
+        REFERENCES:
+            http://mathworld.wolfram.com/HookLengthFormula.html
+        """
+        p = self
+        conj = p.conjugate()
+        return [[p[i]-(i+1)+conj[j]-(j+1)+1 for j in range(p[i])] for i in range(len(p))]
+
+
+    def weighted_size(self):
+        """
+        Returns sum([i*p[i] for i in range(len(p))]).
+
+        EXAMPLES:
+            sage: Partition([2,2,1]).weighted_size()
+            9
+            sage: Partition([3,3]).weighted_size()
+            9
+        """
+        p = self
+        return sum([(i+1)*p[i] for i in range(len(p))])
+
+
+    def to_exp(self, k=0):
+        """
+        Return a list of the multiplicities of the parts of a partition.
+
+        EXAMPLES:
+            sage: Partition([3,2,2,1]).to_exp()
+            [0, 1, 2, 1]
+        """
+        p = self
+        if len(p) > 0:
+            k = max(k, p[0])
+        a = [ 0 ] * (k+1)
+        for i in p:
+            a[i] += 1
+        return a
+
+    def evaluation(self):
+        """
+        Returns the evaluation of the partition.
+
+        EXAMPLES:
+            sage: Partition([4,3,1,1]).evaluation()
+            [0, 2, 0, 1, 1]
+        """
+        return self.to_exp()
+
+    def centralizer_size(self, t=0, q=0):
+        """
+        Returns the size of the centralizer of any permuation of cycle type p.
+
+        EXAMPLES:
+            sage: Partition([2,2,1]).centralizer_size()
+            8
+            sage: Partition([2,2,2]).centralizer_size()
+            48 
+
+        REFERENCES:
+            Kerber, A. 'Algebraic Combintorics via Finite Group Action', 1.3 p24
+        """
+        p = self
+        a = p.to_exp()
+        size = prod([i**a[i]*factorial(a[i]) for i in range(1, len(a))])
+        size *= prod( [ (1-q**p[i])/(1-t**p[i]) for i in range(len(p)) ] )
+
+        return size
+
+
+    def conjugacy_class_size(self):
+        """
+        Returns the size of the conjugacy class of the symmetric group
+        indexed by the partition p.
+
+        EXAMPLES:
+            sage: Partition([2,2,2]).conjugacy_class_size()
+            15
+            sage: Partition([2,2,1]).conjugacy_class_size()
+            15
+            sage: Partition([2,1,1]).conjugacy_class_size() 
+            6
+
+
+        REFERENCES:
+            Kerber, A. 'Algebraic Combinatorics via Finite Group Action' 1.3 p24
+        """
+        
+        return factorial(sum(self))/self.centralizer_size()
+
+
+    def corners(self):
+        """
+        Returns a list of the corners of the partitions.  These are the
+        positions where we can remove a box.
+
+        EXAMPLES:
+            sage: Partition([3,2,1]).corners()
+            [[0, 2], [1, 1], [2, 0]]
+            sage: Partition([3,3,1]).corners()
+            [[1, 2], [2, 0]]
+
+        """
+        p = self
+        if p == []:
+            return []
+
+        lcors = [[0,p[0]-1]]
+        nn = len(p)
+        if nn == 1:
+            return lcors
+
+        lcors_index = 0
+        for i in range(1, nn):
+            if p[i] == p[i-1]:
+                lcors[lcors_index][0] += 1
+            else:
+                lcors.append([i,p[i]-1])
+                lcors_index += 1
+
+        return lcors
+
+
+    def outside_corners(self):
+        """
+        Returns a list of the positions where we can add a box so
+        that the shape is still a partition.
+
+        EXAMPLES:
+            sage: Partition([2,2,1]).outside_corners()
+            [[0, 2], [2, 1], [3, 0]]
+            sage: Partition([2,2]).outside_corners()
+            [[0, 2], [2, 0]]
+            sage: Partition([6,3,3,1,1,1]).outside_corners() 
+            [[0, 6], [1, 3], [3, 1], [6, 0]]
+
+        """
+        p = self
+        res = [ [0, p[0]] ]        
+        for i in range(1, len(p)):
+            if p[i-1] != p[i]:
+                res.append([i,p[i]])
+        res.append([len(p), 0])
+                
+        return res
+
+    def r_core(self, length):
+        """
+        Returns the r-core of the partition p.
+
+        EXAMPLES:
+            sage: Partition([6,3,2,2]).r_core(3)
+            [2, 1, 1]
+        """
+        p = self
+        #Normalize the length
+        remainder = len(p) % length
+        part = p[:] + [0]*remainder
+
+        #Add the canonical vector to the partition
+        part = [part[i-1] + len(part)-i for i in range(1, len(part)+1)]
+
+        for e in range(length):
+            k = e
+            for i in reversed(range(1,len(part)+1)):
+                if part[i-1] % length == e:
+                    part[i-1] = k
+                    k += length
+        part.sort()
+        part.reverse()
+
+        #Remove the canonical vector
+        part = [part[i-1]-len(part)+i for i in range(1, len(part)+1)]
+        #Select the r-core
+        return filter(lambda x: x != 0, part)
+
+    def r_quotient(self, length):
+        """
+        Returns the r-quotient of the partition p.
+
+        EXAMPLES:
+            sage: Partition([7,7,5,3,3,3,1]).r_quotient(3) #[[2], [1], [2, 2, 2]]?
+            [[1], [2, 2, 2], [2]]
+        """
+        p = self
+        #Normalize the length
+        remainder = len(p) % length
+        part = p[:] + [0]*remainder
+
+
+        #Add the canonical vector to the partition
+        part = [part[i-1] + len(part)-i for i in range(1, len(part)+1)]
+
+        result = [None]*length
+
+        for e in range(length):
+            k = e
+            tmp = []
+            for i in reversed(range(len(part))):
+                if part[i] % length == e:
+                    tmp.append((part[i]-k)/length)
+                    k += length
+
+            a = filter(lambda x: x != 0, tmp)
+            a.reverse()
+            result[e] = a
+
+        return result
+
+
+    def remove_box(self, i, j = None):
+        """
+        Returns the partiton obtained by removing a box at the end of row i.
+
+        EXAMPLES:
+            sage: Partition([2,2]).remove_box(1)
+            [2, 1]
+            sage: Partition([2,2,1]).remove_box(2)
+            [2, 2]
+            sage: #Partition([2,2]).remove_box(0)
+            
+            sage: Partition([2,2]).remove_box(1,1)
+            [2, 1]
+            sage: #Partition([2,2]).remove_box(1,0)
+        """
+
+        if i >= len(self):
+            raise ValueError, "i must be less than the length of the partition"
+
+        if j is None:
+            j = self[i] - 1
+            
+        if [i,j] not in self.corners():
+            raise ValueError, "[%d,%d] is not a corner of the partition" % (i,j)
+
+        if self[i] == 1:
+            return Partition(self[:-1])
+        else:
+            return Partition(self[:i] + [ self[i:i+1][0] - 1 ] + self[i+1:])
+
+
+
+    def k_skew(self, k):
+        r"""
+        Returns the k-skew partition.
+
+        The k-skew diagram of a k-bounded partition is the skew diagram denoted
+        $\lambda/^k$ satisfying the conditions:
+        (i) row i of $\lambda/^k$ has length $\lambda_i$
+        (ii) no cell in $\lambda/^k$ has hook-length exceeding k
+        (iii) every square above the diagram of $\lambda/^k$ has hook
+        length exceeding k.
+
+        REFERENCES:
+            Lapointe, L. and Morse, J. 'Order Ideals in Weak Subposets of Young's Lattice
+                and Associated Unimodality Conjectures'
+        
+        EXAMPLES:
+            sage: p = Partition([4,3,2,2,1,1])
+            sage: p.k_skew(4)
+            [[9, 5, 3, 2, 1, 1], [5, 2, 1]]
+        """
+
+        if len(self) == 0:
+            return sage.combinat.skew_partition.SkewPartition([[],[]])
+
+        if self[0] > k:
+            raise ValueError, "the partition must be %d-bounded" % k
+
+        #Find the k-skew diagram of the partition formed
+        #by removing the first row
+        s = Partition(self[1:]).k_skew(k)
+        
+        s_inner = s.inner()
+        s_outer = s.outer()
+        s_conj_rl = s.conjugate().row_lengths()
+        
+        #Find the leftmost column with less than
+        # or equal to kdiff boxes
+        kdiff = k - self[0]
+        
+        if s_outer == []:
+            spot = 0
+        else:
+            spot = s_outer[0]
+
+        for i in range(len(s_conj_rl)):
+            if s_conj_rl[i] <= kdiff:
+                spot = i
+                break
+
+        outer = [ self[0] + spot ] + s_outer[:]
+        if spot > 0:
+            inner = [ spot ] + s_inner[:]
+        else:
+            inner = s_inner[:]
+
+        return sage.combinat.skew_partition.SkewPartition([outer, inner])
+
+        
+    def k_conjugate(self, k):
+        """
+        Returns the k-conjugate of the partition.
+
+        The k-conjugate is the partition that is given by the columns
+        of the k-skew diagram of the partition.
+
+        EXAMPLES:
+            sage: p = Partition([4,3,2,2,1,1])
+            sage: p.k_conjugate(4)
+            [3, 2, 2, 1, 1, 1, 1, 1, 1]
+        """
+        return Partition(self.k_skew(k).conjugate().row_lengths())
+        
+    def parent(self):
+        """
+        Returns the combinatorial class of partitions of
+        sum(self).
+
+        EXAMPLES:
+            sage: Partition([3,2,1]).parent()
+            Partitions of the integer 6
+        """
+        return Partitions(sum(self[:]))
+
+    def arms_legs_coeff(self, i , j):
+        """
+        EXAMPLES:
+            sage: Partition([3,2,1]).arms_legs_coeff(1,1)
+            (-t + 1)/(-q + 1)
+            sage: Partition([3,2,1]).arms_legs_coeff(0,0)
+            (-q^2*t^3 + 1)/(-q^3*t^2 + 1)
+        """
+        QQqt = PolynomialRing(QQ, ['q', 't'])
+        (q,t) = QQqt.gens()
+        if i < len(self) and j < self[i]:
+            res =  (1-q**self.arm(i,j) * t**(self.leg(i,j)+1))
+            res /= (1-q**(self.arm(i,j)+1) * t**self.leg(i,j))
+            return res
+        else:
+            return ZZ(1)
+
+    def macdonald_coeff(self):
+        res = 1
+        for i in range(len(self)):
+            for j in range(self[i]):
+                res *= self.arms_legs_coeff(i,j)
+        return res
+
+    def jacobi_trudi(self):
+        """
+        EXAMPLES:
+            sage: part = Partition([3,2,1])
+            sage: jt = part.jacobi_trudi(); jt
+            [h[3] h[1]    0]
+            [h[4] h[2]  h[]]
+            [h[5] h[3] h[1]]
+            sage: s = SFASchur(QQ)
+            sage: h = SFAHomogeneous(QQ)
+            sage: h( s(part) )
+            h[3, 2, 1] - h[3, 3] - h[4, 1, 1] + h[5, 1]
+            sage: jt.det()
+            h[3, 2, 1] - h[3, 3] - h[4, 1, 1] + h[5, 1]
+        """
+        return sage.combinat.skew_partition.SkewPartition([ self, [] ]).jacobi_trudi()
+    
+##################################################
+
+
+##################
+# Set Partitions #
+##################
+
+def partitions_set(S,k=None):
+    r"""
+
+    WARNING: Wraps GAP -- hence S must be a list of objects that have
+    string representations that can be interpreted by the GAP
+    intepreter.  If mset consists of at all complicated SAGE objects,
+    this function does *not* do what you expect.  A proper function
+    should be written! (TODO!)
+
+    Wraps GAP's PartitionsSet.
+        
+
+    """
+    if k is None:
+        ans=gap.eval("PartitionsSet(%s)"%S)
+    else:
+        ans=gap.eval("PartitionsSet(%s,%s)"%(S,k))
+    return eval(ans)
+
+def number_of_partitions_set(S,k):
+    r"""
+    Returns the size of \code{partitions_set(S,k)}.  Wraps GAP's
+    NrPartitionsSet.
+    
+    The Stirling number of the second kind is the number of partitions
+    of a set of size n into k blocks.
+
+    EXAMPLES:
+        sage: mset = [1,2,3,4]
+        sage: partition.number_of_partitions_set(mset,2)
+        7
+        sage: stirling_number2(4,2)
+        7
+
+    REFERENCES:
+        http://en.wikipedia.org/wiki/Partition_of_a_set
+
+    """
+    if k is None:
+        ans=gap.eval("NrPartitionsSet(%s)"%S)
+    else:
+        ans=gap.eval("NrPartitionsSet(%s,%s)"%(S,ZZ(k)))
+    return ZZ(ans)
+
+def number_of_partitions_list(n,k=None):
+    r"""
+    Returns the size of partitions_list(n,k).
+
+    Wraps GAP's NrPartitions.
+ 
+    It is possible to associate with every partition of the integer n
+    a conjugacy class of permutations in the symmetric group on n
+    points and vice versa.  Therefore p(n) = NrPartitions(n) is the
+    number of conjugacy classes of the symmetric group on n points.
+
+    \code{number_of_partitions(n)} is also available in PARI, however
+    the speed seems the same until $n$ is in the thousands (in which
+    case PARI is faster).
+
+    EXAMPLES:
+        sage: partition.number_of_partitions_list(10,2)
+        5
+        sage: partition.number_of_partitions_list(10)
+        42
+
+    A generating function for p(n) is given by the reciprocal of Euler's function:
+    \[
+    \sum_{n=0}^\infty p(n)x^n = \prod_{k=1}^\infty \left(\frac {1}{1-x^k} \right). 
+    \]
+    SAGE verifies that the first several coefficients do instead agree:
+    
+        sage: q = PowerSeriesRing(QQ, 'q', default_prec=9).gen()
+        sage: prod([(1-q^k)^(-1) for k in range(1,9)])  ## partial product of 
+        1 + q + 2*q^2 + 3*q^3 + 5*q^4 + 7*q^5 + 11*q^6 + 15*q^7 + 22*q^8 + O(q^9)
+        sage: [partition.number_of_partitions_list(k) for k in range(2,10)]
+        [2, 3, 5, 7, 11, 15, 22, 30]
+
+    REFERENCES:
+        http://en.wikipedia.org/wiki/Partition_%28number_theory%29
+
+    """
+    if k is None:
+        ans=gap.eval("NrPartitions(%s)"%(ZZ(n)))
+    else:
+        ans=gap.eval("NrPartitions(%s,%s)"%(ZZ(n),ZZ(k)))
+    return ZZ(ans)
+
+
+######################
+# Ordered Partitions #
+######################
+def OrderedPartitions(n, k=None):
+    return OrderedPartitions_nk(n,k)
+
+class OrderedPartitions_nk(CombinatorialClass):
+    def __init__(self, n, k=None):
+        self.n = n
+        self.k = k
+
+    def __repr__(self):
+        string = "Ordered partitions of %s "%self.n
+        if self.k is not None:
+            string += "of length %s"%self.k
+        return string
+        
+    def list(self):
+        n = self.n
+        k = self.k
+        if self.k is None:
+            ans=gap.eval("OrderedPartitions(%s)"%(ZZ(n)))
+        else:
+            ans=gap.eval("OrderedPartitions(%s,%s)"%(ZZ(n),ZZ(k)))
+        result = eval(ans.replace('\n',''))
+        result.reverse()
+        return result
+
+    def count(self):
+        n = self.n
+        k = self.k
+        if k is None:
+            ans=gap.eval("NrOrderedPartitions(%s)"%(n))
+        else:
+            ans=gap.eval("NrOrderedPartitions(%s,%s)"%(n,k))
+        return ZZ(ans)
+    
+def ordered_partitions(n,k=None):
+    r"""
+    An {\it ordered partition of $n$} is an ordered sum
+    $$
+       n = p_1+p_2 + \cdots + p_k
+    $$
+    of positive integers and is represented by the list $p = [p_1,p_2,\cdots ,p_k]$.
+    If $k$ is omitted then all ordered partitions are returned.
+
+    \code{ordered_partitions(n,k)} returns the set of all (ordered)
+    partitions of the positive integer n into sums with k summands.
+
+    Do not call \code{ordered_partitions} with an n much larger than
+    15, since the list will simply become too large.
+
+    Wraps GAP's OrderedPartitions.
+        
+    The number of ordered partitions $T_n$ of $\{ 1, 2, ..., n \}$ has the 
+    generating function is
+    \[
+    \sum_n {T_n \over n!} x^n = {1 \over 2-e^x}. 
+    \]
+
+    EXAMPLES:
+        sage: partition.ordered_partitions(10,2)
+        [[1, 9], [2, 8], [3, 7], [4, 6], [5, 5], [6, 4], [7, 3], [8, 2], [9, 1]]
+        
+        sage: partition.ordered_partitions(4)
+        [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
+
+    REFERENCES:
+        http://en.wikipedia.org/wiki/Ordered_partition_of_a_set
+
+    """
+    if k is None:
+        ans=gap.eval("OrderedPartitions(%s)"%(ZZ(n)))
+    else:
+        ans=gap.eval("OrderedPartitions(%s,%s)"%(ZZ(n),ZZ(k)))
+    result = eval(ans.replace('\n',''))
+    return [Partition(p) for p in result]
+
+def number_of_ordered_partitions(n,k=None):
+    """
+    Returns the size of ordered_partitions(n,k).
+    Wraps GAP's NrOrderedPartitions.
+ 
+    It is possible to associate with every partition of the integer n a conjugacy 
+    class of permutations in the symmetric group on n points and vice versa. 
+    Therefore p(n) = NrPartitions(n) is the number of conjugacy classes of the 
+    symmetric group on n points.
+
+   
+    EXAMPLES:
+        sage: partition.number_of_ordered_partitions(10,2)
+        9
+        sage: partition.number_of_ordered_partitions(15)
+        16384
+    """
+    if k is None:
+        ans=gap.eval("NrOrderedPartitions(%s)"%(n))
+    else:
+        ans=gap.eval("NrOrderedPartitions(%s,%s)"%(n,k))
+    return ZZ(ans)
+
+##########################
+# Partitions Greatest LE #
+##########################
+def PartitionsGreatestLE(n,k):
+    return PartitionsGreatestLE_nk(n,k)
+
+class PartitionsGreatestLE_nk(CombinatorialClass):
+    """
+    The combinatorial class of all (unordered) ``restricted'' partitions of the
+    integer n having parts less than or equal to the integer k.
+    """
+    object_class = Partition_class
+    def __init__(self, n, k):
+        self.n = n
+        self.k = k
+        
+    def __repr__(self):
+        return "Partitions of %s having parts less than or equal to %s"%(self.n, self.k)
+
+    def list(self):
+        """
+        Returns a list of all (unordered) ``restricted'' partitions of the
+        integer n having parts less than or equal to the integer k.
+    
+        Wraps GAP's PartitionsGreatestLE.
+
+        EXAMPLES:
+            sage: PartitionsGreatestLE(10,2).list()
+            [[2, 2, 2, 2, 2],
+             [2, 2, 2, 2, 1, 1],
+             [2, 2, 2, 1, 1, 1, 1],
+             [2, 2, 1, 1, 1, 1, 1, 1],
+             [2, 1, 1, 1, 1, 1, 1, 1, 1],
+             [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
+        """
+        result = eval(gap.eval("PartitionsGreatestLE(%s,%s)"%(ZZ(self.n),ZZ(self.k))))
+        result.reverse()
+        return [Partition(p) for p in result]        
+
+##########################
+# Partitions Greatest EQ #
+##########################
+def PartitionsGreatestEQ(n,k):
+    return PartitionsGreatestEQ_nk(n,k)
+
+class PartitionsGreatestEQ_nk(CombinatorialClass):
+    """
+    The combinatorial class of all (unordered) ``restricted'' partitions of the 
+    integer n having at least one part equal to the integer k.
+    """
+    object_class = Partition_class
+    def __init__(self, n, k):
+        self.n = n
+        self.k = k
+        
+    def __repr__(self):
+        return "Partitions of %s having at least one part equal to %s"%(self.n, self.k)
+    
+    def list(self):
+        """
+        Returns a list of all (unordered) ``restricted'' partitions of the 
+        integer n having at least one part equal to the integer k.
+
+        Wraps GAP's PartitionsGreatestEQ.
+
+        EXAMPLES:
+           sage: PartitionsGreatestEQ(10,2).list()
+           [[2, 2, 2, 2, 2],
+            [2, 2, 2, 2, 1, 1],
+            [2, 2, 2, 1, 1, 1, 1],
+            [2, 2, 1, 1, 1, 1, 1, 1],
+            [2, 1, 1, 1, 1, 1, 1, 1, 1]]
+        """
+        result = eval(gap.eval("PartitionsGreatestEQ(%s,%s)"%(self.n,self.k)))
+        result.reverse()
+        return [Partition(p) for p in result]
+
+
+#########################
+# Restricted Partitions #
+#########################
+def RestrictedPartitions(n, S, k=None):
+    return RestrictedPartitions_nsk(n, S, k)
+
+class RestrictedPartitions(CombinatorialClass):
+    r"""
+    A {\it restricted partition} is, like an ordinary partition, an 
+    unordered sum $n = p_1+p_2+\ldots+p_k$ of positive integers and is 
+    represented by the list $p = [p_1,p_2,\ldots,p_k]$, in nonincreasing 
+    order. The difference is that here the $p_i$ must be elements 
+    from the set $S$, while for ordinary partitions they may be 
+    elements from $[1..n]$.
+
+    """
+    object_class = Partition_class
+    def __init__(self, n, S, k=None):
+        self.n = n
+        self.S = S
+        self.S.sort()
+        self.k = k
+
+    def __repr__(self):
+        string = "Partitions of %s restricted to the values %s "%(self.n, self.S)
+        if self.k is not None:
+            string += "of length %s" % self.k
+        return string
+
+    def list(self):
+        r"""
+        Returns the set of all restricted partitions of the positive integer 
+        n into sums with k summands with the summands of the partition coming 
+        from the set $S$. If k is not given all restricted partitions for all 
+        k are returned.
+        
+        Wraps GAP's RestrictedPartitions.
+
+        EXAMPLES:
+            sage: RestrictedPartitions(8,[1,3,5,7]).list()
+            [[7, 1],
+            [5, 3],
+            [5, 1, 1, 1],
+            [3, 3, 1, 1],
+            [3, 1, 1, 1, 1, 1],
+            [1, 1, 1, 1, 1, 1, 1, 1]]
+            sage: RestrictedPartitions(8,[1,3,5,7],2).list()
+            [[7, 1], [5, 3]]
+        """
+        n = self.n
+        k = self.k
+        S = self.S
+        if k is None:
+            ans=gap.eval("RestrictedPartitions(%s,%s)"%(n,S))
+        else:
+            ans=gap.eval("RestrictedPartitions(%s,%s,%s)"%(n,S,k))
+        result = eval(ans)
+        result.reverse()
+        return [Partition(p) for p in result]
+
+    def count(self):
+        """
+        Returns the size of RestrictedPartitions(n,S,k).
+        Wraps GAP's NrRestrictedPartitions.
+        
+        EXAMPLES:
+            sage: RestrictedPartitions(8,[1,3,5,7]).count()
+            6
+            sage: RestrictedPartitions(8,[1,3,5,7],2).count()
+            2
+        """
+        n = self.n
+        k = self.k
+        S = self.S
+        if k is None:
+            ans=gap.eval("NrRestrictedPartitions(%s,%s)"%(ZZ(n),S))
+        else:
+            ans=gap.eval("NrRestrictedPartitions(%s,%s,%s)"%(ZZ(n),S,ZZ(k)))
+        return ZZ(ans)
+        
+####################
+# Partition Tuples #
+####################
+def PartitionTuples(n,k):
+    return PartitionTuples_nk(n,k)
+
+class PartitionTuples_nk(CombinatorialClass):
+    """
+    k-tuples of partitions describe the classes and the characters of 
+    wreath products of groups with k conjugacy classes with the symmetric 
+    group $S_n$.
+    
+    """
+    object_class = Partition_class
+    def __init__(self, n, k):
+        self.n = n
+        self.k = k
+        
+    def __repr__(self):
+        return "%s-tuples of partitions of %s"%(self.k, self.n)
+
+    def list(self):
+        """
+        Returns the list of all k-tuples of partitions 
+        which together form a partition of n. 
+        
+        Wraps GAP's PartitionTuples.
+
+        EXAMPLES:
+            sage: PartitionTuples(3,2).list()
+            [[[1, 1, 1], []],
+            [[1, 1], [1]],
+            [[1], [1, 1]],
+            [[], [1, 1, 1]],
+            [[2, 1], []],
+            [[1], [2]],
+            [[2], [1]],
+            [[], [2, 1]],
+            [[3], []],
+            [[], [3]]]
+        """
+        ans=gap.eval("PartitionTuples(%s,%s)"%(ZZ(self.n),ZZ(self.k)))
+        return map(lambda x: map(lambda y: Partition(y), x), eval(ans))
+    
+    def count(self):
+        r"""
+        Returns the number of k-tuples of partitions which together
+        form a partition of n.
+        
+        Wraps GAP's NrPartitionTuples.
+
+        EXAMPLES:
+            sage: PartitionTuples(3,2).count()
+            10
+            sage: PartitionTuples(8,2).count()
+            185
+            
+            Now we compare that with the result of the following GAP
+            computation:
+            \begin{verbatim}
+            gap> S8:=Group((1,2,3,4,5,6,7,8),(1,2));
+            Group([ (1,2,3,4,5,6,7,8), (1,2) ])
+            gap> C2:=Group((1,2));
+            Group([ (1,2) ])
+            gap> W:=WreathProduct(C2,S8);
+            <permutation group of size 10321920 with 10 generators>
+            gap> Size(W);
+            10321920     ## = 2^8*Factorial(8), which is good:-)
+            gap> Size(ConjugacyClasses(W));
+            185
+            \end{verbatim}          
+        """
+        
+        ans=gap.eval("NrPartitionTuples(%s,%s)"%(ZZ(self.n),ZZ(self.k)))
+        return ZZ(ans)
+
+##############
+# Partitions #
+##############
+
+def Partitions(n=None, **kwargs):
+    if n is None:
+        return Partitions_all()
+    else:
+        if len(kwargs) == 0:
+            return Partitions_n(n)
+        else:
+            return Partitions_constraints(n, **kwargs)
+
+class Partitions_all(CombinatorialClass):
+    def __init__(self):
+        """
+        TESTS:
+            sage: P = Partitions()
+            sage: P == loads(dumps(P))
+            True
+        """
+        pass
+    
+    object_class = Partition_class
+    
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: P = Partitions()
+            sage: Partition([2,1]) in P
+            True
+            sage: [2,1] in P
+            True
+            sage: [3,2,1] in P
+            True
+            sage: [1,2] in P
+            False
+        """
+        if isinstance(x, Partition_class):
+            return True
+        elif isinstance(x, __builtin__.list):
+            for i in range(len(x)):
+                if not isinstance(x[i], (int, Integer)):
+                    return False
+                if x[i] < 0:
+                    return False
+                if i == 0:
+                    prev = x[i]
+                    continue
+                if x[i] > prev:
+                    return False
+                prev = x[i]
+            return True
+        else:
+            return False
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Partitions())
+            'Partitions'
+        """
+        return "Partitions"
+    
+    def list(self):
+        raise NotImplementedError
+
+class Partitions_constraints(CombinatorialClass):
+    def __init__(self, n, **kwargs):
+        """
+        TESTS:
+            sage: p = Partitions(5, min_part=2)
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.n = n
+        self.constraints = kwargs
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: p = Partitions(5, min_part=2)
+            sage: [2,1] in p
+            False
+            sage: [2,2,1] in p
+            False
+            sage: [3,2] in p
+            True
+        """
+        return x in Partitions_all() and sum(x)==self.n and misc.check_integer_list_constraints(x, singleton=True, **self.constraints)
+
+    def size(self):
+        return self.n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr( Partitions(5, min_part=2) )
+            'Partitions of the integer 5 satisfying constraints min_part=2'
+        """
+        return "Partitions of the integer %s satisfying constraints %s"%(self.n, ", ".join( ["%s=%s"%(key, self.constraints[key]) for key in sorted(self.constraints.keys())] ))
+
+    def iterator(self):
+        """
+        An iterator a list of the partitions of n.
+
+        EXAMPLES:
+            sage: [x for x in Partitions(4)]
+            [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]
+            sage: [x for x in Partitions(4, length=2)]
+            [[3, 1], [2, 2]]
+            sage: [x for x in Partitions(4, min_length=2)]
+            [[3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]
+            sage: [x for x in Partitions(4, max_length=2)]
+            [[4], [3, 1], [2, 2]]
+            sage: [x for x in Partitions(4, min_length=2, max_length=2)]
+            [[3, 1], [2, 2]]
+            sage: [x for x in Partitions(4, max_part=2)]
+            [[2, 2], [2, 1, 1], [1, 1, 1, 1]]
+            sage: [x for x in Partitions(4, min_part=2)]
+            [[4], [2, 2]]
+            sage: [x for x in Partitions(4, length=3, min_part=0)]
+            [[4, 0, 0], [3, 1, 0], [2, 2, 0], [2, 1, 1]]
+            sage: [x for x in Partitions(4, min_length=3, min_part=0)]
+            [[4, 0, 0], [3, 1, 0], [2, 2, 0], [2, 1, 1], [1, 1, 1, 1]]
+            sage: [x for x in Partitions(4, outer=[3,1,1])]
+            [[3, 1], [2, 1, 1]]
+            sage: [x for x in Partitions(4, outer=['inf', 1, 1])]
+            [[4], [3, 1], [2, 1, 1]]
+            sage: [x for x in Partitions(4, inner=[1,1,1])]
+            [[2, 1, 1], [1, 1, 1, 1]]
+            sage: [x for x in Partitions(4, max_slope=-1)]
+            [[4], [3, 1]]
+            sage: [x for x in Partitions(4, min_slope=-1)]
+            [[4], [2, 2], [2, 1, 1], [1, 1, 1, 1]]
+            sage: [x for x in Partitions(11, max_slope=-1, min_slope=-3, min_length=2, max_length=4)]
+            [[7, 4], [6, 5], [6, 4, 1], [6, 3, 2], [5, 4, 2], [5, 3, 2, 1]]
+            sage: [x for x in Partitions(11, max_slope=-1, min_slope=-3, min_length=2, max_length=4, outer=[6,5,2])]
+            [[6, 5], [6, 4, 1], [6, 3, 2], [5, 4, 2]]
+        """
+        n = self.n
+
+        #put the constraints in the namespace
+        length = self.constraints.get('length',None)
+        min_length = self.constraints.get('min_length',None)
+        max_length = self.constraints.get('max_length',None)        
+        max_part = self.constraints.get('max_part',None)
+        min_part = self.constraints.get('min_part',None)
+        max_slope = self.constraints.get('max_slope',None)
+        min_slope = self.constraints.get('min_slope',None)
+        inner = self.constraints.get('inner',None)
+        outer = self.constraints.get('outer',None)
+
+        #Preproccess the constraints
+        if max_slope == "inf":
+            max_slope = n
+        if min_slope == "-inf":
+            min_slope = -n
+        if length is not None:
+            min_length = length
+            max_length = length
+        if outer is not None:
+            for i in range(len(outer)):
+                if outer[i] == "inf":
+                    outer[i] = n
+
+        l = []
+        old_p = Partition_class([self.n])
+
+        #Go through all of the partitions
+        while old_p != False:
+            meets_constraints = True
+
+            #Handle the case if the user specifies
+            #min_part = 0
+            if min_part == 0:
+                #if length is not None and len(p) < length:
+                #    p += [0]*(len(p)-length)
+                if min_length is not None and len(old_p) < min_length:
+                    p = old_p + [0]*(min_length-len(old_p))
+                else:
+                    p = old_p
+            else:
+                p = old_p
+
+            #if length is not None:
+            #    if len(p) != length:
+            #        meets_constraints = False
+
+            if min_length is not None:
+                if len(p) < min_length:
+                    meets_constraints = False
+
+            if max_length is not None:
+                if len(p) > max_length:
+                    meets_constraints = False
+
+            if max_part is not None:
+                if max(p) > max_part:
+                    meets_constraints = False
+
+            if min_part is not None:
+                if min(p) < min_part:
+                    meets_constraints = False
+
+            if outer is not None:
+                if len(p) > len(outer):
+                    meets_constraints = False
+                else:
+                    for i in range(len(p)):
+                        if p[i] > outer[i]:
+                            meets_constraints = False
+
+            if inner is not None:
+                if len(p) < len(inner):
+                    meets_constraints = False
+                else:
+                    for i in range(len(inner)):
+                        if p[i] < inner[i]:
+                            meets_constraints = False
+
+
+            if max_slope is not None:
+                if max([p[i+1]-p[i] for i in range(0, len(p)-1)]+[-n] ) > max_slope:
+                    meets_constraints = False
+
+            if min_slope is not None:
+                if min([p[i+1]-p[i] for i in range(0, len(p)-1)]+[n] ) < min_slope:
+                    meets_constraints = False
+
+
+            if meets_constraints:
+                yield p
+
+            old_p = old_p.next()
+
+class Partitions_n(CombinatorialClass):
+    object_class = Partition_class
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: p = Partitions(5)
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.n = n
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: p = Partitions(5)
+            sage: [2,1] in p
+            False
+            sage: [2,2,1] in p
+            True
+            sage: [3,2] in p
+            True
+        """
+        return x in Partitions_all() and sum(x)==self.n
+
+    def size(self):
+        return self.n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr( Partitions(5) )
+            'Partitions of the integer 5'
+        """
+        return "Partitions of the integer %s"%self.n
+
+    def count(self, algorithm='default'):
+        r"""
+            algorithm -- (default: 'default')
+                'bober' -- use Jonathon Bober's implementation (*very* fast,
+                          but new and not well tested yet).
+                'gap' -- use GAP (VERY *slow*)
+                'pari' -- use PARI.  Speed seems the same as GAP until $n$ is
+                          in the thousands, in which case PARI is faster. *But*
+                          PARI has a bug, e.g., on 64-bit Linux PARI-2.3.2
+                          outputs numbpart(147007)%1000 as 536, but it
+                          should be 533!.  So do not use this option.
+                'default' -- 'bober' when k is not specified; otherwise
+                          use 'gap'.
+
+
+        Use the function \code{partitions(n)} to return a generator over
+        all partitions of $n$.
+
+        It is possible to associate with every partition of the integer n
+        a conjugacy class of permutations in the symmetric group on n
+        points and vice versa.  Therefore p(n) = NrPartitions(n) is the
+        number of conjugacy classes of the symmetric group on n points.
+
+        EXAMPLES:
+            sage: v = Partitions(5).list(); v
+            [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]]
+            sage: len(v)
+            7
+            sage: Partitions(5).count(algorithm='gap')
+            7
+            sage: Partitions(5).count(algorithm='pari')
+            7
+            sage: Partitions(5).count(algorithm='bober')
+            7
+
+        The input must be a nonnegative integer or a ValueError is raised.
+            sage: Partitions(10).count()
+            42
+            sage: Partitions(3).count()
+            3
+            sage: Partitions(10).count()
+            42
+            sage: Partitions(3).count(algorithm='pari')
+            3
+            sage: Partitions(10).count(algorithm='pari')
+            42
+            sage: Partitions(40).count()
+            37338
+            sage: Partitions(100).count()
+            190569292
+
+        A generating function for p(n) is given by the reciprocal of
+        Euler's function:
+
+        \[
+        \sum_{n=0}^\infty p(n)x^n = \prod_{k=1}^\infty \left(\frac {1}{1-x^k} \right). 
+        \]
+
+        We use SAGE to verify that the first several coefficients do
+        instead agree:
+
+            sage: q = PowerSeriesRing(QQ, 'q', default_prec=9).gen()
+            sage: prod([(1-q^k)^(-1) for k in range(1,9)])  ## partial product of 
+            1 + q + 2*q^2 + 3*q^3 + 5*q^4 + 7*q^5 + 11*q^6 + 15*q^7 + 22*q^8 + O(q^9)
+            sage: [Partitions(k) .count()for k in range(2,10)]
+            [2, 3, 5, 7, 11, 15, 22, 30]
+
+        REFERENCES:
+            http://en.wikipedia.org/wiki/Partition_%28number_theory%29
+
+        """
+        return number_of_partitions(self.n, algorithm=algorithm)
+
+    def first(self):
+        """
+        Returns the lexicographically first partition of a
+        positive integer n. This is the partition [n].
+
+        EXAMPLES:
+            sage: Partitions(4).first()
+            [4]
+        """
+        return Partition([self.n])
+
+    def last(self):
+        """
+        Returns the lexicographically last partition of the
+        positive integer n.  This is the all-ones partition.
+
+        EXAMPLES:
+            sage: Partitions(4).last()
+            [1, 1, 1, 1]
+        """
+
+        return Partition_class([1]*self.n)
+
+
+    def iterator(self):
+        """
+        An iterator a list of the partitions of n.
+
+        EXAMPLES:
+            sage: [x for x in Partitions(4)]
+            [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]
+        """
+        # base case of the recursion: zero is the sum of the empty tuple
+        if self.n == 0:
+            yield Partition_class([])
+            return
+        
+        # modify the partitions of n-1 to form the partitions of n
+        for p in Partitions_n(self.n-1):
+            if p and (len(p) < 2 or p[-2] > p[-1]):
+                yield Partition_class(list(p[:-1]) + [p[-1] + 1])
+            yield  Partition_class(p + [1])
+
+
+
+def PartitionsInBox(h, w):
+    return PartitionsInBox_hw(h, w)
+
+class PartitionsInBox_hw(CombinatorialClass):
+    object_class = Partition_class
+    def __init__(self, h, w):
+        self.h = h
+        self.w = w
+
+    def __repr__(self):
+        return "Integer Partitions which fit in a %s x %s box" % (self.h, self.w)
+
+    def list(self):
+        """
+        Returns a list of all the partitions inside a box of height h
+        and width w.
+
+        EXAMPLES:
+            sage: PartitionsInBox(2,2).list()
+            [[], [1], [1, 1], [2], [2, 1], [2, 2]]
+        """
+        h = self.h
+        w = self.w
+        if h == 0:
+            return [[]]
+        else:
+            l = [[i] for i in range(0, w+1)]
+            add = lambda x: [ x+[i] for i in range(0, x[-1]+1)]
+            for i in range(h-1):
+                new_list = []
+                for element in l:
+                    new_list += add(element)
+                l = new_list
+
+            return [Partition(filter(lambda x: x!=0, p)) for p in l]
Index: sage/combinat/partition_algebra.py
===================================================================
--- sage/combinat/partition_algebra.py	(revision 6908)
+++ sage/combinat/partition_algebra.py	(revision 6908)
@@ -0,0 +1,1636 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from combinat import CombinatorialClass, CombinatorialObject, catalan_number
+from combinatorial_algebra import CombinatorialAlgebra, CombinatorialAlgebraElement
+import set_partition
+from sage.sets.set import Set
+from sage.graphs.graph import Graph
+from sage.rings.arith import factorial, binomial
+from permutation import Permutations
+from sage.rings.all import Integer, is_RealNumber
+from sage.calculus.all import floor, ceil
+from subset import Subsets
+
+def create_set_partitions_function(letter):
+    """
+    """
+    def function(k):
+        """
+        """
+        if isinstance(k, (int, Integer)):
+            if k > 0:
+                return eval('SetPartitions' + letter + 'k_k(k)')
+        elif is_RealNumber(k):
+            if k - floor(k) == 0.5:
+                return eval('SetPartitions' + letter + 'khalf_k(floor(k))')
+
+        raise ValueError, "k must be an integer or an integer + 1/2"
+
+    return function
+
+#####
+#A_k#
+#####
+SetPartitionsAk = create_set_partitions_function("A")
+SetPartitionsAk.__doc__ = """
+Returns the combinatorial class of set partitions of type A_k.
+
+EXAMPLES:
+    sage: A3 = SetPartitionsAk(3); A3
+    Set partitions of {1, ..., 3, -1, ..., -3}
+
+    sage: A3.first() #random
+    {{1, 2, 3, -1, -3, -2}}
+    sage: A3.last() #random
+    {{-1}, {-2}, {3}, {1}, {-3}, {2}}
+    sage: A3.random()  #random
+    {{1, 3, -3, -1}, {2, -2}}
+
+    sage: A3.count()
+    203
+
+    sage: A2p5 = SetPartitionsAk(2.5); A2p5
+    Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block
+    sage: A2p5.count()
+    52
+
+    sage: A2p5.first() #random
+    {{1, 2, 3, -1, -3, -2}}
+    sage: A2p5.last() #random
+    {{-1}, {-2}, {2}, {3, -3}, {1}}
+    sage: A2p5.random() #random
+    {{-1}, {-2}, {3, -3}, {1, 2}}
+    
+"""
+
+class SetPartitionsAk_k(set_partition.SetPartitions_set):
+    def __init__(self, k):
+        """
+        TESTS:
+           sage: A3 = SetPartitionsAk(3); A3
+           Set partitions of {1, ..., 3, -1, ..., -3}
+           sage: A3 == loads(dumps(A3))
+           True
+        """
+        self.k = k
+        set_partition.SetPartitions_set.__init__(self, Set(range(1,k+1) + map(lambda x: -1*x,range(1,k+1))))
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsAk(3))
+            'Set partitions of {1, ..., 3, -1, ..., -3}'
+        """
+        return "Set partitions of {1, ..., %s, -1, ..., -%s}"%(self.k, self.k)
+
+class SetPartitionsAkhalf_k(CombinatorialClass):
+    def __init__(self, k):
+        """
+        TESTS:
+            sage: A2p5 = SetPartitionsAk(2.5); A2p5
+            Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block
+            sage: A2p5 == loads(dumps(A2p5))
+            True           
+        """
+        self.k = k
+        self._set = range(1,k+2) + map(lambda x: -1*x, range(1,k+1))
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsAk(2.5))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block'
+        """
+        s = self.k+1
+        return "Set partitions of {1, ..., %s, -1, ..., -%s} with %s and -%s in the same block"%(s,s,s,s)
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: A2p5 = SetPartitionsAk(2.5)
+            sage: all([ sp in A2p5 for sp in A2p5])
+            True
+            sage: A3 = SetPartitionsAk(3)
+            sage: len(filter(lambda x: x in A2p5, A3))
+            52
+            sage: A2p5.count()
+            52
+        """
+        if x not in SetPartitionsAk_k(self.k+1):
+            return False
+
+        for part in x:
+            if self.k+1 in part and -self.k-1 not in part:
+                return False
+
+        return True
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsAk(1.5).count()
+            5
+            sage: SetPartitionsAk(2.5).count()
+            52
+            sage: SetPartitionsAk(3.5).count()
+            877
+        """
+        return set_partition.SetPartitions_set(self._set).count()
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: SetPartitionsAk(1.5).list() #random
+            [{{1, 2, -2, -1}},
+             {{2, -2, -1}, {1}},
+             {{2, -2}, {1, -1}},
+             {{-1}, {1, 2, -2}},
+             {{-1}, {2, -2}, {1}}]
+
+             sage: ks = [ 1.5, 2.5, 3.5 ]
+             sage: aks = map(SetPartitionsAk, ks)
+             sage: all([ak.count() == len(ak.list()) for ak in aks])
+             True
+        """
+        kp = Set([-self.k-1])
+        for sp in set_partition.SetPartitions_set(self._set):
+            res = []
+            for part in sp:
+                if self.k+1 in part:
+                    res.append( part + kp )
+                else:
+                    res.append(part)
+            yield Set(res)
+
+#####
+#S_k#
+#####
+SetPartitionsSk = create_set_partitions_function("S")
+SetPartitionsSk.__doc__ = """
+Returns the combinatorial class of set partitions of type S_k.  There
+is a bijection between these set partitions and the permutations
+of 1, ..., k.
+
+EXAMPLES:
+    sage: S3 = SetPartitionsSk(3); S3
+    Set partitions of {1, ..., 3, -1, ..., -3} with propagating number 3
+    sage: S3.count()
+    6
+
+    sage: S3.list()  #random
+    [{{2, -2}, {3, -3}, {1, -1}},
+     {{1, -1}, {2, -3}, {3, -2}},
+     {{2, -1}, {3, -3}, {1, -2}},
+     {{1, -2}, {2, -3}, {3, -1}},
+     {{1, -3}, {2, -1}, {3, -2}},
+     {{1, -3}, {2, -2}, {3, -1}}]
+    sage: S3.first() #random
+    {{2, -2}, {3, -3}, {1, -1}}
+    sage: S3.last() #random
+    {{1, -3}, {2, -2}, {3, -1}}
+    sage: S3.random() #random
+    {{1, -3}, {2, -1}, {3, -2}}
+
+    sage: S3p5 = SetPartitionsSk(3.5); S3p5
+    Set partitions of {1, ..., 4, -1, ..., -4} with 4 and -4 in the same block and propagating number 4
+    sage: S3p5.count()
+    6
+
+    sage: S3p5.list() #random
+    [{{2, -2}, {3, -3}, {1, -1}, {4, -4}},
+     {{2, -3}, {1, -1}, {4, -4}, {3, -2}},
+     {{2, -1}, {3, -3}, {1, -2}, {4, -4}},
+     {{2, -3}, {1, -2}, {4, -4}, {3, -1}},
+     {{1, -3}, {2, -1}, {4, -4}, {3, -2}},
+     {{1, -3}, {2, -2}, {4, -4}, {3, -1}}]
+    sage: S3p5.first() #random
+    {{2, -2}, {3, -3}, {1, -1}, {4, -4}}
+    sage: S3p5.last() #random
+    {{1, -3}, {2, -2}, {4, -4}, {3, -1}}
+    sage: S3p5.random() #random
+    {{1, -3}, {2, -2}, {4, -4}, {3, -1}}
+"""
+class SetPartitionsSk_k(SetPartitionsAk_k):
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsSk(3))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with propagating number 3'
+        """
+        return SetPartitionsAk_k.__repr__(self) + " with propagating number %s"%self.k
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: A3 = SetPartitionsAk(3)
+            sage: S3 = SetPartitionsSk(3)
+            sage: all([ sp in S3 for sp in S3])
+            True
+            sage: S3.count()
+            6
+            sage: len(filter(lambda x: x in S3, A3))
+            6
+        """
+        if not SetPartitionsAk_k.__contains__(self, x):
+            return False
+
+        if propagating_number(x) != self.k:
+            return False
+
+        return True
+
+    def count(self):
+        """
+        Returns k!.
+        
+        TESTS:
+            sage: SetPartitionsSk(2).count()
+            2
+            sage: SetPartitionsSk(3).count()
+            6
+            sage: SetPartitionsSk(4).count()
+            24
+            sage: SetPartitionsSk(5).count()
+            120
+        """
+        return factorial(self.k)
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: SetPartitionsSk(3).list() #random
+            [{{2, -2}, {3, -3}, {1, -1}},
+             {{1, -1}, {2, -3}, {3, -2}},
+             {{2, -1}, {3, -3}, {1, -2}},
+             {{1, -2}, {2, -3}, {3, -1}},
+             {{1, -3}, {2, -1}, {3, -2}},
+             {{1, -3}, {2, -2}, {3, -1}}]
+            sage: ks = range(1, 6)
+            sage: sks = map(SetPartitionsSk, ks)
+            sage: all([ sk.count() == len(sk.list()) for sk in sks])
+            True
+        """
+        for p in Permutations(self.k):
+            res = []
+            for i in range(self.k):
+                res.append( Set([ i+1, -p[i] ]) )
+            yield Set(res)
+
+class SetPartitionsSkhalf_k(SetPartitionsAkhalf_k):
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: S2p5 = SetPartitionsSk(2.5)
+            sage: A3 = SetPartitionsAk(3)
+            sage: all([sp in S2p5 for sp in S2p5])
+            True
+            sage: len(filter(lambda x: x in S2p5, A3))
+            2
+            sage: S2p5.count()
+            2
+        """
+        if not SetPartitionsAkhalf_k.__contains__(self, x):
+            return False
+        if propagating_number(x) != self.k+1:
+            return False
+        return True
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsSk(2.5))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and propagating number 3'
+        """
+        s = self.k+1
+        return SetPartitionsAkhalf_k.__repr__(self) + " and propagating number %s"%s
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsSk(2.5).count()
+            2
+            sage: SetPartitionsSk(3.5).count()
+            6
+            sage: SetPartitionsSk(4.5).count()
+            24
+
+            sage: ks = [2.5, 3.5, 4.5, 5.5]
+            sage: sks = [SetPartitionsSk(k) for k in ks]
+            sage: all([ sk.count() == len(sk.list()) for sk in sks])
+            True
+
+        """
+        return factorial(self.k)
+
+    def iterator(self):
+        """
+
+        TESTS:
+            sage: SetPartitionsSk(3.5).list() #random indirect test
+            [{{2, -2}, {3, -3}, {1, -1}, {4, -4}},
+             {{2, -3}, {1, -1}, {4, -4}, {3, -2}},
+             {{2, -1}, {3, -3}, {1, -2}, {4, -4}},
+             {{2, -3}, {1, -2}, {4, -4}, {3, -1}},
+             {{1, -3}, {2, -1}, {4, -4}, {3, -2}},
+             {{1, -3}, {2, -2}, {4, -4}, {3, -1}}]
+        """
+        for p in Permutations(self.k):
+            res = []
+            for i in range(self.k):
+                res.append( Set([ i+1, -p[i] ]) )
+
+            res.append(Set([self.k+1, -self.k - 1]))
+            yield Set(res)
+
+#####
+#I_k#
+#####
+SetPartitionsIk = create_set_partitions_function("I")
+SetPartitionsIk.__doc__ = """
+Returns the combinatorial class of set partitions of type I_k.  These
+are set partitions with a propagating number of less than k.  Note
+that the identity set partition {{1, -1}, ..., {k, -k}} is not
+in I_k.
+
+EXAMPLES:
+    sage: I3 = SetPartitionsIk(3); I3
+    Set partitions of {1, ..., 3, -1, ..., -3} with propagating number < 3
+    sage: I3.count()
+    197
+
+    sage: I3.first() #random
+    {{1, 2, 3, -1, -3, -2}}
+    sage: I3.last() #random
+    {{-1}, {-2}, {3}, {1}, {-3}, {2}}
+    sage: I3.random() #random
+    {{-1}, {-3, -2}, {2, 3}, {1}}
+
+    sage: I2p5 = SetPartitionsIk(2.5); I2p5
+    Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and propagating number < 3
+    sage: I2p5.count()
+    50
+
+    sage: I2p5.first() #random
+    {{1, 2, 3, -1, -3, -2}}
+    sage: I2p5.last() #random
+    {{-1}, {-2}, {2}, {3, -3}, {1}}
+    sage: I2p5.random() #random
+    {{-1}, {-2}, {1, 3, -3}, {2}}
+
+"""
+class SetPartitionsIk_k(SetPartitionsAk_k):
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsIk(3))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with propagating number < 3'
+        """
+        return SetPartitionsAk_k.__repr__(self) + " with propagating number < %s"%self.k
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: I3 = SetPartitionsIk(3)
+            sage: A3 = SetPartitionsAk(3)
+            sage: all([ sp in I3 for sp in I3])
+            True
+            sage: len(filter(lambda x: x in I3, A3))
+            197
+            sage: I3.count()
+            197
+        """
+        if not SetPartitionsAk_k.__contains__(self, x):
+            return False
+        if propagating_number(x) >= self.k:
+            return False
+        return True
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsIk(2).count()
+            13
+        """
+        return len(self.list())
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: SetPartitionsIk(2).list() #random indirect test
+                [{{1, 2, -1, -2}},
+                 {{2, -1, -2}, {1}},
+                 {{2}, {1, -1, -2}},
+                 {{-1}, {1, 2, -2}},
+                 {{-2}, {1, 2, -1}},
+                 {{1, 2}, {-1, -2}},
+                 {{2}, {-1, -2}, {1}},
+                 {{-1}, {2, -2}, {1}},
+                 {{-2}, {2, -1}, {1}},
+                 {{-1}, {2}, {1, -2}},
+                 {{-2}, {2}, {1, -1}},
+                 {{-1}, {-2}, {1, 2}},
+                 {{-1}, {-2}, {2}, {1}}]
+        """
+        for sp in SetPartitionsAk_k.iterator(self):
+            if propagating_number(sp) < self.k:
+                yield sp
+
+class SetPartitionsIkhalf_k(SetPartitionsAkhalf_k):
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: I2p5 = SetPartitionsIk(2.5)
+            sage: A3 = SetPartitionsAk(3)
+            sage: all([ sp in I2p5 for sp in I2p5])
+            True
+            sage: len(filter(lambda x: x in I2p5, A3))
+            50
+            sage: I2p5.count()
+            50
+        """
+        if not SetPartitionsAkhalf_k.__contains__(self, x):
+            return False
+        if propagating_number(x) >= self.k+1:
+            return False
+        return True
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsIk(2.5))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and propagating number < 3'
+        """
+        return SetPartitionsAkhalf_k.__repr__(self) + " and propagating number < %s"%(self.k+1)
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsIk(1.5).count()
+            4
+            sage: SetPartitionsIk(2.5).count()
+            50
+            sage: SetPartitionsIk(3.5).count()
+            871
+        """
+        return len(self.list())
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: SetPartitionsIk(1.5).list() #random
+            [{{1, 2, -2, -1}},
+             {{2, -2, -1}, {1}},
+             {{-1}, {1, 2, -2}},
+             {{-1}, {2, -2}, {1}}]
+        """
+
+        for sp in SetPartitionsAkhalf_k.iterator(self):
+            if propagating_number(sp) < self.k+1:
+                yield sp
+#####
+#B_k#
+#####
+SetPartitionsBk = create_set_partitions_function("B")
+SetPartitionsBk.__doc__ = """
+Returns the combinatorial class of set partitions of type B_k.
+These are the set partitions where every block has size 2.
+
+EXAMPLES:
+    sage: B3 = SetPartitionsBk(3); B3
+    Set partitions of {1, ..., 3, -1, ..., -3} with block size 2
+
+    sage: B3.first() #random
+    {{2, -2}, {1, -3}, {3, -1}}
+    sage: B3.last() #random
+    {{1, 2}, {3, -2}, {-3, -1}}
+    sage: B3.random() #random
+    {{2, -1}, {1, -3}, {3, -2}}
+
+    sage: B3.count()
+    15
+
+    sage: B2p5 = SetPartitionsBk(2.5); B2p5
+    Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and with block size 2
+
+    sage: B2p5.first() #random
+    {{2, -1}, {3, -3}, {1, -2}}
+    sage: B2p5.last() #random
+    {{1, 2}, {3, -3}, {-1, -2}}
+    sage: B2p5.random() #random
+    {{2, -2}, {3, -3}, {1, -1}}
+
+    sage: B2p5.count()
+    3
+"""
+
+class SetPartitionsBk_k(SetPartitionsAk_k):
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsBk(2.5))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and with block size 2'
+        """
+        return SetPartitionsAk_k.__repr__(self) + " with block size 2"
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: B3 = SetPartitionsBk(3)
+            sage: A3 = SetPartitionsAk(3)
+            sage: len(filter(lambda x: x in B3, A3))
+            15
+            sage: B3.count()
+            15
+        """
+        if not SetPartitionsAk_k.__contains__(self, x):
+            return False
+
+        for part in x:
+            if len(part) != 2:
+                return False
+            
+        return True
+
+    def count(self):
+        """
+        Returns the number of set partitions in B_k where k is an integer.
+        This is given by (2k)!! = (2k-1)*(2k-3)*...*5*3*1.
+
+        EXAMPLES:
+            sage: SetPartitionsBk(3).count()
+            15
+            sage: SetPartitionsBk(2).count()
+            3
+            sage: SetPartitionsBk(1).count()
+            1
+            sage: SetPartitionsBk(4).count()
+            105
+            sage: SetPartitionsBk(5).count()
+            945
+
+        """
+        c = 1
+        for i in range(1, 2*self.k,2):
+            c *= i
+        return c
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: SetPartitionsBk(1).list()
+            [{{1, -1}}]
+
+            sage: SetPartitionsBk(2).list() #random
+            [{{2, -1}, {1, -2}}, {{2, -2}, {1, -1}}, {{1, 2}, {-1, -2}}]
+            sage: SetPartitionsBk(3).list() #random
+            [{{2, -2}, {1, -3}, {3, -1}},
+             {{2, -1}, {1, -3}, {3, -2}},
+             {{1, -3}, {2, 3}, {-1, -2}},
+             {{3, -1}, {1, -2}, {2, -3}},
+             {{3, -2}, {1, -1}, {2, -3}},
+             {{1, 3}, {2, -3}, {-1, -2}},
+             {{2, -1}, {3, -3}, {1, -2}},
+             {{2, -2}, {3, -3}, {1, -1}},
+             {{1, 2}, {3, -3}, {-1, -2}},
+             {{-3, -2}, {2, 3}, {1, -1}},
+             {{1, 3}, {-3, -2}, {2, -1}},
+             {{1, 2}, {3, -1}, {-3, -2}},
+             {{-3, -1}, {2, 3}, {1, -2}},
+             {{1, 3}, {-3, -1}, {2, -2}},
+             {{1, 2}, {3, -2}, {-3, -1}}]
+
+          Check to make sure that the number of elements generated
+          is the same as what is given by count()
+          
+            sage: bks = [ SetPartitionsBk(i) for i in range(1, 6) ]
+            sage: all( [ bk.count() == len(bk.list()) for bk in bks] )
+            True
+        """
+        for sp in set_partition.SetPartitions(self.set, [2]*(len(self.set)/2)):
+            yield sp
+
+class SetPartitionsBkhalf_k(SetPartitionsAkhalf_k):
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsBk(2.5))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and with block size 2'
+        """
+        return SetPartitionsAkhalf_k.__repr__(self) + " and with block size 2"
+
+    
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: A3 = SetPartitionsAk(3)
+            sage: B2p5 = SetPartitionsBk(2.5)
+            sage: all([ sp in B2p5 for sp in B2p5 ])
+            True
+            sage: len(filter(lambda x: x in B2p5, A3))
+            3
+            sage: B2p5.count()
+            3
+        """
+        if not SetPartitionsAkhalf_k.__contains__(self, x):
+            return False
+        for part in x:
+            if len(part) != 2:
+                return False
+        return True
+
+    def count(self):
+        """
+        TESTS:
+            sage: B3p5 = SetPartitionsBk(3.5)
+            sage: B3p5.count()
+            15
+        """
+        return len(self.list())
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: B3p5 = SetPartitionsBk(3.5)
+            sage: B3p5.count()
+            15
+
+            sage: B3p5.list() #random
+            [{{2, -2}, {1, -3}, {4, -4}, {3, -1}},
+             {{2, -1}, {1, -3}, {4, -4}, {3, -2}},
+             {{1, -3}, {2, 3}, {4, -4}, {-1, -2}},
+             {{2, -3}, {1, -2}, {4, -4}, {3, -1}},
+             {{2, -3}, {1, -1}, {4, -4}, {3, -2}},
+             {{1, 3}, {4, -4}, {2, -3}, {-1, -2}},
+             {{2, -1}, {3, -3}, {1, -2}, {4, -4}},
+             {{2, -2}, {3, -3}, {1, -1}, {4, -4}},
+             {{1, 2}, {3, -3}, {4, -4}, {-1, -2}},
+             {{-3, -2}, {2, 3}, {1, -1}, {4, -4}},
+             {{1, 3}, {-3, -2}, {2, -1}, {4, -4}},
+             {{1, 2}, {-3, -2}, {4, -4}, {3, -1}},
+             {{-3, -1}, {2, 3}, {1, -2}, {4, -4}},
+             {{1, 3}, {-3, -1}, {2, -2}, {4, -4}},
+             {{1, 2}, {-3, -1}, {4, -4}, {3, -2}}]
+        """
+        set = range(1,self.k+1) + map(lambda x: -1*x, range(1,self.k+1))
+        for sp in set_partition.SetPartitions(set, [2]*(len(set)/2) ):
+            yield sp + Set([Set([self.k+1, -self.k -1])])
+
+#####
+#P_k#
+#####
+SetPartitionsPk = create_set_partitions_function("P")
+SetPartitionsPk.__doc__ = """
+Returns the combinatorial class of set partitions of type P_k.
+These are the planar set partitions.
+
+
+sage: P3 = SetPartitionsPk(3); P3
+Set partitions of {1, ..., 3, -1, ..., -3} that are planar
+sage: P3.count()
+132
+
+sage: P3.first() #random
+{{1, 2, 3, -1, -3, -2}} 
+sage: P3.last() #random
+{{-1}, {-2}, {3}, {1}, {-3}, {2}}
+sage: P3.random() #random
+{{1, 2, -1}, {-3}, {3, -2}}
+
+sage: P2p5 = SetPartitionsPk(2.5); P2p5
+Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and that are planar
+sage: P2p5.count()
+42
+
+sage: P2p5.first() #random
+{{1, 2, 3, -1, -3, -2}}
+sage: P2p5.last() #random
+{{-1}, {-2}, {2}, {3, -3}, {1}}
+sage: P2p5.random() #random
+{{1, 2, 3, -3}, {-1, -2}}
+
+
+"""
+class SetPartitionsPk_k(SetPartitionsAk_k):
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsPk(3))
+            'Set partitions of {1, ..., 3, -1, ..., -3} that are planar'
+        """
+        return SetPartitionsAk_k.__repr__(self) + " that are planar"
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: P3 = SetPartitionsPk(3)
+            sage: A3 = SetPartitionsAk(3)
+            sage: len(filter(lambda x: x in P3, A3))
+            132
+            sage: P3.count()
+            132
+            sage: all([sp in P3 for sp in P3])
+            True
+        """
+        if not SetPartitionsAk_k.__contains__(self, x):
+            return False
+
+        if not is_planar(x):
+            return False
+
+        return True
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsPk(2).count()
+            14
+            sage: SetPartitionsPk(3).count()
+            132
+            sage: SetPartitionsPk(4).count()
+            1430
+        """
+        return catalan_number(2*self.k)
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: SetPartitionsPk(2).list() #random indirect test
+            [{{1, 2, -1, -2}},
+             {{2, -1, -2}, {1}},
+             {{2}, {1, -1, -2}},
+             {{-1}, {1, 2, -2}},
+             {{-2}, {1, 2, -1}},
+             {{2, -2}, {1, -1}},
+             {{1, 2}, {-1, -2}},
+             {{2}, {-1, -2}, {1}},
+             {{-1}, {2, -2}, {1}},
+             {{-2}, {2, -1}, {1}},
+             {{-1}, {2}, {1, -2}},
+             {{-2}, {2}, {1, -1}},
+             {{-1}, {-2}, {1, 2}},
+             {{-1}, {-2}, {2}, {1}}]
+        """
+        for sp in SetPartitionsAk_k.iterator(self):
+            if is_planar(sp):
+                yield sp
+
+class SetPartitionsPkhalf_k(SetPartitionsAkhalf_k):
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: A3 = SetPartitionsAk(3)
+            sage: P2p5 = SetPartitionsPk(2.5)
+            sage: all([ sp in P2p5 for sp in P2p5 ])
+            True
+            sage: len(filter(lambda x: x in P2p5, A3))
+            42
+            sage: P2p5.count()
+            42
+        """
+        if not SetPartitionsAkhalf_k.__contains__(self, x):
+            return False
+        if not is_planar(x):
+            return False
+        
+        return True
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr( SetPartitionsPk(2.5) )
+            'Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and that are planar'
+        """
+        return SetPartitionsAkhalf_k.__repr__(self) + " and that are planar"
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsPk(2.5).count()
+            42
+            sage: SetPartitionsPk(1.5).count()
+            5
+        """
+        return len(self.list())
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: SetPartitionsPk(1.5).list() #random
+            [{{1, 2, -2, -1}},
+             {{2, -2, -1}, {1}},
+             {{2, -2}, {1, -1}},
+             {{-1}, {1, 2, -2}},
+             {{-1}, {2, -2}, {1}}]
+
+        """
+        for sp in SetPartitionsAkhalf_k.iterator(self):
+            if is_planar(sp):
+                yield sp
+
+
+#####
+#T_k#
+#####
+SetPartitionsTk = create_set_partitions_function("T")
+SetPartitionsTk.__doc__ = """
+Returns the combinatorial class of set partitions of type T_k.
+These are planar set partitions where every block is of size 2.
+
+sage: T3 = SetPartitionsTk(3); T3
+Set partitions of {1, ..., 3, -1, ..., -3} with block size 2 and that are planar
+sage: T3.count()
+5
+
+sage: T3.first() #random
+{{1, -3}, {2, 3}, {-1, -2}}
+sage: T3.last() #random
+{{1, 2}, {3, -1}, {-3, -2}}
+sage: T3.random() #random
+{{1, -3}, {2, 3}, {-1, -2}}
+
+sage: T2p5 = SetPartitionsTk(2.5); T2p5
+Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and with block size 2 and that are planar
+sage: T2p5.count()
+2
+
+sage: T2p5.first() #random
+{{2, -2}, {3, -3}, {1, -1}}
+sage: T2p5.last() #random
+{{1, 2}, {3, -3}, {-1, -2}}
+
+"""
+class SetPartitionsTk_k(SetPartitionsBk_k):
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsTk(3))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with block size 2 and that are planar'
+        """
+        return SetPartitionsBk_k.__repr__(self) + " and that are planar"
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: T3 = SetPartitionsTk(3)
+            sage: A3 = SetPartitionsAk(3)
+            sage: all([ sp in T3 for sp in T3])
+            True
+            sage: len(filter(lambda x: x in T3, A3))
+            5
+            sage: T3.count()
+            5
+        """
+        if not SetPartitionsBk_k.__contains__(self, x):
+            return False
+
+        if not is_planar(x):
+            return False
+
+        return True
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsTk(2).count()
+            2
+            sage: SetPartitionsTk(3).count()
+            5
+            sage: SetPartitionsTk(4).count()
+            14
+            sage: SetPartitionsTk(5).count()
+            42
+        """
+        return catalan_number(self.k)
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: SetPartitionsTk(3).list() #random
+            [{{1, -3}, {2, 3}, {-1, -2}},
+             {{2, -2}, {3, -3}, {1, -1}},
+             {{1, 2}, {3, -3}, {-1, -2}},
+             {{-3, -2}, {2, 3}, {1, -1}},
+             {{1, 2}, {3, -1}, {-3, -2}}]
+        """
+        for sp in SetPartitionsBk_k.iterator(self):
+            if is_planar(sp):
+                yield sp
+
+class SetPartitionsTkhalf_k(SetPartitionsBkhalf_k):
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: A3 = SetPartitionsAk(3)
+            sage: T2p5 = SetPartitionsTk(2.5)
+            sage: all([ sp in T2p5 for sp in T2p5 ])
+            True
+            sage: len(filter(lambda x: x in T2p5, A3))
+            2
+            sage: T2p5.count()
+            2
+        """
+        if not SetPartitionsBkhalf_k.__contains__(self, x):
+            return False
+        if not is_planar(x):
+            return False
+        
+        return True
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsTk(2.5))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and with block size 2 and that are planar'
+        """
+        return SetPartitionsBkhalf_k.__repr__(self) + " and that are planar"
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsTk(2.5).count()
+            2
+            sage: SetPartitionsTk(3.5).count()
+            5
+            sage: SetPartitionsTk(4.5).count()
+            14
+        """
+        return catalan_number(self.k)
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: SetPartitionsTk(3.5).list() #random
+            [{{1, -3}, {2, 3}, {4, -4}, {-1, -2}},
+             {{2, -2}, {3, -3}, {1, -1}, {4, -4}},
+             {{1, 2}, {3, -3}, {4, -4}, {-1, -2}},
+             {{-3, -2}, {2, 3}, {1, -1}, {4, -4}},
+             {{1, 2}, {-3, -2}, {4, -4}, {3, -1}}]
+        """
+        for sp in SetPartitionsBkhalf_k.iterator(self):
+            if is_planar(sp):
+                yield sp
+
+
+
+SetPartitionsRk = create_set_partitions_function("R")
+SetPartitionsRk.__doc__ = """
+"""
+class SetPartitionsRk_k(SetPartitionsAk_k):
+    def __init__(self, k):
+        """
+        TESTS:
+           sage: R3 = SetPartitionsRk(3); R3
+           Set partitions of {1, ..., 3, -1, ..., -3} with at most 1 positive and negative entry in each block
+           sage: R3 == loads(dumps(R3))
+           True
+        """
+        self.k = k
+        SetPartitionsAk_k.__init__(self, k)
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsRk(3))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with at most 1 positive and negative entry in each block'
+        """
+        return SetPartitionsAk_k.__repr__(self) + " with at most 1 positive and negative entry in each block"
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: R3 = SetPartitionsRk(3)
+            sage: A3 = SetPartitionsAk(3)
+            sage: all([ sp in R3 for sp in R3])
+            True
+            sage: len(filter(lambda x: x in R3, A3))
+            34
+            sage: R3.count()
+            34
+        """
+        if not SetPartitionsAk_k.__contains__(self, x):
+            return False
+
+        for block in x:
+            if len(block) > 2:
+                return False
+            
+            negatives = 0
+            positives = 0
+            for i in block:
+                if i < 0:
+                    negatives += 1
+                else:
+                    positives += 1
+
+                if negatives > 1 or positives > 1:
+                    return False
+
+        return True
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsRk(2).count()
+            7
+            sage: SetPartitionsRk(3).count()
+            34
+            sage: SetPartitionsRk(4).count()
+            209
+            sage: SetPartitionsRk(5).count()
+            1546
+        """
+        return sum( [ binomial(self.k, l)**2*factorial(l) for l in range(self.k + 1) ] )
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: len(SetPartitionsRk(3).list() ) == SetPartitionsRk(3).count()
+            True
+        """
+        #The number of blocks with at most two things
+        positives = Set(range(1, self.k+1))
+        negatives = Set( [ -i for i in positives ] )
+
+        yield to_set_partition([],self.k)
+        for n in range(1,self.k+1):
+            for top in Subsets(positives, n):
+                t = list(top)
+                for bottom in Subsets(negatives, n):
+                    b = list(bottom)
+                    for permutation in Permutations(n):
+                        l = [ [t[i], b[ permutation[i] - 1 ] ] for i in range(n) ]
+                        yield to_set_partition(l, k=self.k)
+
+class SetPartitionsRkhalf_k(SetPartitionsAkhalf_k):
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: A3 = SetPartitionsAk(3)
+            sage: R2p5 = SetPartitionsRk(2.5)
+            sage: all([ sp in R2p5 for sp in R2p5 ])
+            True
+            sage: len(filter(lambda x: x in R2p5, A3))
+            7
+            sage: R2p5.count()
+            7
+        """
+        if not SetPartitionsAkhalf_k.__contains__(self, x):
+            return False
+
+        for block in x:
+            if len(block) > 2:
+                return False
+            
+            negatives = 0
+            positives = 0
+            for i in block:
+                if i < 0:
+                    negatives += 1
+                else:
+                    positives += 1
+
+                if negatives > 1 or positives > 1:
+                    return False
+
+        
+        return True
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsRk(2.5))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and with at most 1 positive and negative entry in each block'
+        """
+        return SetPartitionsAkhalf_k.__repr__(self) + " and with at most 1 positive and negative entry in each block"
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsRk(2.5).count()
+            7
+            sage: SetPartitionsRk(3.5).count()
+            34
+            sage: SetPartitionsRk(4.5).count()
+            209
+        """
+        return sum( [ binomial(self.k, l)**2*factorial(l) for l in range(self.k + 1) ] )
+
+    def iterator(self):
+        """
+        TESTS:
+
+        """
+        positives = Set(range(1, self.k+1))
+        negatives = Set( [ -i for i in positives ] )
+        
+        yield to_set_partition([[self.k+1, -self.k-1]], self.k+1)
+        for n in range(1,self.k+1):
+            for top in Subsets(positives, n):
+                t = list(top)
+                for bottom in Subsets(negatives, n):
+                    b = list(bottom)
+                    for permutation in Permutations(n):
+                        l = [ [t[i], b[ permutation[i] - 1 ] ] for i in range(n) ] + [ [self.k+1, -self.k-1] ]
+                        yield to_set_partition(l, k=self.k+1)
+
+
+SetPartitionsPRk = create_set_partitions_function("PR")
+SetPartitionsPRk.__doc__ = """
+"""
+class SetPartitionsPRk_k(SetPartitionsRk_k):
+    def __init__(self, k):
+        """
+        TESTS:
+           sage: PR3 = SetPartitionsPRk(3); PR3
+           Set partitions of {1, ..., 3, -1, ..., -3} with at most 1 positive and negative entry in each block and that are planar
+           sage: PR3 == loads(dumps(PR3))
+           True
+        """
+        self.k = k
+        SetPartitionsRk_k.__init__(self, k)
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsPRk(3))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with at most 1 positive and negative entry in each block and that are planar'
+        """
+        return SetPartitionsRk_k.__repr__(self) + " and that are planar"
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: PR3 = SetPartitionsPRk(3)
+            sage: A3 = SetPartitionsAk(3)
+            sage: all([ sp in PR3 for sp in PR3])
+            True
+            sage: len(filter(lambda x: x in PR3, A3))
+            20
+            sage: PR3.count()
+            20
+        """
+        if not SetPartitionsRk_k.__contains__(self, x):
+            return False
+
+        if not is_planar(x):
+            return False
+
+        return True
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsPRk(2).count()
+            6
+            sage: SetPartitionsPRk(3).count()
+            20
+            sage: SetPartitionsPRk(4).count()
+            70
+            sage: SetPartitionsPRk(5).count()
+            252
+        """
+        return binomial(2*self.k, self.k)
+
+    def iterator(self):
+        """
+        TESTS:
+            sage: len(SetPartitionsPRk(3).list() ) == SetPartitionsPRk(3).count()
+            True
+        """
+        #The number of blocks with at most two things
+        positives = Set(range(1, self.k+1))
+        negatives = Set( [ -i for i in positives ] )
+
+        yield to_set_partition([], self.k)
+        for n in range(1,self.k+1):
+            for top in Subsets(positives, n):
+                t = list(top)
+                t.sort()
+                for bottom in Subsets(negatives, n):
+                    b = list(bottom)
+                    b.sort(reverse=True)
+                    l = [ [t[i], b[ i ] ] for i in range(n) ]
+                    yield to_set_partition(l, k=self.k)
+
+class SetPartitionsPRkhalf_k(SetPartitionsRkhalf_k):
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: A3 = SetPartitionsAk(3)
+            sage: PR2p5 = SetPartitionsPRk(2.5)
+            sage: all([ sp in PR2p5 for sp in PR2p5 ])
+            True
+            sage: len(filter(lambda x: x in PR2p5, A3))
+            6
+            sage: PR2p5.count()
+            6
+        """
+        if not SetPartitionsRkhalf_k.__contains__(self, x):
+            return False
+
+        if not is_planar(x):
+            return False
+        
+        return True
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitionsPRk(2.5))
+            'Set partitions of {1, ..., 3, -1, ..., -3} with 3 and -3 in the same block and with at most 1 positive and negative entry in each block and that are planar'
+        """
+        return SetPartitionsRkhalf_k.__repr__(self) + " and that are planar"
+
+    def count(self):
+        """
+        TESTS:
+            sage: SetPartitionsPRk(2.5).count()
+            6
+            sage: SetPartitionsPRk(3.5).count()
+            20
+            sage: SetPartitionsPRk(4.5).count()
+            70
+        """
+        return binomial(2*self.k, self.k)
+
+    def iterator(self):
+        """
+        TESTS:
+
+        """
+        positives = Set(range(1, self.k+1))
+        negatives = Set( [ -i for i in positives ] )
+        
+        yield to_set_partition([[self.k+1, -self.k-1]],k=self.k+1)
+        for n in range(1,self.k+1):
+            for top in Subsets(positives, n):
+                t = list(top)
+                t.sort()
+                for bottom in Subsets(negatives, n):
+                    b = list(bottom)
+                    b.sort(reverse=True)
+                    l = [ [t[i], b[ i ] ] for i in range(n) ] + [ [self.k+1, -self.k-1] ]
+                    yield to_set_partition(l, k=self.k+1)
+
+#########################################################
+#Algebras
+
+class PartitionAlgebra_generic(CombinatorialAlgebra):
+    def __init__(self, R, cclass, n, k, name=None, prefix=None):
+        self.k = k
+        self.n = n
+
+        self._combinatorial_class = cclass
+
+        if name is None:
+            self._name = "Generic partition algebra with k = %s and n = %s and basis %s"%( self.k, self.n, cclass)
+        else:
+            self._name = name
+        
+        self._one = identity(ceil(self.k))
+        
+        if prefix is None:
+            self._prefix = ""
+        else:
+            self._prefix = prefix
+            
+        CombinatorialAlgebra.__init__(self, R)
+        
+    def _multiply_basis(self, left, right):
+        (sp, l) = set_partition_composition(left, right)
+        return {sp: self.n**l}
+
+
+class PartitionAlgebra_ak(PartitionAlgebra_generic):
+    def __init__(self, R, k, n, name=None):
+        if name is None:
+            name = "Partition algebra A_%s(%s)"%(k, n)
+        cclass = SetPartitionsAk(k)
+        PartitionAlgebra_generic.__init__(self, R, cclass, n, k, name=name, prefix="A")
+        
+class PartitionAlgebra_bk(PartitionAlgebra_generic):
+    def __init__(self, R, k, n, name=None):
+        if name is None:
+            name = "Partition algebra B_%s(%s)"%(k, n)
+        cclass = SetPartitionsBk(k)
+        PartitionAlgebra_generic.__init__(self, R, cclass, n, k, name=name, prefix="B")
+
+class PartitionAlgebra_sk(PartitionAlgebra_generic):
+    def __init__(self, R, k, n, name=None):
+        if name is None:
+            name = "Partition algebra S_%s(%s)"%(k, n)
+        cclass = SetPartitionsSk(k)
+        PartitionAlgebra_generic.__init__(self, R, cclass, n, k, name=name, prefix="S")
+
+class PartitionAlgebra_pk(PartitionAlgebra_generic):
+    def __init__(self, R, k, n, name=None):
+        if name is None:
+            name = "Partition algebra P_%s(%s)"%(k, n)
+        cclass = SetPartitionsPk(k)
+        PartitionAlgebra_generic.__init__(self, R, cclass, n, k, name=name, prefix="P")
+        
+class PartitionAlgebra_tk(PartitionAlgebra_generic):
+    def __init__(self, R, k, n, name=None):
+        if name is None:
+            name = "Partition algebra T_%s(%s)"%(k, n)
+        cclass = SetPartitionsTk(k)
+        PartitionAlgebra_generic.__init__(self, R, cclass, n, k, name=name, prefix="T")
+
+class PartitionAlgebra_rk(PartitionAlgebra_generic):
+    def __init__(self, R, k, n, name=None):
+        if name is None:
+            name = "Partition algebra R_%s(%s)"%(k, n)
+        cclass = SetPartitionsRk(k)
+        PartitionAlgebra_generic.__init__(self, R, cclass, n, k, name=name, prefix="R")
+
+class PartitionAlgebra_prk(PartitionAlgebra_generic):
+    def __init__(self, R, k, n, name=None):
+        if name is None:
+            name = "Partition algebra PR_%s(%s)"%(k, n)
+        cclass = SetPartitionsPRk(k)
+        PartitionAlgebra_generic.__init__(self, R, cclass, n, k, name=name, prefix="PR")
+        
+##########################################################
+                
+def is_planar(sp):
+    """
+    Returns True if the diagram corresponding to the set partition is planar;
+    otherwise, it returns False.
+
+    EXAMPLES:
+        sage: import sage.combinat.partition_algebra as pa
+        sage: pa.is_planar( pa.to_set_partition([[1,-2],[2,-1]]))
+        False
+        sage: pa.is_planar( pa.to_set_partition([[1,-1],[2,-2]]))
+        True
+    """
+    to_consider = map(list, sp)
+
+    #Singletons don't affect planarity
+    to_consider = filter(lambda x: len(x) > 1, to_consider)
+    n = len(to_consider)
+    
+    for i in range(n):
+        #Get the positive and negative entries of this
+        #part
+        ap = filter(lambda x: x>0, to_consider[i])
+        an = filter(lambda x: x<0, to_consider[i])
+        an = map(abs, an)
+        #print a, ap, an
+
+
+        #Check if a includes numbers in both the top and bottom rows
+        if len(ap) > 0 and len(an) > 0:
+
+            for j in range(n):
+                if i == j:
+                    continue
+                #Get the postitive and negative entries of this part
+                bp = filter(lambda x: x>0, to_consider[j])
+                bn = filter(lambda x: x<0, to_consider[j])
+                bn = map(abs, bn)
+
+                #Skip the ones that don't involve numbers in both
+                #the bottom and top rows
+                if len(bn) == 0 or len(bp) == 0:
+                    continue
+
+                #Make sure that if min(bp) > max(ap)
+                #then min(bn) >  max(an)
+                if max(bp) > max(ap):
+                    if min(bn) < min(an):
+                        return False
+
+
+        #Go through the bottom and top rows
+        for row in [ap, an]:
+            if len(row) > 1:
+                row.sort()
+                for s in range(len(row)-1):
+                    if row[s] + 1 == row[s+1]:
+                        #No gap, continue on
+                        continue
+                    else:
+                        rng = range(row[s] + 1, row[s+1])
+                        
+                        #Go through and make sure any parts that
+                        #contain numbers in this range are completely
+                        #contained in this range
+                        for j in range(n):
+                            if i == j:
+                                continue
+
+                            #Make sure we make the numbers negative again
+                            #if we are in the bottom row
+                            if row is ap:
+                                sr = Set(rng)
+                            else:
+                                sr = Set(map(lambda x: -1*x, rng))
+
+                            
+                            sj = Set(to_consider[j])
+                            intersection = sr.intersection(sj)
+                            if intersection:
+                                if sj != intersection:
+                                    return False
+
+    return True
+
+   
+def to_graph(sp):
+    """
+    Returns a graph representing the set partition sp.
+    
+    EXAMPLES:
+        sage: import sage.combinat.partition_algebra as pa
+        sage: g = pa.to_graph( pa.to_set_partition([[1,-2],[2,-1]])); g
+        Graph on 4 vertices
+       
+        sage: g.vertices() #random
+        [1, 2, -2, -1]
+        sage: g.edges() #random
+        [(1, -2, None), (2, -1, None)]
+    """
+    g = Graph()
+    for part in sp:
+        part_list = list(part)
+        if len(part_list) > 0:
+            g.add_vertex(part_list[0])
+        for i in range(1, len(part_list)):
+            g.add_vertex(part_list[i])
+            g.add_edge(part_list[i-1], part_list[i])
+    return g
+
+def pair_to_graph(sp1, sp2):
+    """
+    Returns a graph consisting of the graphs of set partitions sp1
+    and sp2 along with edges joining the bottom row (negative numbers)
+    of sp1 to the top row (positive numbers) of sp2.
+
+    EXAMPLES:
+        sage: import sage.combinat.partition_algebra as pa
+        sage: sp1 = pa.to_set_partition([[1,-2],[2,-1]])
+        sage: sp2 = pa.to_set_partition([[1,-2],[2,-1]])        
+        sage: g = pa.pair_to_graph( sp1, sp2 ); g
+        Graph on 8 vertices
+
+
+        sage: g.vertices() #random
+        [(1, 2), (-1, 1), (-2, 2), (-1, 2), (-2, 1), (2, 1), (2, 2), (1, 1)]
+        sage: g.edges() #random
+        [((1, 2), (-1, 1), None),
+         ((1, 2), (-2, 2), None),
+         ((-1, 1), (2, 1), None),
+         ((-1, 2), (2, 2), None),
+         ((-2, 1), (1, 1), None),
+         ((-2, 1), (2, 2), None)]
+    """
+    g = Graph()
+
+    #Add the first set partition to the graph
+    for part in sp1:
+        part_list = list(part)
+        if len(part_list) > 0:
+            g.add_vertex( (part_list[0],1) )
+
+            #Add the edge to the second part of the graph
+            if part_list[0] < 0 and len(part_list) > 1:
+                g.add_edge( (part_list[0], 1), (abs(part_list[0]),2)  )
+            
+        for i in range(1, len(part_list)):
+            g.add_vertex( (part_list[i],1) )
+            
+            #Add the edge to the second part of the graph
+            if part_list[i] < 0:
+                g.add_edge( (part_list[i], 1), (abs(part_list[i]),2) )
+
+            #Add the edge between parts
+            g.add_edge( (part_list[i-1],1), (part_list[i],1) )
+
+    #Add the second set partition to the graph
+    for part in sp2:
+        part_list = list(part)
+        if len(part_list) > 0:
+            g.add_vertex( (part_list[0],2) )
+        for i in range(1, len(part_list)):
+            g.add_vertex( (part_list[i],2) )
+            g.add_edge( (part_list[i-1],2), (part_list[i],2) )
+
+            
+    return g
+
+def propagating_number(sp):
+    """
+    Returns the propagating number of the set partition sp.
+    The propagating number is the number of blocks with
+    both a positive and negative number.
+
+    EXAMPLES:
+        sage: import sage.combinat.partition_algebra as pa
+        sage: sp1 = pa.to_set_partition([[1,-2],[2,-1]])
+        sage: sp2 = pa.to_set_partition([[1,2],[-2,-1]])        
+        sage: pa.propagating_number(sp1)
+        2
+        sage: pa.propagating_number(sp2)
+        0
+    """
+    pn = 0
+    for part in sp:
+        if min(part) < 0  and max(part) > 0:
+            pn += 1
+    return pn
+
+def to_set_partition(l,k=None):
+    """
+    Coverts a list of a list of numbers to a set partitions. Each
+    list of numbers in the outer list specifies the numbers
+    contained in one of the blocks in the set partition.
+
+    If k is specified, then the set partition will be a
+    set partition of {1, ..., k, -1, ..., -k}.  Otherwise,
+    k will default to the minimum number needed to contain all
+    of the specified numbers.
+
+    EXAMPLES:
+        sage: import sage.combinat.partition_algebra as pa
+        sage: pa.to_set_partition([[1,-1],[2,-2]]) == pa.identity(2)
+        True
+    """
+    if k == None:
+        if l == []:
+            return Set([])
+        else:
+            k = max( map( lambda x: max( map(abs, x) ), l) )
+
+    to_be_added = Set( range(1, k+1) + map(lambda x: -1*x, range(1, k+1) ) )
+    
+    sp = []
+    for part in l:
+        spart = Set(part)
+        to_be_added -= spart
+        sp.append(spart)
+
+    for singleton in to_be_added:
+        sp.append(Set([singleton]))
+
+    return Set(sp)
+
+def identity(k):
+    """
+    Returns the identity set partition {{1, -1}, ..., {k, -k}}
+
+    EXAMPLES:
+        sage: import sage.combinat.partition_algebra as pa
+        sage: pa.identity(2)
+        {{2, -2}, {1, -1}}
+    """
+    res = []
+    for i in range(1, k+1):
+        res.append(Set([i, -i]))
+    return Set(res)
+
+
+def set_partition_composition(sp1, sp2):
+    """
+    Returns a tuple consisting of the composition of the set
+    partitions sp1 and sp2 and the number of components removed
+    from the middle rows of the graph.
+
+    EXAMPLES:
+        sage: import sage.combinat.partition_algebra as pa
+        sage: sp1 = pa.to_set_partition([[1,-2],[2,-1]])
+        sage: sp2 = pa.to_set_partition([[1,-2],[2,-1]])
+        sage: pa.set_partition_composition(sp1, sp2) == (pa.identity(2), 0)
+        True
+    """
+    g = pair_to_graph(sp1, sp2)
+    connected_components = g.connected_components()
+
+    res = []
+    total_removed = 0
+    for cc in connected_components:
+        #Remove the vertices that live in the middle two rows
+        new_cc = filter(lambda x: not ( (x[0]<0 and x[1] == 1) or (x[0]>0 and x[1]==2)), cc)
+
+        if new_cc == []:
+            if len(cc) > 1:
+                total_removed += 1
+        else:
+            res.append( Set(map(lambda x: x[0], new_cc)) )
+
+
+    return ( Set(res), total_removed )
+        
Index: sage/combinat/partitions_c.cc
===================================================================
--- sage/combinat/partitions_c.cc	(revision 5746)
+++ sage/combinat/partitions_c.cc	(revision 6960)
@@ -1,4 +1,5 @@
-/*      Author:     Jonathan Bober
- *      Version:    .4
+/*
+ *      Author:     Jonathan Bober
+ *      Version:    .6
  *
  *      This program computes p(n), the number of integer partitions of n, using Rademacher's
@@ -83,12 +84,11 @@
  */
 
-
 #if defined(__sun)
-extern long double fabsl (long double);
-extern long double sinl (long double);
-extern long double cosl (long double);
-extern long double sqrtl (long double);
-extern long double coshl (long double);
-extern long double sinhl (long double);
+extern "C" long double fabsl (long double);
+extern "C" long double sinl (long double);
+extern "C" long double cosl (long double);
+extern "C" long double sqrtl (long double);
+extern "C" long double coshl (long double);
+extern "C" long double sinhl (long double);
 #endif
 
@@ -100,4 +100,5 @@
 
 #include <cmath>
+#include <cstdlib>
 
 #include <iostream>
@@ -108,27 +109,73 @@
 #include <gmp.h>
 
-const bool debug = false;
-//const bool debug = true;
-
-const bool debugs = false;
-//const bool debugf = true;
-const bool debugf = false;
-//const bool debuga = true;
-const bool debuga = false;
-//const bool debugt = true;
-const bool debugt = false;
+#include <qd/qd_real.h>
+#include <qd/dd_real.h>
+#include <qd/fpu.h>
+
+using namespace std;
 
 using std::cout;
 using std::endl;
 
-const unsigned int min_precision = DBL_MANT_DIG;
-const unsigned int double_precision = DBL_MANT_DIG;
-const unsigned int long_double_precision = LDBL_MANT_DIG;
-
-//const unsigned int level_two_precision = long_double_precision; // qd_real precision
-const unsigned int level_two_precision = 200; // qd_real precision
-const unsigned int level_three_precision = 128;
+/*****************************************************************************
+ *
+ *      We begin be declaring all the constant global variables.
+ *
+ ****************************************************************************/
+
+// First, some variables that can be set to have the program
+// output some information that might be useful for debugging.
+
+const bool debug = false;                                       // If true, output some random stuff
+
+const bool debug_precision = false;                             // If true, output information that might be useful for
+                                                                // debugging the precision setting code.
+                                        
+const bool debugs = false;                                      // If true, output informaiton that might be useful for
+                                                                // debugging the various s() functions.
+const bool debugf = false;                                      // Same for the f() functions.
+const bool debuga = false;                                      // Same for the a() functions.
+const bool debugt = false;                                      // Same for the t() functions.
+
+#if FLT_RADIX != 2
+#error I don't know what to do when the float radix is not 2.
+#endif
+// Note - it might be unreasonable to not support a float radix other than
+// 2, but apparently gcc doesn't either. See http://gcc.gnu.org/ml/fortran/2006-12/msg00032.html.
+
+
+const unsigned int min_precision = DBL_MANT_DIG;                            // The minimum precision that we will ever use.
+const unsigned int double_precision = DBL_MANT_DIG;                         // The assumed precision of a double.
+
+
+const unsigned int long_double_precision = (LDBL_MANT_DIG == 106) ? double_precision : LDBL_MANT_DIG;
+                                                                            // The assumed precision of a long double.
+                                                                            // Note: On many systems double_precision = long_double_precision. This is OK, as
+                                                                            // the long double stage of the computation will just be skipped.
+                                                                            // 
+                                                                            // NOTE: If long_double_precision > dd_precision, then, again, long doubles
+                                                                            //      will not ever be used. It would be nice if this were fixed.
+
+
+const unsigned int qd_precision = 200;                          // The assumed precision of a qd_real. (Note, qd_reals should have a precision of
+                                                                // 4 * double_precision = 4*53, but since we need the library to be compiled with
+                                                                // "sloppy" multiplication and division if we want it to be fast, so we only count
+                                                                // on it for a little less precision.
+const unsigned int dd_precision = 100;                          // The assumed precision for a dd_real. (Same note applies here.)
+
+
+
+// Second, some constants that control the precision at which we compute.
+
+// When we compute the terms of the Rademacher series, we start by computing with
+// mpfr_t variables. But for efficiency we switch to special purpose code when
+// we don't need as much precision. These constants control the various
+// precision levels at which we switch to different special
+// purpose functions.
+
+// const unsigned int level_one_precision = infinity        // We don't actually use this, but if we did it would be infinite.
+const unsigned int level_two_precision = qd_precision;
+const unsigned int level_three_precision = dd_precision;
 const unsigned int level_four_precision = long_double_precision;
-//const unsigned int level_two_precision = double_precision;
 const unsigned int level_five_precision = double_precision;
 
@@ -136,10 +183,205 @@
 const double d_pi = ld_pi;
 
-bool test(bool longtest = false);
-
-void cospi (mpfr_t res, mpfr_t x);
-
-
-
+// Third, the rounding mode for mpfr.
+const mp_rnd_t round_mode = GMP_RNDN;
+
+/*****************************************************************************
+ *
+ *  We are finished declaring constants, and next declare semi-constant
+ *  variables. These are all set just once per call to part(n).
+ *
+ *  All of these are set in initialize_constants(), and the mpfr_t variables
+ *  are cleared in clear_constants().
+ *
+ ****************************************************************************/
+
+mpfr_t mp_one_over_12, mp_one_over_24, mp_sqrt2, mp_sqrt3, mp_pi, half, fourth;         // These need to be set at run time
+                                                                                        // because we don't know how much precision we will need
+                                                                                        // until we know for what n we are computing p(n).
+
+qd_real qd_one_over_12, qd_one_over_24, qd_sqrt2, qd_sqrt3, qd_pi, qd_half, qd_fourth;  // Technically, these could be set at compile time.
+dd_real dd_one_over_12, dd_one_over_24, dd_sqrt2, dd_sqrt3, dd_pi, dd_half, dd_fourth;  // but that would probably not be worth the effort.
+qd_real qd_pi_sqrt2;                                                                    //
+dd_real dd_pi_sqrt2;                                                                    //
+
+mpfr_t mp_A, mp_B, mp_C, mp_D;                                                          // These "constants" all depend on n, and 
+qd_real qd_A, qd_B, qd_C, qd_D;                                                         // are used many times in f() and mp_f().
+dd_real dd_A, dd_B, dd_C, dd_D;                                                         //
+double d_A, d_B, d_C, d_D;                                                              //
+long double ld_A, ld_B, ld_C, ld_D;                                                     //
+
+
+/*****************************************************************************
+ *
+ * We next declare the variables that actually vary. It is cumbersome to have
+ * so many global variables, but it is somewhat necessary since we want to call
+ * the functions mpz_init(), mpq_init(), mpfr_init(), and the corresponding
+ * clear() functions as little as possible.
+ *
+ ****************************************************************************/
+
+mpz_t ztemp1;                                                                   // These are initialized in the function initialize_mpz_and_mpq_variables(), and
+mpq_t qtemps, qtempa, qtempa2;                                                  // cleared in the function clear_mpz_and_mpq_variables().
+                                                                                // qtemps is used by q_s() and qtempa and qtempa2() are used by mp_a().
+                                                                                //
+                                                                                // ztemp1 is only used in one function, and the code where is it used is actually unlikely
+                                                                                // to be used for any input, so it should be erased.
+
+mpfr_t tempa1, tempa2, tempf1, tempf2, temps1, temps2;                          // These are all initialized by initialize_mpfr_variables(), and cleared by
+                                                                                // clear_mpfr_variables().
+                                                                                // NAMING CONVENTIONS:
+                                                                                //
+                                                                                // -tempa1 and tempa2 are two variables available for use
+                                                                                //      in the function mp_a()
+                                                                                //
+                                                                                // -tempf1 and tempf2 are two variables available for use
+                                                                                //      in the function mp_f()
+                                                                                //
+                                                                                // -etc...
+
+mpfr_t tempc1, tempc2;                                                          // temp variables used by cospi()
+
+
+/*****************************************************************************
+ *
+ * End of Global Variables, beginning of function declarations
+ *
+ ****************************************************************************/
+
+// 
+// A listing of the main functions, in "conceptual" order.
+//
+
+int part(mpz_t answer, unsigned int n);
+
+static void mp_t(mpfr_t result, unsigned int n);                                // Compute t(n,N) for an N large enough, and with a high enough precision, so that
+                                                                                // |p(n) - t(n,N)| < .5
+
+static unsigned int compute_initial_precision(unsigned int n);                  // computes the precision required to accurately compute p(n)
+
+static void initialize_constants(unsigned int prec, unsigned int n);            // Once we know the precision that we will need, we precompute
+                                                                                // some commonly used constants.
+
+static unsigned int compute_current_precision(unsigned int n, unsigned int N, unsigned int extra);  // Computed the precision required to
+                                                                                // accurately compute the tail of the rademacher series
+                                                                                // assuming that N terms have already been computed.
+                                                                                // This is called after computing each summand, unless
+                                                                                // we have already reached the minimum precision.
+                                                                                //
+                                                                                // Reducing the precision as fast as possible is key to
+                                                                                // fast performance.
+
+static double compute_remainder(unsigned int n, unsigned int N);                // Gives an upper bound on the error that occurs
+                                                                                // when only N terms of the Rademacher series have been
+                                                                                // computed.
+                                                                                //
+                                                                                // This should only be called when we know that compute_current_precision
+                                                                                // will return min_precision. Otherwise the error will be too large for
+                                                                                // it to compute.
+
+
+//
+// The following functions are all called in exactly one place, so
+// we could ask the compiler to inline everything. Actually making this
+// work properly requires changing some compiler options, and doesn't
+// provide much improvement, however.
+//
+
+static void mp_f(mpfr_t result, unsigned int k);                                // See introduction for an explanation of these functions.
+static void q_s(mpq_t result, unsigned int h, unsigned int k);                  //
+static void mp_a(mpfr_t result, unsigned int n, unsigned int k);                //
+
+template <class T> static inline T a(unsigned int n, unsigned int k);           // Template versions of the above functions for computing with
+template <class T> static inline T f(unsigned int k);                           // low precision. Currently used for computing with qd_real, dd_real,
+template <class T> static inline T s(unsigned int h, unsigned int k);           // long double, and double.
+
+
+//
+// The following are a bunch of "fancy macros" designed so that in the templated code
+// for a, for example, when we need to use pi, we just call pi<T>() to get pi to
+// the proper precision. The compiler should inline these, so using one of these
+// functions is just as good as using a constant, and since these functions are static
+// they shouldn't even appear in the object code generated.
+
+template <class T> static inline T pi(){ return ld_pi; }
+template <> static inline qd_real pi() { return qd_pi; }
+template <> static inline dd_real pi() { return dd_pi; }
+
+template <class T> static inline T sqrt2() {return sqrt(2.0L);}
+template <> static inline qd_real sqrt2() {return qd_sqrt2;}
+template <> static inline dd_real sqrt2() {return dd_sqrt2;}
+
+template <class T> static inline T sqrt3() {return sqrt(3.0L);}
+template <> static inline qd_real sqrt3() {return qd_sqrt3;}
+template <> static inline dd_real sqrt3() {return dd_sqrt3;}
+
+template <class T> static inline T A() {return 1;}
+template <> static inline double A() {return d_A;}
+template <> static inline long double A() {return ld_A;}
+template <> static inline qd_real A() {return qd_A;}
+template <> static inline dd_real A() {return dd_A;}
+
+template <class T> static inline T B() {return 1;}
+template <> static inline double B() {return d_B;}
+template <> static inline long double B() {return ld_B;}
+template <> static inline qd_real B() {return qd_B;}
+template <> static inline dd_real B() {return dd_B;}
+
+template <class T> static inline T C() {return 1;}
+template <> static inline double C() {return d_C;}
+template <> static inline long double C() {return ld_C;}
+template <> static inline qd_real C() {return qd_C;}
+template <> static inline dd_real C() {return dd_C;}
+
+template <class T> static inline T D() {return 1;}
+template <> static inline double D() {return d_D;}
+template <> static inline long double D() {return ld_D;}
+template <> static inline qd_real D() {return qd_D;}
+template <> static inline dd_real D() {return dd_D;}
+
+template <class T> static inline T pi_sqrt2() {return 1;}
+template <> static inline double pi_sqrt2() {return d_pi * sqrt(2.0);}
+template <> static inline long double pi_sqrt2() {return ld_pi * sqrt(2.0L);}
+template <> static inline qd_real pi_sqrt2() {return qd_pi_sqrt2;}
+template <> static inline dd_real pi_sqrt2() {return dd_pi_sqrt2;}
+
+template <class T> static inline T one_over_12() {return 1;}
+template <> static inline double one_over_12() {return 1.0/12.0;}
+template <> static inline long double one_over_12() {return 1.0L/12.0L;}
+template <> static inline qd_real one_over_12() {return qd_one_over_12;}
+template <> static inline dd_real one_over_12() {return dd_one_over_12;}
+
+// A few utility functions...
+
+static inline long GCD(long a, long b);
+static int test(bool longtest = false, bool forever = false);                   // Runs a bunch of tests to make sure
+                                                                                // that we are getting the right answers.
+                                                                                // Tests are based on a few "known" values that
+                                                                                // have been verified by other programs, and
+                                                                                // also on known congruences for p(n)
+
+static void cospi (mpfr_t res, mpfr_t x);                                       // Puts cos(pi x) in result. This is not currently    
+                                                                                // used, but should be faster than using mpfr_cos,
+                                                                                // according to comments in the file part.c
+                                                                                // mentioned in the introduction.   
+                                                                                // test
+
+static int grab_last_digits(char * output, int n, mpfr_t x);                    // Might be useful for debugging, but
+                                                                                // don't use it for anything else.
+                                                                                // (See function definition for more information.)
+
+
+int main(int argc, char *argv[]);                                               // This program is mainly meant for inclusion
+                                                                                // in SAGE (or any other program, if anyone
+                                                                                // feels like it). We include a main() function
+                                                                                // anyway, because it is useful to compile
+                                                                                // this as a standalone program
+                                                                                // for testing purposes.
+
+/***********************************************************************
+ *
+ * That should be the end of both function and variable definitions.
+ *
+ **********************************************************************/
 
 // The following function can be useful for debugging in come circumstances, but should not be used for anything else 
@@ -177,60 +419,4 @@
 
 
-long GCD(long a, long b);
-
-unsigned int calc_precision(unsigned int n, unsigned int N);
-
-//mpfr versions
-
-mpz_t ztemp1, ztemp2, ztemp3;
-mpq_t qtemp1, qtemp2, qtemp3;
-
-mpfr_t mp_one_over_12, mp_one_over_24, mp_sqrt2, mp_sqrt3, mp_pi, half, fourth;
-mpfr_t mp_A, mp_B, mp_C, mp_D;
-
-
-mp_rnd_t round_mode = GMP_RNDN;
-
-mpfr_t tempa1, tempa2, tempf1, tempf2, temps1, temps2, tempt1, tempt2;  // temp variables for different functions, with precision set and cleared by initialize_mpfr_variables
-mpfr_t tempc1, tempc2; // temp variable used by cospi()
-
-
-bool mp_vars_initialized = false;
-
-mp_prec_t mp_precision;
-
-void initialize_constants(unsigned int prec, unsigned int n);
-//void mp_f_precompute(unsigned int n);
-void mp_f(mpfr_t result, unsigned int k);
-void mp_s(mpfr_t result, unsigned int j, unsigned int q);
-void mp_a(mpfr_t result, unsigned int n, unsigned int k);
-void mp_t(mpfr_t result, unsigned int n);
-
-unsigned int compute_initial_precision(unsigned int n);     // computes the precision required to accurately compute p(n)
-unsigned int compute_current_precision(unsigned int n, unsigned int N); // computed the precision required to
-                                                                        // accurately compute the tail of the rademacher series
-                                                                        // assuming that N terms have already been computed
-
-double compute_remainder(unsigned int n, unsigned int N);   // Gives an upper bound on the error that occurs
-                                                            // when only N terms of the Rademacher series have been
-                                                            // computed. NOTE: should only be called when we already know
-                                                            // that the error is small (ie, compute_current_precision returns
-                                                            // a small number, eg, something < 32)
-
-//low precision (double) versions of the functions:
-
-double d_A, d_B, d_C, d_D;
-long double ld_A, ld_B, ld_C, ld_D;
-
-
-double d_f(unsigned int k);
-double d_s(unsigned int h,unsigned int q);
-double d_a(unsigned int n, unsigned int k);
-double d_t(unsigned int n, unsigned int N);
-
-long double ld_f(unsigned int k);
-long double ld_s(unsigned int h,unsigned int q);
-long double ld_a(unsigned int n, unsigned int k);
-long double ld_t(unsigned int n, unsigned int N);
 
 unsigned int compute_initial_precision(unsigned int n) {
@@ -267,11 +453,24 @@
 }
 
-unsigned int compute_current_precision(unsigned int n, unsigned int N) {
-    // we want to compute
+unsigned int compute_current_precision(unsigned int n, unsigned int N, unsigned int extra = 0) {
+    // Roughly, we compute
+    // 
     //      log(A/sqrt(N) + B*sqrt(N/(n-1))*sinh(C * sqrt(n) / N) / log(2)
     //
-    //  where A, B, and C are the constants listed below. These error bounds
-    //  are given in the paper by Rademacher listed at the top of this file.
-    //
+    // where A, B, and C are the constants listed below. These error bounds
+    // are given in the paper by Rademacher listed at the top of this file.
+    // We then return this + extra, if extra != 0. If extra == 0, return with
+    // what is probably way more extra precision than is needed.
+    // 
+    // extra should probably have been set by a call to compute_extra_precision()
+    // before this function was called.
+
+
+    // n = the number for which we are computing p(n)
+    // N = the number of terms that have been computed so far
+
+    // if N is 0, then we can't use the above formula (because we would be
+    // dividing by 0).
+    if(N == 0) return compute_initial_precision(n) + extra;
 
     mpfr_t A, B, C;
@@ -285,31 +484,43 @@
 
     mpfr_t error, t1, t2;
-    mpfr_init2(error, 32);      // we shouldn't need much precision here since we just need the most significant bit
+    mpfr_init2(error, 32);                                // we shouldn't need much precision here since we just need the most significant bit
     mpfr_init2(t1, 32);
     mpfr_init2(t2, 32);
 
-    mpfr_set(error, A, round_mode);      // error = A
-    mpfr_sqrt_ui(t1, N, round_mode);        // t1 = sqrt(N)
-    mpfr_div(error, error, t1, round_mode); // error = A/sqrt(N)
-
-
-    mpfr_sqrt_ui(t1, n, round_mode);        // t1 = sqrt(n)
-    mpfr_mul(t1, t1, C, round_mode);     // t1 = C * sqrt(n)
-    mpfr_div_ui(t1, t1, N, round_mode);     // t1 = C * sqrt(n) / N
-    mpfr_sinh(t1, t1, round_mode);          // t1 = sinh( ditto )
-    mpfr_mul(t1, t1, B, round_mode);     // t1 = B * sinh( ditto )
-
-    mpfr_set_ui(t2, N, round_mode);         // t2 = N
-    mpfr_div_ui(t2, t2, n-1, round_mode);       // t2 = N/(n-1)
-    mpfr_sqrt(t2, t2, round_mode);          // t2 = sqrt( ditto )
-    
-    mpfr_mul(t1, t1, t2, round_mode);       // t1 = B * sqrt(N/(n-1)) * sinh(C * sqrt(n)/N)
-
-    mpfr_add(error, error, t1, round_mode); // error = (ERROR ESTIMATE)
-    
-    unsigned int p = mpfr_get_exp(error);   // I am almost certain that this does the right thing
-                                                // (The 3 is for good luck.)
-    
-    p = p + (unsigned int)ceil(log(n)/log(2));
+    mpfr_set(error, A, round_mode);                       // error = A
+    mpfr_sqrt_ui(t1, N, round_mode);                      // t1 = sqrt(N)
+    mpfr_div(error, error, t1, round_mode);               // error = A/sqrt(N)
+
+
+    mpfr_sqrt_ui(t1, n, round_mode);                      // t1 = sqrt(n)
+    mpfr_mul(t1, t1, C, round_mode);                      // t1 = C * sqrt(n)
+    mpfr_div_ui(t1, t1, N, round_mode);                   // t1 = C * sqrt(n) / N
+    mpfr_sinh(t1, t1, round_mode);                        // t1 = sinh( ditto )
+    mpfr_mul(t1, t1, B, round_mode);                      // t1 = B * sinh( ditto )
+
+    mpfr_set_ui(t2, N, round_mode);                       // t2 = N
+    mpfr_div_ui(t2, t2, n-1, round_mode);                 // t2 = N/(n-1)
+    mpfr_sqrt(t2, t2, round_mode);                        // t2 = sqrt( ditto )
+    
+    mpfr_mul(t1, t1, t2, round_mode);                     // t1 = B * sqrt(N/(n-1)) * sinh(C * sqrt(n)/N)
+
+    mpfr_add(error, error, t1, round_mode);               // error = (ERROR ESTIMATE)
+                                                         
+    unsigned int p = mpfr_get_exp(error);                 // I am not 100% certain that this always does the right thing.
+                                                          // (It should be the case that p is now the number of bits
+                                                          // required to hold the integer part of the error.)
+    
+
+    if(extra == 0) {
+        p = p + (unsigned int)ceil(log(n)/log(2));        // This is a stupid case to fall back on,
+                                                          // left over from earlier versions of this code.
+                                                          // It really should never be used.
+    }
+    else {
+        p = p + extra;                                    // Recall that the extra precision should be
+                                                          // large enough so that the accumulated errors
+                                                          // in all of the computations that we make
+                                                          // are not big enough to matter.
+    }
 
     if(debug) {
@@ -330,10 +541,65 @@
 
     if(p > min_precision) {
-        return p;                           // don't want to return < min_precision
-                                            // Note that when we hit the minimum precision
-                                            // we should switch over to using C doubles instead
-                                            // of mpfr types.
+        return p;                                         // We don't want to return < min_precision.
+                                                          // Note that when the code that calls this
+                                                          // function finds that the returned result
+                                                          // is min_precision, it should stop calling
+                                                          // this function, since the result won't change
+                                                          // after that. Also, it should probably switch
+                                                          // to computations with doubles, and should
+                                                          // start calling compute_remainder().
     }
     return min_precision;
+}
+
+int compute_extra_precision(unsigned int n, double error = .25) {
+    // Return the number of terms of the Rachemacher series that
+    // we will need to compute to get a remainder of less than error
+    // in absolute value, and then return the extra precision
+    // that will guarantee that the accumulated error after computing
+    // that number of steps will be less than .5 - error.
+    // 
+    // How this works:
+    // We first need to figure out how many terms of the series we are going to
+    // need to compute. That is, we need to know how large k needs to be
+    // for compute_remainder(n,k) to return something smaller than error. There
+    // might be a clever way to do this, but instead we just keep calling
+    // compute_current_precision() until we know that the error will be
+    // small enough to call compute_remainder(). Then we just call compute_remainder()
+    // until the error is small enough.
+    // 
+    // Now that we know how many terms we will need to compute, k, we compute
+    // the number of bits required to accurately store (.5 - error)/k. This ensures
+    // that the total error introduced when we add up all k terms of the sum
+    // will be less than (.5 - error). This way, if everything else works correctly,
+    // then the sum will be within .5 of the correct (integer) answer, and we
+    // can correctly find it by rounding.
+    unsigned int k = 1;
+    for( ; compute_current_precision(n,k,0) > double_precision; k += 100) {
+    }
+
+    for( ; compute_remainder(n, k) > error ; k += 100)  {
+    }
+    if(debug_precision) {
+        cout << "To compute p(" << n << ") we will add up approximately " << k << " terms from the Rachemacher series." << endl;
+    }
+    int bits = (int)((log(k/(.5 - error)))/log(2)) + 5;   // NOTE: reducing the number of bits by 3 here is known to cause errors
+                                                          // Why the extra 5 bits? Anytime we call a function, eg mp_a(),
+                                                          // we end up doing a bunch of arithmetic operations, and if
+                                                          // we want the result of those operations to be accurate
+                                                          // within (.5 - error)/k, then we need that function to use
+                                                          // a slightly higher working precision, which should be 
+                                                          // independent of n.
+                                                          // TODO:
+                                                          // Extensive trial and error has found 3 to be the smallest value
+                                                          // that doesn't seem to produce any wrong answers. Thus, to
+                                                          // be safe, we use 5 extra bits.
+                                                          // (Extensive trial and error means compiling this file to get
+                                                          // a.out and then running './a.out testforever' for a few hours.)
+                                                          
+                                                          
+                                                       
+
+    return bits;
 }
 
@@ -382,6 +648,4 @@
     mpfr_init2(tempf1, prec);
     mpfr_init2(tempf2, prec);
-    mpfr_init2(tempt1, prec);
-    mpfr_init2(tempt2, prec);
     mpfr_init2(temps1, prec);
     mpfr_init2(temps2, prec);
@@ -395,6 +659,4 @@
     mpfr_clear(tempf1);
     mpfr_clear(tempf2);
-    mpfr_clear(tempt1);
-    mpfr_clear(tempt2);
     mpfr_clear(temps1);
     mpfr_clear(temps2);
@@ -417,6 +679,5 @@
     // NOTE: Calls to this function must be paired with calls to clear_constants()
     static bool init = false;
-    mp_precision = prec;
-    mp_prec_t p = mp_precision;
+    mp_prec_t p = prec;
     
     mpfr_init2(mp_one_over_12,p); mpfr_init2(mp_one_over_24,p); mpfr_init2(mp_sqrt2,p); mpfr_init2(mp_sqrt3,p); mpfr_init2(mp_pi,p);
@@ -425,16 +686,27 @@
     init = true;
     
+    unsigned int cw;
+    fpu_fix_start(&cw);
+
     mpfr_set_ui(mp_one_over_12, 1, round_mode);                             // mp_one_over_12 = 1/12
     mpfr_div_ui(mp_one_over_12, mp_one_over_12, 12, round_mode);            //
 
+    qd_one_over_12 = "0.083333333333333333333333333333333333333333333333333333333333333333";
+    dd_one_over_12 = "0.083333333333333333333333333333333333333333333333333333333333333333";
 
     mpfr_set_ui(mp_one_over_24, 1, round_mode);                             // mp_one_over_24 = 1/24
     mpfr_div_ui(mp_one_over_24, mp_one_over_24, 24, round_mode);            //
 
+    qd_one_over_24 = "0.041666666666666666666666666666666666666666666666666666666666666667";
+    dd_one_over_24 = "0.041666666666666666666666666666666666666666666666666666666666666667";
 
     mpfr_set_ui(half, 1, round_mode);                                       //
-    mpfr_div_ui(half, half, 2, round_mode);                                    // half = 1/2
-    mpfr_div_ui(fourth, half, 2, round_mode);                                  // fourth = 1/4
-
+    mpfr_div_ui(half, half, 2, round_mode);                                 // half = 1/2
+    mpfr_div_ui(fourth, half, 2, round_mode);                               // fourth = 1/4
+ 
+    qd_half = "0.5";
+    qd_fourth = "0.25";
+    dd_half = "0.5";
+    dd_fourth = "0.25";
 
     mpfr_t n_minus;                                                         //
@@ -452,4 +724,13 @@
     mpfr_const_pi(mp_pi, round_mode);                                       // mp_pi = pi
 
+    qd_sqrt2 = "1.4142135623730950488016887242096980785696718753769480731766797380";
+    qd_sqrt3 = "1.7320508075688772935274463415058723669428052538103806280558069795";
+    qd_pi_sqrt2 = "4.4428829381583662470158809900606936986146216893756902230853956";
+    qd_pi = "3.1415926535897932384626433832795028841971693993751058209749445923";
+
+    dd_sqrt2 = "1.4142135623730950488016887242096980785696718753769480731766797380";
+    dd_sqrt3 = "1.7320508075688772935274463415058723669428052538103806280558069795";
+    dd_pi = "3.1415926535897932384626433832795028841971693993751058209749445923";
+    dd_pi_sqrt2 = "4.4428829381583662470158809900606936986146216893756902230853956";
 
     //mp_A = sqrt(2) * 3.1415926535897931 * sqrt(n - 1.0/24.0);---------------
@@ -460,7 +741,7 @@
     //------------------------------------------------------------------------
 
-    //cout << "mp_A = ";
-    //mpfr_out_str(stdout, 10, 0, mp_A, round_mode);
-    //cout << endl;
+    qd_A = qd_sqrt2 * qd_pi * sqrt(n - qd_one_over_24);
+    dd_A = dd_sqrt2 * dd_pi * sqrt(n - dd_one_over_24);
+
 
     //mp_B = 2.0 * sqrt(3) * (n - 1.0/24.0);----------------------------------
@@ -469,8 +750,7 @@
     mpfr_mul(mp_B, mp_B, n_minus, round_mode);                              // mp_A = 2*sqrt(3)*(n-1/24)
     //------------------------------------------------------------------------
-
-    //cout << "mp_B = ";
-    //mpfr_out_str(stdout, 10, 0, mp_B, round_mode);
-    //cout << endl;
+    qd_B = 2 * qd_sqrt3 * (n - qd_one_over_24);
+    dd_B = 2 * dd_sqrt3 * (n - dd_one_over_24);
+
 
     //mp_C = sqrt(2) * pi * sqrt(n - 1.0/24.0) / sqrt(3);---------------------
@@ -480,8 +760,7 @@
     mpfr_div(mp_C, mp_C, mp_sqrt3, round_mode);                             // mp_C = sqrt(2) * pi * sqrt(n - 1/24) / sqrt3
     //------------------------------------------------------------------------
-
-    //cout << "mp_C = ";
-    //mpfr_out_str(stdout, 10, 0, mp_C, round_mode);
-    //cout << endl;
+    qd_C = qd_sqrt2 * qd_pi * sqrt(n - qd_one_over_24) / qd_sqrt3;
+    dd_C = dd_sqrt2 * dd_pi * sqrt(n - dd_one_over_24) / dd_sqrt3;
+
     
     //mp_D = 2.0 * (n - 1.0/24.0) * sqrt(n - 1.0/24.0);-----------------------
@@ -490,8 +769,8 @@
     mpfr_mul(mp_D, mp_D, sqrt_n_minus, round_mode);                         // mp_D = 2 * (n - 1/24) * sqrt(n - 1/24)
     //------------------------------------------------------------------------
-    
-    //cout << "mp_D = ";
-    //mpfr_out_str(stdout, 10, 0, mp_D, round_mode);
-    //cout << endl;
+    qd_D = 2 * (n - qd_one_over_24) * sqrt(n - qd_one_over_24);
+    dd_D = 2 * (n - dd_one_over_24) * sqrt(n - dd_one_over_24);
+    
+    fpu_fix_end(&cw);
 
     mpfr_clear(n_minus);
@@ -525,20 +804,16 @@
      */
     mpz_init(ztemp1);
-    mpz_init(ztemp2);
-    mpz_init(ztemp3);
-
-    mpq_init(qtemp1);
-    mpq_init(qtemp2);
-    mpq_init(qtemp3);
+
+    mpq_init(qtemps);
+    mpq_init(qtempa);
+    mpq_init(qtempa2);
 }
 
 void clear_mpz_and_mpq_variables() {
     mpz_clear(ztemp1);
-    mpz_clear(ztemp2);
-    mpz_clear(ztemp3);
-
-    mpq_clear(qtemp1);
-    mpq_clear(qtemp2);
-    mpq_clear(qtemp3);
+
+    mpq_clear(qtemps);
+    mpq_clear(qtempa);
+    mpq_clear(qtempa2);
 }
 
@@ -583,12 +858,5 @@
 //       part of s(h,k)/2. It may be possible to make use of this somehow.
 //
-//       NOTE: when we compute p(1000000000),
-//       it takes about 3m 30s (on my laptop). If we uncomment
-//       the first two lines below, so that this function doesn't actually
-//       compute anything, it takes about 3m 10s to run. So not that much time
-//       is spent in this function when computing for large n
 void q_s(mpq_t result, unsigned int h, unsigned int k) {
-    //mpq_set_ui(result, 1, 1);
-    //return;
     
     if(k < 3) {
@@ -605,15 +873,12 @@
             mpq_set_ui(result, (k-1)*(k-2), 12*k);
         }
-        //mpq_canonicalize(result);
         return;
     }
-    // TODO: In the function mp_s() there are a few special cases for special forms of h and k.
-    // (And there are more special cases listed in one of the references listed in the introduction.)
-    //
-    // It may be advantageous to implement some here, but I'm not sure
-    // if there is any real speed benefit to this.
-    //
-    // In the mpfr_t version of this function, the speedups didn't seem to help too much, but
-    // they might make more of a difference when using mpq_t.
+    // TODO:
+    // It may be advantageous to implement some of the special forms in the comments below,
+    // and also some more listed in some of the links mentioned in the introduction, but
+    // it seems like there might not be much speed benefit to this, and putting in too
+    // many seems to slow things down a little.
+    //
 
     // if h = 2 and k is odd, we have
@@ -673,16 +938,16 @@
         unsigned int d = GCD(r1 * r1 + r2 * r2 + 1, r1 * r2);
         if(d > 1) {
-            mpq_set_ui(qtemp1, (r1 * r1 + r2 * r2 + 1)/d, (r1 * r2)/d);
+            mpq_set_ui(qtemps, (r1 * r1 + r2 * r2 + 1)/d, (r1 * r2)/d);
         }
         else{
-            mpq_set_ui(qtemp1, r1 * r1 + r2 * r2 + 1, r1 * r2);
-        }
-        //mpq_canonicalize(qtemp1);
+            mpq_set_ui(qtemps, r1 * r1 + r2 * r2 + 1, r1 * r2);
+        }
+        //mpq_canonicalize(qtemps);
         
         if(n % 2 == 0){                                             //
-            mpq_add(result, result, qtemp1);                        // result += temp1;
+            mpq_add(result, result, qtemps);                        // result += temp1;
         }                                                           //
         else {                                                      //
-            mpq_sub(result, result, qtemp1);                        // result -= temp1;
+            mpq_sub(result, result, qtemps);                        // result -= temp1;
         }                                                           //
         temp3 = r1 % r2;                                            //
@@ -692,162 +957,11 @@
     }
 
-    mpq_set_ui(qtemp1, 1, 12);
-    mpq_mul(result, result, qtemp1);                                // result = result * 1.0/12.0;
+    mpq_set_ui(qtemps, 1, 12);
+    mpq_mul(result, result, qtemps);                                // result = result * 1.0/12.0;
     
     
     if(n % 2 == 1) {
-        mpq_set_ui(qtemp1, 1, 4);
-        mpq_sub(result, result, qtemp1);                            // result = result - .25;
-    }
-
-}
-
-
-void mp_s(mpfr_t result, unsigned int h,unsigned int k) {
-    // Compute s(h,k) using some clever tricks.
-
-    // If k < 3, then we know that the result is going to be 0.
-    if(k < 3) {
-        mpfr_set_ui(result, 0, round_mode);
-        return;
-    }
-
-    unsigned int n, r1, r2, temp3 = 0;
-   
-    // If h = 1, then the result has the form
-    // 
-    //      s(h,k) = (k-1)(k-2)/(12k).
-    //
-    
-    if(h == 1) {
-        
-        // When k is small enough, we can do some of the computation using
-        // just ordinary integer arithmetic.
-        
-        if(k < (unsigned int)(sqrt(UINT_MAX))) {
-            mpfr_set_ui(result, (k-1)*(k-2), round_mode);
-            mpfr_div_ui(result, result, 12*k, round_mode);
-        }
-        else {
-            // When k is very large, we might need to use this code.
-            mpz_set_ui(ztemp1, k-1);                                // temp = k-1
-            mpz_mul_ui(ztemp1, ztemp1, k-2);                        // temp = (k-1)(k-2)
-        
-            mpfr_set_z(result, ztemp1, round_mode);                 // result = (k-1)(k-2)
-            mpz_set_ui(ztemp1, k);                                  // temp = k
-            mpz_mul_ui(ztemp1, ztemp1, 12);                         // temp = 12k
-            mpfr_div_z(result, result, ztemp1, round_mode);         // result = (k-1)(k-2)/12k
-        }
-        return;
-    }
-
-    // TODO: Below are a few special cases for special forms of h and k.
-    //
-    // It may be advantageous to implement a few more, but I'm not even sure
-    // that there is any real speed benefit to the special forms that are here
-    // now.
-
-    // if h = 2 and k is odd, then s(h,k) is given by
-    // (we need k > 5 because k is unsigned. k = 3 or 5 should
-    // be special cased.)
-    //
-    //      s(h,k) = (k-1)(k-5)/(24k)
-    //
-    if(h == 2 && k > 5 && k % 2 == 1) {
-        
-        // When k is small enough, we can do some of the computation using
-        // just ordinary integer arithmetic.
-        
-        if(k < (unsigned int)(sqrt(UINT_MAX))) {
-            mpfr_set_ui(result, (k-1)*(k-5), round_mode);
-            mpfr_div_ui(result, result, 24*k, round_mode);
-        }
-        else {
-            // When k is very large, we might need to use this code.
-            mpz_set_ui(ztemp1, k-1);                                // temp = k-1
-            mpz_mul_ui(ztemp1, ztemp1, k-5);                        // temp = (k-1)(k-5)
-        
-            mpfr_set_z(result, ztemp1, round_mode);                 // result = (k-1)(k-5)
-            mpz_set_ui(ztemp1, k);                                  // temp = k
-            mpz_mul_ui(ztemp1, ztemp1, 24);                         // temp = 24k
-            mpfr_div_z(result, result, ztemp1, round_mode);         // result = (k-1)(k-5)/24k
-        }
-        return;
-    }
-
-    // if k % h == 1, then
-    //
-    //      s(h,k) = (k-1)(k - h^2 - 1)/(12hk)
-    //
-
-    if(k % h == 1) {
-        if(4*k < (unsigned int)(sqrt(UINT_MAX))) {
-            mpfr_set_si(result, (k-1)*(k - h*h - 1), round_mode);
-            mpfr_div_ui(result, result, 12*h*k, round_mode);
-            return;
-        }
-    }
-
-    // if k % h == 2, then
-    //
-    //      s(h,k) = (k-2)[k - .5(h^2 + 1)]/(12hk)
-    //
-    //
-    //
-
-
-    
-    // At this point we have given up hope of using a special form and fall back on our generic 
-    // algorithm. 
-
-
-    mpfr_set_ui(result, 0, round_mode);                             // result = 0
-
-    r1 = k;
-    r2 = h;
-
-    n = 0;
-    while(r1 > 0 && r2 > 0) {
-        if(r1 < (unsigned int)(sqrt(UINT_MAX)/2.0)) {               // if r1 is small enough we can use
-                                                                    // standard C integers
-                                                                    // NOTE: squareroot computation should be optimized by the compiler.
-            mpfr_set_ui(temps1, r1*r1 + r2*r2 + 1, round_mode);
-            mpfr_div_ui(temps1, temps1, r1 * r2, round_mode);
-            
-        }
-        else {
-            //temp1 = (R1*R1 + R2*R2 + 1.0)/(R1 * R2);              //
-                                                                    //
-            mpfr_set_ui(temps1, r1, round_mode);                    // temp1 = r1
-            mpfr_mul_ui(temps1, temps1, r1, round_mode);            // temp1 = r1 * r1
-                                                                    //
-            mpfr_set_ui(temps2, r2, round_mode);                    // temp2 = r2
-            mpfr_mul_ui(temps2, temps2, r2, round_mode);            // temp2 = r2 * r2
-                                                                    //
-            mpfr_add(temps1, temps1, temps2, round_mode);           // temp1 = r1*r1 + r2*r2
-            mpfr_add_ui(temps1, temps1, 1, round_mode);             // temp1 = r1*r1 + r2*r2 + 1
-                                                                    //
-            mpfr_div_ui(temps1, temps1, r1, round_mode);            // temp1 = (r1*r1 + r2*r2 + 1)/r1
-            mpfr_div_ui(temps1, temps1, r2, round_mode);            // temp1 = (r1*r1 + r2*r2 + 1)/(r1 * r2)
-        }                                                           //
-        if(n % 2 == 0){                                             //
-            mpfr_add(result, result, temps1, round_mode);           // result += temp1;
-        }                                                           //
-        else {                                                      //
-            mpfr_sub(result, result, temps1, round_mode);           // result -= temp1;
-        }                                                           //
-        temp3 = r1 % r2;                                            //
-        r1 = r2;                                                    //
-        r2 = temp3;                                                 //
-        n++;                                                        //
-    }
-
-
-    mpfr_mul(result, result, mp_one_over_12, round_mode);           // result = result * 1.0/12.0;
-    
-    
-    if(n % 2 == 1) {
-        mpfr_set_d(temps1, .25, round_mode);
-        mpfr_sub(result, result, temps1, round_mode);               // result = result - .25;
+        mpq_set_ui(qtemps, 1, 4);
+        mpq_sub(result, result, qtemps);                            // result = result - .25;
     }
 
@@ -877,59 +991,65 @@
             // imaginary part will be 0, as we are computing an integer.
             
-            if(4*k < (unsigned int)(sqrt(UINT_MAX))) {
-                q_s(qtemp2, h, k);
-                
-                //mpfr_mul_q(tempa1, mp_pi, qtemp2, round_mode);
-                //mpfr_mul_ui(tempa1, tempa1, k * k, round_mode);
-
-                //mpfr_set_q(tempa1, qtemp2, round_mode);
-                unsigned int r = n % k;                                     // here we make use of the fact that the 
-                unsigned int d = GCD(r,k);                                  // cos() term written above only depends
-                unsigned int K;                                             // on {hn/k}.
-                if(d > 1) {
-                    r = r/d;
-                    K = k/d;
-                }
-                else {
-                    K = k;
-                }
-                if(K % 2 == 0) {
-                    K = K/2;
-                }
-                else {
-                    r = r * 2;
-                }
-                mpq_set_ui(qtemp3, h*r, K);
-                mpq_sub(qtemp2, qtemp2, qtemp3);
-                /*
-                mpfr_set_q(tempa2, qtemp2, round_mode);                 // This might be faster, according to
-                cospi(tempa1, tempa2);                                  // the comments in Ralf Stephan's part.c, but
+            q_s(qtempa, h, k);
+              
+            //mpfr_mul_q(tempa1, mp_pi, qtempa, round_mode);
+            //mpfr_mul_ui(tempa1, tempa1, k * k, round_mode);
+
+            //mpfr_set_q(tempa1, qtempa, round_mode);
+            unsigned int r = n % k;                                     // here we make use of the fact that the 
+            unsigned int d = GCD(r,k);                                  // cos() term written above only depends
+            unsigned int K;                                             // on {hn/k}.
+            if(d > 1) {
+                r = r/d;
+                K = k/d;
+            }
+            else {
+                K = k;
+            }
+            if(K % 2 == 0) {
+                K = K/2;
+            }
+            else {
+                r = r * 2;
+            }
+            mpq_set_ui(qtempa2, h*r, K);
+            mpq_sub(qtempa, qtempa, qtempa2);
+            
+            //mpfr_set_q(tempa2, qtempa, round_mode);                   // This might be faster, according to
+            //cospi(tempa1, tempa2);                                    // the comments in Ralf Stephan's part.c, but
                                                                         // I haven't noticed a significant speed up.
                                                                         // (Perhaps a different version that takes an mpq_t
                                                                         // as an input might be faster.)
-                */
-                mpfr_mul_q(tempa1, mp_pi, qtemp2, round_mode);
-                mpfr_cos(tempa1, tempa1, round_mode);
-                mpfr_add(result, result, tempa1, round_mode);
-            }
-            else{
-                mp_s(tempa1, h, k);                                     // temp1 = s(h,k)
             
-                mpfr_set_ui(tempa2, 2, round_mode);                     // temp2 = 2
-                mpfr_mul_ui(tempa2, tempa2, h, round_mode);             // temp2 = 2h
-                mpfr_mul_ui(tempa2, tempa2, n, round_mode);             // temp2 = 2hn
-                mpfr_div_ui(tempa2, tempa2, k, round_mode);             // temp2 = 2hn/k
-            
-                mpfr_sub(tempa1, tempa1, tempa2, round_mode);           // temp1 = s(h,k) - 2hn/k
-                mpfr_mul(tempa1, tempa1, mp_pi, round_mode);            // temp1 = pi * (s(h,k) - 2hn/k)
-                mpfr_cos(tempa1, tempa1, round_mode);                   // temp1 = cos( ditto )
-
-                mpfr_add(result, result, tempa1, round_mode);           // result = result + temp1
-            }
+            mpfr_mul_q(tempa1, mp_pi, qtempa, round_mode);
+            mpfr_cos(tempa1, tempa1, round_mode);
+            mpfr_add(result, result, tempa1, round_mode);
+  
+        }
         
-        }
-        
-    }
-
+    }
+
+}
+
+template <class T> 
+inline T partial_sum_of_t(unsigned int n, unsigned int &k, unsigned int exit_precision, unsigned int extra_precision, double error = 0) {
+    unsigned int current_precision = compute_current_precision(n, k - 1, extra_precision);
+    T result = 0;
+    if(error == 0) {
+        for(; current_precision > exit_precision; k++) {                        // (don't change k -- it is already the right value)
+            result += sqrt(T(int(k))) * a<T>(n,k) * f<T>(k);                    //
+            current_precision = compute_current_precision(n,k,extra_precision); // The only reason that we compute the new precision
+                                                                                // now is so that we know when we can change to using just doubles.
+                                                                                // (There should be a 'long double' version of the compute_current_precision function.
+        }
+    }
+    else {
+        double remainder = 1;
+        for(; remainder > error; k++) {                                     // (don't change k -- it is already the right value)
+            result += sqrt(T(int(k))) * a<T>(n,k) * f<T>(k);                //
+            remainder = compute_remainder(n,k);
+        }
+    }
+    return result;
 }
 
@@ -944,4 +1064,7 @@
     // NOTE: result should NOT have been initialized when this is called, 
     // as we initialize it to the proper precision in this function.
+    
+    double error = .25;
+    int extra = compute_extra_precision(n, error);
 
     unsigned int initial_precision = compute_initial_precision(n);  // We begin by computing the precision necessary to hold the final answer.
@@ -958,13 +1081,9 @@
                                                                     // that will be used throughout, and also
                                                                     //
-    initialize_mpfr_variables(initial_precision);                            // set the precision of the "temp" variables that are used in individual functions.
-//
+    initialize_mpfr_variables(initial_precision);                   // set the precision of the "temp" variables that are used in individual functions.
+
     unsigned int current_precision = initial_precision;
     unsigned int new_precision;
     
-    double remainder = 0.5772156649;                                // (We just need the remainder to be initialized to something. This
-                                                                    // seems like as good a number as any.)
-    
-                                                                    
     // We start by computing with high precision arithmetic, until
     // we are sure enough that we don't need that much precision
@@ -973,6 +1092,9 @@
     // that only involves doubles.
 
+
+
     unsigned int k = 1;                                             // (k holds the index of the summand that we are computing.)
-    for(k = 1; current_precision > level_four_precision; k++) {            //
+    for(k = 1; current_precision > level_two_precision; k++) {      //
+        
         mpfr_sqrt_ui(t1, k, round_mode);                            // t1 = sqrt(k)
                                                                     //
@@ -1000,7 +1122,4 @@
 
         if(debugt) {
-            //cout << "Partial sum " << k << " = ";
-            //mpfr_out_str(stdout, 10, 0, result, round_mode);
-            //cout << endl;
             int num_digits = 20;
             int num_extra_digits;
@@ -1017,5 +1136,5 @@
         }
 
-        new_precision = compute_current_precision(n,k);             // After computing one summand, check what the new precision should be.
+        new_precision = compute_current_precision(n,k,extra);       // After computing one summand, check what the new precision should be.
         if(new_precision != current_precision) {                    // If the precision changes, we need to clear
             current_precision = new_precision;                      // and reinitialize all "temp" variables to
@@ -1028,5 +1147,4 @@
     }
 
-
     mpfr_clear(t1); mpfr_clear(t2);
 
@@ -1034,33 +1152,33 @@
     mpfr_init2(t2, 200);
 
-
-    long double tail_result_1 = 0;
-
-    for( ; current_precision > level_five_precision; k++) {        // (don't change k -- it is already the right value)
-        tail_result_1 += sqrtl(k) * ld_a(n,k) * ld_f(k);            //
-        current_precision = compute_current_precision(n,k);         // The only reason that we compute the new precision
-                                                                    // now is so that we know when we can change to using just doubles.
-                                                                    // (There should be a 'long double' version of the compute_current_precision function.
-    }
-
-
-    double tail_result_2 = 0;                                       // (tail_result_2 will hold the result of the "tail end"
-                                                                    // computation using doubles.)
-
-    for( ; remainder > .5; k++) {                                   // (don't change k -- it is already the right value)
-        tail_result_2 += sqrt(k) * d_a(n,k) * d_f(k);                     //
-        remainder = compute_remainder(n,k);                         // Now we start computing the size of the remainder. Once
-                                                                    // it is small enough, we know that we have the answer.
-    }
-
-    mpfr_set_d(t1, tail_result_2, round_mode);                      //
+    unsigned int cw;
+    fpu_fix_start(&cw);
+
+    qd_real qd_partial_sum = partial_sum_of_t<qd_real>(n, k, level_three_precision, extra, 0);
+    dd_real dd_partial_sum = partial_sum_of_t<dd_real>(n,k, level_four_precision, extra, 0);
+    
+    char partial_sum_str[220];                                      // Unfortunately, this seems the best way to convert
+    qd_partial_sum.write(partial_sum_str, 200);                     // a qd_real into an mpfr.
+    mpfr_set_str(t1, partial_sum_str, 10, round_mode);              // TODO: There is a better way. See the file
+    mpfr_add(result, result, t1, round_mode);                       // real_rqdf.pyx in the sage source.
+    
+    dd_partial_sum.write(partial_sum_str, 200);                    
+    mpfr_set_str(t1, partial_sum_str, 10, round_mode);           
+    mpfr_add(result, result, t1, round_mode);
+    
+    fpu_fix_end(&cw);
+
+    long double ld_partial_sum = partial_sum_of_t<long double>(n,k,level_five_precision, extra, 0);
+    mpfr_set_ld(t1, ld_partial_sum, round_mode);
+    mpfr_add(result, result, t1, round_mode);
+
+    fpu_fix_start(&cw);
+    
+    double d_partial_sum = partial_sum_of_t<double>(n,k,0,extra,error);
+
+
+    mpfr_set_d(t1, d_partial_sum, round_mode);                      //
     mpfr_add(result, result, t1, round_mode);                       // We add together the main result and the tail ends'
 
-    mpfr_set_ld(t1, tail_result_1, round_mode);
-    mpfr_add(result, result, t1, round_mode);
-
-    //cout << tail_result_0_str << endl;
-    //mpfr_out_str(stdout, 10, 0, t1, round_mode);
-    //cout << endl;
 
     mpfr_div(result, result, mp_pi, round_mode);                    // The actual result is the sum that we have computed
@@ -1071,129 +1189,27 @@
     clear_mpfr_variables();
     mpfr_clear(t1);
-    mpfr_clear(t2);                         //
-}
-
-//  Double versions of the functions, see the above functions for documentation.
-
-double d_f(unsigned int k) {
-    return  3.141592653589793238462643 * sqrt(2) * cosh(d_A/(sqrt(3)*k))/(d_B*k) - sinh(d_C/k)/d_D;
-}
-
-long double ld_f(unsigned int k) {
-    return  3.141592653589793238462643 * sqrtl(2) * coshl(ld_A/(sqrtl(3)*k))/(ld_B*k) - sinhl(ld_C/k)/ld_D;
-}
-
-double d_s(unsigned int h,unsigned int k) {
-    if(k < 3) {
-        return 0.0;
-    }
-
-    double result, R1, R2, temp1, temp2;
-    unsigned int n, r1, r2, temp3 = 0;
-    
-    if(h == 1) {
-        double K;
-        K = k;
-        result = (K-1)*(K-2)/(12*K);
-        return result;
-    }
-
-    result = 0;
-    R1 = k;
-    R2 = h;
-
-    r1 = k;
-    r2 = h;
-
-    n = 0;
-    while(r1 && r2) {
-        temp1 = (R1*R1 + R2*R2 + 1.0)/(R1 * R2);
-        if(n % 2 == 0){
-            result += temp1;
-        }
-        else {
-            result -= temp1;
-        }
-        temp3 = r1 % r2;
-        r1 = r2;
-        r2 = temp3;
-        R1 = r1;
-        R2 = r2;
-        n++;
-    }
-
-    result = result * 1.0/12.0;
-
-    if(n % 2 == 1) {
-        result = result - .25;
-    }
-
-    return result;
-}
-
-long double ld_s(unsigned int h,unsigned int k) {
-    if(k < 3) {
-        return 0.0;
-    }
-
-    long double result, R1, R2, temp1, temp2;
-    unsigned int n, r1, r2, temp3 = 0;
-    
-    if(h == 1) {
-        long double K;
-        K = k;
-        result = (K-1)*(K-2)/(12*K);
-        return result;
-    }
-
-    result = 0;
-    R1 = k;
-    R2 = h;
-
-    r1 = k;
-    r2 = h;
-
-    n = 0;
-    while(r1 && r2) {
-        temp1 = (R1*R1 + R2*R2 + 1.0L)/(R1 * R2);
-        if(n % 2 == 0){
-            result += temp1;
-        }
-        else {
-            result -= temp1;
-        }
-        temp3 = r1 % r2;
-        r1 = r2;
-        r2 = temp3;
-        R1 = r1;
-        R2 = r2;
-        n++;
-    }
-
-    result = result * 1.0L/12.0L;
-
-    if(n % 2 == 1) {
-        result = result - .25L;
-    }
-
-    return result;
-}
-
-
-
-double d_a(unsigned int n, unsigned int k) {
-    double result;
-    result = 0;
-
-    if (k == 1) {
-        return 1.0;
-    }
-    
+    mpfr_clear(t2);                        
+
+    fpu_fix_end(&cw);    
+}
+
+template <class T>
+T f(unsigned int k) {
+    return pi_sqrt2<T>() * cosh(A<T>()/(sqrt3<T>()*k))/(B<T>() * k) - sinh(C<T>()/k)/D<T>();
+}
+
+template <class T>
+T a(unsigned int n, unsigned int k) {
+    if(k == 1) {
+        return 1;
+    }
+    T result = 0;
+ 
     unsigned int h = 0;
     for(h = 1; h < k+1; h++) {
         if(GCD(h,k) == 1) {
-        //    cout << "s(" << h << "," << k << ") = " << d_s(h,k) << endl;
-        //    cout << "s(" << h << "," << k << ") = " << d_s(h,k) << endl;
-            result += cos( 3.1415926535897931 * ( d_s(h,k) - (2.0 * h * n)/double(k)) );
+            result += cos( pi<T>() * ( s<T>(h,k) - T(2.0 * double(h) * n)/T(int(k))) ); // be careful to promote 2 and h to Ts
+                                                                                        // because the result 2 * h * n could
+                                                                                        // be too large.
         }
     }
@@ -1201,24 +1217,89 @@
 }
 
-long double ld_a(unsigned int n, unsigned int k) {
-    long double result;
-    result = 0;
-
-    if (k == 1) {
-        return 1.0;
-    }
-    
-    unsigned int h = 0;
-    for(h = 1; h < k+1; h++) {
-        if(GCD(h,k) == 1) {
-        //    cout << "s(" << h << "," << k << ") = " << d_s(h,k) << endl;
-        //    cout << "s(" << h << "," << k << ") = " << d_s(h,k) << endl;
-            result += cosl( ld_pi * ( ld_s(h,k) - (2.0L * h * n)/(long double)(k)) );
-        }
+template <class T>
+T s(unsigned int h, unsigned int k) {
+    //mpq_set_ui(result, 1, 1);
+    //return;
+    
+    //return T(0);  // Uncommenting this line saves 25% or more time in the computation of p(10^9) in the current version (.51)
+                    // but, of course, gives wrong results. (This is just to give an idea of how much time could
+                    // possibly be saved by optimizing this function.
+    
+    if(k < 3) {
+        return T(0);
+    }
+
+    if (h == 1) {
+        return T( int((k-1)*(k-2)) )/T(int(12 * k));
+    }
+    // TODO: In the function mp_s() there are a few special cases for special forms of h and k.
+    // (And there are more special cases listed in one of the references listed in the introduction.)
+    //
+    // It may be advantageous to implement some here, but I'm not sure
+    // if there is any real speed benefit to this.
+    //
+    // In the mpfr_t version of this function, the speedups didn't seem to help too much, but
+    // they might make more of a difference here.
+    //
+    // Update to the above comments:
+    // Actually, a few tests seem to indicate that putting in too many special
+    // cases slows things down a little bit.
+
+    // if h = 2 and k is odd, we have
+    // s(h,k) = (k-1)*(k-5)/24k
+    if(h == 2 && k > 5 && k % 2 == 1) {
+        return T( int((k-1)*(k-5)) )/ T(int(24*k));
+    }
+
+
+    // if k % h == 1, then
+    //
+    //      s(h,k) = (k-1)(k - h^2 - 1)/(12hk)
+    //
+
+    // We might need to be a little careful here because k - h^2 - 1 can be negative.
+    // THIS CODE DOESN'T WORK.
+    //if(k % h == 1) {
+    //    int num = (k-1)*(k - h*h - 1);
+    //    int den = 12*k*h;
+    //    return T(num)/T(den);
+    //}
+
+    // if k % h == 2, then
+    //
+    //      s(h,k) = (k-2)[k - .5(h^2 + 1)]/(12hk)
+    //
+
+    //if(k % h == 2) {
+    //}
+    
+    int r1 = k;
+    int r2 = h;
+
+    int n = 1;
+    int temp3;
+
+    T result = T(0);
+    T temp;
+    while(r2 > 0)   // Note that we maintain the invariant r1 >= r2, so
+                    // we only need to make sure that r2 > 0
+    {
+        temp = T(int(r1 * r1 + r2 * r2 + 1))/(n * r1 * r2);
+        temp3 = r1 % r2;                                            
+        r1 = r2;                                                    
+        r2 = temp3;                                                 
+        
+        result += temp;                        // result += temp1;
+
+        n = -n;
+    }
+
+    result *= one_over_12<T>();
+    
+    if(n < 0) {
+        result -= T(.25);
     }
     return result;
 }
-
-
 
 
@@ -1255,5 +1336,7 @@
 
 
-
+// The following function was copied from Ralf Stephan's code,
+// mentioned in the introduction, and then some variable names
+// were changed. The function is not currently used, however.
 void cospi (mpfr_t res, 
 		mpfr_t x)
@@ -1329,23 +1412,19 @@
 }
 
-
-
-void mpz_part(mpz_t result, unsigned int n) {
+/* answer must have already been mpz_init'd. */
+int part(mpz_t answer, unsigned int n){
     if(n == 1) {
-        mpz_set_str(result, "1", 10);
-        return;
-    }
-    
-    mpfr_t mp_result;
-
-    mp_t(mp_result, n);
-    
-    mpfr_get_z(result, mp_result, round_mode);
-
-    mpfr_clear(mp_result);
-    
-    return;
-}
-
+        mpz_set_str(answer, "1", 10);
+        return 0;
+    }
+    mpfr_t result;
+    
+    mp_t(result, n);
+    
+    mpfr_get_z(answer, result, round_mode);
+
+    mpfr_clear(result);
+    return 0;
+}
 
 
@@ -1356,8 +1435,36 @@
 
     if(argc > 1)
-        n = atoi(argv[1]);
+        if(strcmp(argv[1], "test") == 0) {
+            n = test(true);
+            if(n == 0) {
+                cout << "All Tests Passed" << endl;
+            }
+            else {
+                cout << "Error computing p(" << n << ")" << endl;
+            }
+            return 0;
+        }
+        else if(strcmp(argv[1], "testforever") == 0) {
+            n = test(false, true);
+            if(n == 0) {
+                cout << "All Tests Passed" << endl;
+            }
+            else {
+                cout << "Error computing p(" << n << ")" << endl;
+            }
+            return 0;
+        }
+        else {
+            n = atoi(argv[1]);
+        }
     else {
-
-        cout << test() << endl;
+        n = test(false);
+        if(n == 0) {
+            cout << "All short tests passed. Run '" << argv[0] << " test' to run all tests. (This may take some time, but it gives updates as it progresses, and can be interrupted.)" << endl;
+            cout << "Run with the argument 'testforever' to run tests until a failure is found (or, hopefully, to run tests forever.)" << endl;
+        }
+        else {
+            cout << "Error computing p(" << n << ")" << endl;
+        }
         return 0;
     }
@@ -1368,5 +1475,5 @@
     mpz_t answer;
     mpz_init(answer);
-    mpz_part(answer, n);
+    part(answer, n);
 
     //mpfr_get_z(answer, result, round_mode);
@@ -1380,10 +1487,13 @@
 
 
-bool test(bool longtest) {
-    // The values given below are confirmed by multiple sources, so are probably correct.
-    // TODO: There should be some more code here to test that answers satisfy the proper congruences that the should
-    //  satisfy. On the other hand, it might be better to test this file from within SAGE,
-    //  since that might be easier, and would certainly be more in line with the rest of
-    //  SAGE.
+int test(bool longtest, bool forever) {
+    // The exact values given below are confirmed by multiple sources, so are probably correct.
+    // Other tests rely on known congruences.
+    // If longtest is true, then we run some tests that probably take on the order
+    // of 10 minutes.
+    // If forever is true, then we just do randomized tests until a failure
+    // is found. Ideally, this should mean that we test forever, of course.
+
+    int n;
 
     mpz_t expected_value;
@@ -1393,72 +1503,346 @@
     mpz_init(actual_value);
 
-    // n = 1
+    n= 1;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
     mpz_set_str(expected_value, "1", 10);
-    mpz_part(actual_value, 1);
+    part(actual_value, n);
 
     if(mpz_cmp(expected_value, actual_value) != 0)
-        return false;
-
-    // n = 10
+        return n;
+
+    cout << " OK." << endl;
+
+    n = 10;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
     mpz_set_str(expected_value, "42", 10);
-    mpz_part(actual_value, 10);
+    part(actual_value, n);
 
     if(mpz_cmp(expected_value, actual_value) != 0)
-        return false;
-    
-    // n = 100
+        return n;
+    
+    cout << " OK." << endl;
+
+    n = 100;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
     mpz_set_str(expected_value, "190569292", 10);
-    mpz_part(actual_value, 100);
+    part(actual_value, n);
 
     if(mpz_cmp(expected_value, actual_value) != 0)
-        return false;
-
-    // n = 1000
+        return n;
+
+    cout << " OK." << endl;
+
+    n = 1000;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
     mpz_set_str(expected_value, "24061467864032622473692149727991", 10);
-    mpz_part(actual_value, 1000);
+    part(actual_value, n);
 
     if(mpz_cmp(expected_value, actual_value) != 0)
-        return false;
-
-    // n = 10000
+        return n;
+
+    cout << " OK." << endl;
+
+    n = 10000;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
     mpz_set_str(expected_value, "36167251325636293988820471890953695495016030339315650422081868605887952568754066420592310556052906916435144", 10);
-    mpz_part(actual_value, 10000);
+    part(actual_value, n);
 
     if(mpz_cmp(expected_value, actual_value) != 0)
-        return false;
-
-    // n = 100000
+        return n;
+
+    cout << " OK." << endl;
+
+    n = 100000;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
     mpz_set_str(expected_value, "27493510569775696512677516320986352688173429315980054758203125984302147328114964173055050741660736621590157844774296248940493063070200461792764493033510116079342457190155718943509725312466108452006369558934464248716828789832182345009262853831404597021307130674510624419227311238999702284408609370935531629697851569569892196108480158600569421098519", 10);
-    mpz_part(actual_value, 100000);
+    part(actual_value, n);
 
     if(mpz_cmp(expected_value, actual_value) != 0)
-        return false;
-    
-    // n = 1000000
+        return n;
+    
+    cout << " OK." << endl;
+
+    n = 1000000;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
     mpz_set_str(expected_value, "1471684986358223398631004760609895943484030484439142125334612747351666117418918618276330148873983597555842015374130600288095929387347128232270327849578001932784396072064228659048713020170971840761025676479860846908142829356706929785991290519899445490672219997823452874982974022288229850136767566294781887494687879003824699988197729200632068668735996662273816798266213482417208446631027428001918132198177180646511234542595026728424452592296781193448139994664730105742564359154794989181485285351370551399476719981691459022015599101959601417474075715430750022184895815209339012481734469448319323280150665384042994054179587751761294916248142479998802936507195257074485047571662771763903391442495113823298195263008336489826045837712202455304996382144601028531832004519046591968302787537418118486000612016852593542741980215046267245473237321845833427512524227465399130174076941280847400831542217999286071108336303316298289102444649696805395416791875480010852636774022023128467646919775022348562520747741843343657801534130704761975530375169707999287040285677841619347472368171772154046664303121315630003467104673818", 10);
-    mpz_part(actual_value, 1000000);
+    part(actual_value, n);
 
     if(mpz_cmp(expected_value, actual_value) != 0)
-        return false;
-    
-
-
+        return n;
+    
+    cout << " OK." << endl;
+
+
+    // We now run some tests based on the fact that if n = 369 (mod 385) then p(n) = 0 (mod 385).
+    
+    n = 369 + 10*385;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
+    part(actual_value, n);
+    if(mpz_divisible_ui_p(actual_value, 385) == 0)
+        return n;
+
+    cout << " OK." << endl;
+
+    n = 369 + 10*385;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
+    part(actual_value, n);
+    if(mpz_divisible_ui_p(actual_value, 385) == 0)
+        return n;
+
+    cout << " OK." << endl;
+
+    n = 369 + 100*385;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
+    part(actual_value, n);
+    if(mpz_divisible_ui_p(actual_value, 385) == 0)
+        return n;
+
+    cout << " OK." << endl;
+
+    n = 369 + 110*385;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
+    part(actual_value, n);
+    if(mpz_divisible_ui_p(actual_value, 385) == 0)
+        return n;
+
+    cout << " OK." << endl;
+
+    n = 369 + 120*385;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
+    part(actual_value, n);
+    if(mpz_divisible_ui_p(actual_value, 385) == 0)
+        return n;
+
+    cout << " OK." << endl;
+
+    n = 369 + 130*385;
+    cout << "Computing p(" << n << ")...";
+    cout.flush();
+    part(actual_value, n);
+    if(mpz_divisible_ui_p(actual_value, 385) == 0)
+        return n;
+
+    cout << " OK." << endl;
+
+    // Randomized testing
+
+    srand( time(NULL) );
+    
+    for(int i = 0; i < 100; i++) {
+        n = int(100000 * double(rand())/double(RAND_MAX) + 1);
+        n = n - (n % 385) + 369;
+        cout << "Computing p(" << n << ")...";
+        cout.flush();
+        part(actual_value, n);
+        if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+            return n;
+        }
+        cout << " OK." << endl;
+
+    }
+
+    if(longtest) {
+        n = 369 + 1000*385;
+        cout << "Computing p(" << n << ")...";
+        cout.flush();
+        part(actual_value, n);
+        if(mpz_divisible_ui_p(actual_value, 385) == 0)
+            return n;
+
+        cout << " OK." << endl;
+
+        n = 369 + 10000*385;
+        cout << "Computing p(" << n << ")...";
+        cout.flush();
+        part(actual_value, n);
+        if(mpz_divisible_ui_p(actual_value, 385) == 0)
+            return n;
+
+        cout << " OK." << endl;
+
+        n = 369 + 100000*385;
+        cout << "Computing p(" << n << ")...";
+        cout.flush();
+        part(actual_value, n);
+        if(mpz_divisible_ui_p(actual_value, 385) == 0)
+            return n;
+
+        cout << " OK." << endl;
+
+        for(int i = 0; i < 20; i++) {
+            n = int(100000 * double(rand())/double(RAND_MAX) + 1) + 100000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+
+        for(int i = 0; i < 20; i++) {
+            n = int(100000 * double(rand())/double(RAND_MAX) + 1) + 500000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+
+        for(int i = 0; i < 20; i++) {
+            n = int(100000 * double(rand())/double(RAND_MAX) + 1) + 1000000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+
+        for(int i = 0; i < 10; i++) {
+            n = int(100000 * double(rand())/double(RAND_MAX) + 1) + 10000000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+
+        n = 369 + 1000000*385;
+        cout << "Computing p(" << n << ")...";
+        cout.flush();
+        part(actual_value, n);
+        if(mpz_divisible_ui_p(actual_value, 385) == 0)
+            return n;
+        
+        cout << " OK." << endl;
+
+        for(int i = 0; i < 10; i++) {
+            n = int(100000000 * double(rand())/double(RAND_MAX) + 1) + 100000000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+        
+        n = 1000000000 + 139;
+        cout << "Computing p(" << n << ")...";
+        cout.flush();
+        part(actual_value, n);
+        if(mpz_divisible_ui_p(actual_value, 385) == 0)
+            return n;
+        
+        cout << " OK." << endl;
+
+
+        for(int i = 0; i < 10; i++) {
+            n = int(100000000 * double(rand())/double(RAND_MAX) + 1) + 1000000000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+
+    }
+
+    if(forever) {
+        while(1) {
+
+        for(int i = 0; i < 100; i++) {
+            n = int(900000 * double(rand())/double(RAND_MAX) + 1) + 100000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+
+        for(int i = 0; i < 50; i++) {
+            n = int(9000000 * double(rand())/double(RAND_MAX) + 1) + 1000000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+
+        for(int i = 0; i < 50; i++) {
+            n = int(90000000 * double(rand())/double(RAND_MAX) + 1) + 10000000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+
+        for(int i = 0; i < 10; i++) {
+            n = int(900000000 * double(rand())/double(RAND_MAX) + 1) + 100000000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+        for(int i = 0; i < 5; i++) {
+            n = int(100000000 * double(rand())/double(RAND_MAX) + 1) + 1000000000;
+            n = n - (n % 385) + 369;
+            cout << "Computing p(" << n << ")...";
+            cout.flush();
+            part(actual_value, n);
+            if(mpz_divisible_ui_p(actual_value, 385) == 0) {
+                return n;
+            }
+            cout << " OK." << endl;
+        }
+        }
+
+
+    }
 
     mpz_clear(expected_value);
     mpz_clear(actual_value);
-
-    return true;
-}
-
-
-/* answer must have already been mpz_init'd. */
-int part(mpz_t answer, unsigned int n){
-    mpfr_t result;
-    
-    mp_t(result, n);
-    
-    mpfr_get_z(answer, result, round_mode);
-
-    mpfr_clear(result);
     return 0;
 }
+
+
Index: sage/combinat/permutation.py
===================================================================
--- sage/combinat/permutation.py	(revision 6594)
+++ sage/combinat/permutation.py	(revision 6594)
@@ -0,0 +1,3542 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+
+from sage.interfaces.all import gap, maxima
+from sage.rings.all import QQ, RR, ZZ, polygen, Integer, PolynomialRing, factorial
+from sage.rings.arith import binomial
+from sage.misc.sage_eval import sage_eval
+from sage.libs.all import pari
+from sage.matrix.all import matrix
+from sage.combinat.tools import transitive_ideal
+import sage.combinat.misc as misc
+import sage.combinat.subword as subword
+import sage.combinat.composition as composition
+from sage.combinat.composition import Composition, Compositions, Composition_class
+from sage.combinat.tableau import Tableau
+import sage.combinat.partition
+import sage.combinat.permutation_nk as permutation_nk
+import sage.rings.integer
+from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
+from random import randint
+from sage.interfaces.all import gap
+from sage.graphs.graph import DiGraph
+import itertools
+import __builtin__
+from combinat import CombinatorialClass, CombinatorialObject, catalan_number
+import copy
+from necklace import Necklaces
+
+permutation_options = {'display':'list', 'mult':'l2r'}
+
+def PermutationOptions(**kwargs):
+    """
+    Sets the global options for elements of the permutation class.
+    The defaults are for permutations to be displayed in list notation
+    and the multiplication done from left to right (like in GAP).
+
+    display: 'list'  -- the permutations are displayed in list notation
+             'cycle' -- the permutations are displayed in cycle notation
+             'singleton' -- the permutations are displayed in cycle notation
+                            with singleton cycles shown as well.
+
+    mult: 'l2r' -- the multiplication of permutations is done like composition
+                   of functions from left to right. That is, if we think
+                   of the permutations p1 and p2 as functions, then
+                   (p1*p2)(x) = p2(p1(x)). This is the default in multiplication
+                   in GAP.
+          'r2l' -- the multiplication of permutations is done right to left
+                   so that (p1*p2)(x) = p1(p2(x))
+
+    If no parameters are set, then the function returns a copy of the
+    options dictionary.
+
+    Note that these options have no effect on PermutationGroupElements.
+
+    EXAMPLES:
+        sage: p213 = Permutation([2,1,3])
+        sage: p312 = Permutation([3,1,2])
+        sage: PermutationOptions(mult='l2r', display='list')
+        sage: po = PermutationOptions()
+        sage: po['display']
+        'list'
+        sage: p213
+        [2, 1, 3]
+        sage: PermutationOptions(display='cycle')
+        sage: p213
+        (1,2)
+        sage: PermutationOptions(display='singleton')
+        sage: p213
+        (1,2)(3)
+        sage: PermutationOptions(display='list')
+
+        sage: po['mult']
+        'l2r'
+        sage: p213*p312
+        [1, 3, 2]
+        sage: PermutationOptions(mult='r2l')
+        sage: p213*p312
+        [3, 2, 1]
+        sage: PermutationOptions(mult='l2r')
+    """
+    global permutation_options
+    if kwargs == {}:
+        return copy.copy(permutation_options)
+    
+    if 'mult' in kwargs:
+        if kwargs['mult'] not in ['l2r', 'r2l']:
+            raise ValueError, "mult must be either 'l2r' or 'r2l'"
+        else:
+            permutation_options['mult'] = kwargs['mult']
+
+    if 'display' in kwargs:
+        if kwargs['display'] not in ['list', 'cycle', 'singleton']:
+            raise ValueError, "display must be either 'cycle' or 'list'"
+        else:
+            permutation_options['display'] = kwargs['display']
+
+
+def Permutation(l):
+    """
+    EXAMPLES:
+        sage: Permutation([2,1])
+        [2, 1]
+        sage: Permutation([2, 1, 4, 5, 3])
+        [2, 1, 4, 5, 3]
+        sage: Permutation('(1,2)')
+        [2, 1]
+        sage: Permutation('(1,2)(3,4,5)')
+        [2, 1, 4, 5, 3]
+    """
+    #if l is a string, then assume it is in cycle notation
+    if isinstance(l, str):
+        cycles = l.split(")(")
+        cycles[0] = cycles[0][1:]
+        cycles[-1] = cycles[-1][:-1]
+        cycle_list = []
+        for c in cycles:
+            cycle_list.append(map(int, c.split(",")))
+        return from_cycles(sum([len(c) for c in cycle_list]), cycle_list)
+    else:
+        return Permutation_class(l)
+
+class Permutation_class(CombinatorialObject):
+    def __init__(self, l):
+        """
+        TESTS:
+            sage: p = Permutation([1,2,3])
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.list = l
+        
+    def __hash__(self):
+        """
+        TESTS:
+            sage: d = {}
+            sage: p = Permutation([1,2,3])
+            sage: d[p] = 1
+            sage: d[p]
+            1
+        """
+        return str(self).__hash__()
+
+    def __str__(self):
+        """
+        TESTS:
+            sage: PermutationOptions(display='list')
+            sage: p = Permutation([2,1,3])
+            sage: str(p)
+            '[2, 1, 3]'
+            sage: PermutationOptions(display='cycle')
+            sage: str(p)
+            '(1,2)'
+            sage: PermutationOptions(display='singleton')
+            sage: str(p)
+            '(1,2)(3)'
+            sage: PermutationOptions(display='list')
+        """
+        return repr(self)
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: PermutationOptions(display='list')
+            sage: p = Permutation([2,1,3])
+            sage: repr(p)
+            '[2, 1, 3]'
+            sage: PermutationOptions(display='cycle')
+            sage: repr(p)
+            '(1,2)'
+            sage: PermutationOptions(display='singleton')
+            sage: repr(p)
+            '(1,2)(3)'
+            sage: PermutationOptions(display='list')
+        """
+        global permutation_options
+        display = permutation_options['display']
+        if display == 'list':
+            return repr(self.list)
+        elif display == 'cycle':
+            return self.cycle_string()
+        elif display == 'singleton':
+            return self.cycle_string(singletons=True)
+        else:
+            raise ValueError, "permutation_options['display'] should be one of 'list', 'cycle', or 'singleton'"
+
+    def cycle_string(self, singletons=False):
+        """
+        Returns a string of the permutation in cycle notation.
+
+        If singletons=True, it includes 1-cycles in the string.
+        
+        EXAMPLES:
+            sage: Permutation([1,2,3]).cycle_string()
+            '()'
+            sage: Permutation([2,1,3]).cycle_string()
+            '(1,2)'
+            sage: Permutation([2,3,1]).cycle_string()
+            '(1,2,3)'
+            sage: Permutation([2,1,3]).cycle_string(singletons=True)
+            '(1,2)(3)'
+        """
+        cycles = self.to_cycles(singletons=singletons)
+        if cycles == []:
+            return "()"
+        else:
+            return "".join(["("+",".join([str(l) for l in x])+")" for x in cycles])
+
+    def next(self):
+        r"""
+        Returns the permutation that follows p in lexicographic order.
+        If p is the last permutation, then next returns false.
+
+        EXAMPLES:
+            sage: p = Permutation([1, 3, 2])
+            sage: p.next()
+            [2, 1, 3]
+            sage: p = Permutation([4,3,2,1])
+            sage: p.next()
+            False
+        """
+        p = self[:]
+        n = len(self)
+        first = -1
+
+        #Starting from the end, find the first o such that
+        #p[o] < p[o+1]
+        for i in reversed(range(0,n-1)):
+            if p[i] < p[i+1]:
+                first = i
+                break
+
+        #If first is still -1, then we are already at the last permutation
+        if first == -1:
+            return False
+
+        #Starting from the end, find the first j such that p[j] > p[first]
+        j = n - 1
+        while p[j] < p[first]:
+            j -= 1
+
+        #Swap positions first and j
+        (p[j], p[first]) = (p[first], p[j])
+
+        #Reverse the list between first and the end
+        first_half = p[:first+1]
+        last_half  = p[first+1:]
+        last_half.reverse()
+        p = first_half + last_half
+
+        return Permutation(p)
+
+    def prev(self):
+        r"""
+        Returns the permutation that comes directly before p
+        in lexicographic order.  If p is the first permutation, then
+        it returns False.
+
+        EXAMPLES:
+            sage: p = Permutation([1,2,3])
+            sage: p.prev()
+            False
+            sage: p = Permutation([1,3,2])
+            sage: p.prev()
+            [1, 2, 3]
+        """
+
+        p = self[:]
+        n = len(self)
+        first = -1
+
+        #Starting from the beginning, find the first o such that
+        #p[o] > p[o+1]
+        for i in range(0, n-1):
+            if p[i] > p[i+1]:
+                first = i
+                break
+
+        #If first is still -1, that is we didn't find any descents,
+        #then we are already at the last permutation
+        if first == -1:
+            return False
+
+        #Starting from the end, find the first j such that p[j] > p[first]
+        j = n - 1
+        while p[j] > p[first]:
+            j -= 1
+
+        #Swap positions first and j
+        (p[j], p[first]) = (p[first], p[j])
+
+        #Reverse the list between first+1 and end
+        first_half = p[:first+1]
+        last_half  = p[first+1:]
+        last_half.reverse()
+        p = first_half + last_half
+
+        return Permutation(p)
+
+    
+
+    def to_cycles(self, singletons=True):
+        r"""
+        Returns the permutation p as a list of disjoint cycles.
+
+        EXAMPLES:
+            sage: Permutation([2,1,3,4]).to_cycles()
+            [(1, 2), (3,), (4,)]
+            sage: Permutation([2,1,3,4]).to_cycles(singletons=False)
+            [(1, 2)]
+        """
+        p = self[:]
+        cycles = []
+        toConsider = -1
+
+        #Create the list [1,2,...,len(p)]
+        l = [ i+1 for i in range(len(p))]
+        cycle = []
+
+        #Go through until we've considered every number between
+        #1 and len(p)
+        while len(l) > 0:
+            #If we are at the end of a cycle
+            #then we want to add it to the cycles list
+            if toConsider == -1:
+                #Add the cycle to the list of cycles
+                if singletons:
+                    if cycle != []:
+                        cycles.append(tuple(cycle))
+                else:
+                    if len(cycle) > 1:
+                        cycles.append(tuple(cycle))
+
+
+                #Start with the first element in the list
+                toConsider = l[0]
+                l.remove(toConsider)
+                cycle = [ toConsider ]
+                cycleFirst = toConsider
+
+            #Figure out where the element under consideration
+            #gets mapped to.
+            next = p[toConsider - 1]
+
+            #If the next element is the first one in the list
+            #then we've reached the end of the cycle
+            if next == cycleFirst:
+                toConsider = -1
+            else:
+                cycle.append( next )    
+                l.remove( next )
+                toConsider = next
+
+        #When we're finished, add the last cycle
+        if singletons:
+            if cycle != []:
+                cycles.append(tuple(cycle))
+        else:
+            if len(cycle) > 1:
+                cycles.append(tuple(cycle))
+
+        return cycles
+
+    def to_permutation_group_element(self):
+        """
+        Returns a PermutationGroupElement equal to self.
+
+        EXAMPLES:
+            sage: p = Permutation([2,1,4,3])
+            sage: pge = p.to_permutation_group_element()
+            sage: pge
+            (1,2)(3,4)
+        """
+
+        return PermutationGroupElement(self.to_cycles(singletons=False))
+
+    def signature(p):
+        r"""
+        Returns the signature of a permutation.
+
+        EXAMPLES:
+            sage: Permutation([4, 2, 3, 1, 5]).signature()
+            -1
+
+        """
+        return (-1)**(len(p)-len(p.to_cycles()))
+    
+
+    def is_even(self):
+        r"""
+        Returns True if the permutation p is even and false otherwise.
+
+        EXAMPLES:
+            sage: Permutation([1,2,3]).is_even()
+            True
+            sage: Permutation([2,1,3]).is_even()
+            False
+        """
+
+        if self.signature() == 1:
+            return True
+        else:
+            return False
+
+
+    def to_matrix(self):
+        r"""
+        Returns a matrix representing the permutation.
+
+        EXAMPLES:
+            sage: Permutation([1,2,3]).to_matrix()
+            [1 0 0]
+            [0 1 0]
+            [0 0 1]
+
+            sage: Permutation([1,3,2]).to_matrix()
+            [1 0 0]
+            [0 0 1]
+            [0 1 0]
+
+          Notice that matrix multiplication corresponds to permutation
+          multiplication only when the permutation option mult='r2l'
+
+            sage: PermutationOptions(mult='r2l')
+            sage: p = Permutation([2,1,3])
+            sage: q = Permutation([3,1,2])
+            sage: (p*q).to_matrix()
+            [0 0 1]
+            [0 1 0]
+            [1 0 0]
+            sage: p.to_matrix()*q.to_matrix()
+            [0 0 1]
+            [0 1 0]
+            [1 0 0]
+            sage: PermutationOptions(mult='l2r')
+            sage: (p*q).to_matrix()
+            [1 0 0]
+            [0 0 1]
+            [0 1 0]
+        """
+        p = self[:]
+        n = len(p)
+
+        #Build the dictionary of entries since the matrix
+        #is extremely sparse
+        entries = {}
+        for i in range(n):
+            entries[(p[i]-1,i)] = 1
+        return matrix(n, entries, sparse = True)
+
+    def __mul__(self, rp):
+        """
+        TESTS:
+            sage: p213 = Permutation([2,1,3])
+            sage: p312 = Permutation([3,1,2])
+            sage: PermutationOptions(mult='l2r')
+            sage: p213*p312
+            [1, 3, 2]
+            sage: PermutationOptions(mult='r2l')
+            sage: p213*p312
+            [3, 2, 1]
+            sage: PermutationOptions(mult='l2r')
+        """
+        global permutation_options
+        if permutation_options['mult'] == 'l2r':
+            return self._left_to_right_multiply_on_right(rp)
+        else:
+            return self._left_to_right_multiply_on_left(rp)
+
+    def __rmul__(self, lp):
+        """
+        TESTS:
+            sage: p213 = Permutation([2,1,3])
+            sage: p312 = Permutation([3,1,2])
+            sage: PermutationOptions(mult='l2r')
+            sage: p213*p312
+            [1, 3, 2]
+            sage: PermutationOptions(mult='r2l')
+            sage: p213*p312
+            [3, 2, 1]
+            sage: PermutationOptions(mult='l2r')
+        """
+        global permutation_options
+        if permutation_options['mult'] == 'l2r':
+            return self._left_to_right_multiply_on_left(lp)
+        else:
+            return self._left_to_right_multiply_on_right(lp)     
+
+    def _left_to_right_multiply_on_left(self,lp):
+        """
+        EXAMPLES:
+            sage: p = Permutation([2,1,3])
+            sage: q = Permutation([3,1,2])
+            sage: p._left_to_right_multiply_on_left(q)
+            [3, 2, 1]
+            sage: q._left_to_right_multiply_on_left(p)
+            [1, 3, 2]
+        """
+        #Pad the permutations if they are of
+        #different lengths
+        new_lp = lp[:] + [i+1 for i in range(len(lp), len(self))]
+        new_p1 = self[:] + [i+1 for i in range(len(self), len(lp))]
+        return Permutation([ new_p1[i-1] for i in new_lp ])     
+    
+
+    def _left_to_right_multiply_on_right(self, rp):
+        """
+        EXAMPLES:
+            sage: p = Permutation([2,1,3])
+            sage: q = Permutation([3,1,2])
+            sage: p._left_to_right_multiply_on_right(q)
+            [1, 3, 2]
+            sage: q._left_to_right_multiply_on_right(p)
+            [3, 2, 1]
+        """
+        #Pad the permutations if they are of
+        #different lengths
+        new_rp = rp[:] + [i+1 for i in range(len(rp), len(self))]
+        new_p1 = self[:] + [i+1 for i in range(len(self), len(rp))]
+        return Permutation([ new_rp[i-1] for i in new_p1 ]) 
+
+
+    ########
+    # Rank #
+    ########
+
+    def rank(self):
+        r"""
+        Returns the rank of a permutation in lexicographic
+        ordering.
+
+        EXAMPLES:
+            sage: Permutation([1,2,3]).rank()
+            0
+            sage: Permutation([1, 2, 4, 6, 3, 5]).rank()
+            10
+            sage: perms = Permutations(6).list()
+            sage: [p.rank() for p in perms ] == range(factorial(6))
+            True
+        """
+        n = len(self)
+
+        factoradic = self.to_lehmer_code()
+
+        #Compute the index
+        rank = 0
+        for i in reversed(range(0, n)):
+            rank += factoradic[n-1-i]*factorial(i)
+
+        return rank
+
+    ##############
+    # Inversions #
+    ##############
+
+    def to_inversion_vector(self):
+        r"""
+        Returns the inversion vector of a permutation p.
+
+        If iv is the inversion vector, then iv[i] is the number of elements
+        larger than i that appear to the left of i in the permutation.
+
+        EXAMPLES:
+            sage: Permutation([5,9,1,8,2,6,4,7,3]).to_inversion_vector()
+            [2, 3, 6, 4, 0, 2, 2, 1, 0]
+            sage: Permutation([8,7,2,1,9,4,6,5,10,3]).to_inversion_vector()
+            [3, 2, 7, 3, 4, 3, 1, 0, 0, 0]
+            sage: Permutation([3,2,4,1,5]).to_inversion_vector()
+            [3, 1, 0, 0, 0]
+
+        """
+        p = self[:]
+        inversion_vector = [0]*len(p)
+        for i in range(len(p)):
+            j = 0
+            while p[j] != i+1:
+                if p[j] > i+1:
+                    inversion_vector[i] += 1
+                j += 1
+
+        return inversion_vector
+
+
+    def inversions(self):
+        r"""
+        Returns a list of the inversions of permutation p.
+
+        EXAMPLES:
+            sage: Permutation([3,2,4,1,5]).inversions()
+            [[0, 1], [0, 3], [1, 3], [2, 3]]
+
+
+        """
+        p = self[:]
+        inversion_list = []
+
+        for i in range(len(p)):
+            for j in range(i+1,len(p)):
+                if  p[i] > p[j]:
+                    #inversion_list.append((p[i],p[j]))
+                    inversion_list.append([i,j])
+
+        return inversion_list
+
+
+
+    def number_of_inversions(self):
+        r"""
+        Returns the number of inversions in the permutation p.
+
+        An inversion of a permutation is a pair of elements (p[i],p[j])
+        with i > j and p[i] < p[j].
+
+        REFERENCES:
+            http://mathworld.wolfram.com/PermutationInversion.html
+
+        EXAMPLES:
+            sage: Permutation([3,2,4,1,5]).number_of_inversions()
+            4
+            sage: Permutation([1, 2, 6, 4, 7, 3, 5]).number_of_inversions()
+            6
+
+        """
+
+        return sum(self.to_inversion_vector())
+
+
+    def length(self):
+        r"""
+        Returns the length of a permutation p.  The length is given by the
+        number of inversions of p.
+
+        EXAMPLES:
+            sage: Permutation([5, 1, 3, 2, 4]).length()
+            5
+        """
+        return self.number_of_inversions()
+
+    def inverse(self):
+        r"""
+        Returns the inverse of a permutation
+
+        EXAMPLES:
+            sage: Permutation([3,8,5,10,9,4,6,1,7,2]).inverse()
+            [8, 10, 1, 6, 3, 7, 9, 2, 5, 4]
+            sage: Permutation([2, 4, 1, 5, 3]).inverse()
+            [3, 1, 5, 2, 4]
+
+
+        """
+        return Permutation([self.index(i+1)+1 for i in range(len(self))])
+
+    def runs(self):
+        r"""
+        Returns a list of the runs in the permutation p.
+
+        REFERENCES:
+            http://mathworld.wolfram.com/PermutationRun.html
+
+        EXAMPLES:
+            sage: Permutation([1,2,3,4]).runs()
+            [[1, 2, 3, 4]]
+            sage: Permutation([4,3,2,1]).runs()
+            [[4], [3], [2], [1]]
+            sage: Permutation([2,4,1,3]).runs()
+            [[2, 4], [1, 3]]
+        """
+        p = self[:]
+        runs = []
+        current_value = p[0]
+        current_run = [p[0]]
+        for i in range(1, len(p)):
+            if p[i] < current_value:
+                runs.append(current_run)
+                current_run = [p[i]]
+            else:
+                current_run.append(p[i])
+
+            current_value = p[i]
+        runs.append(current_run)
+
+        return runs
+
+    def longest_increasing_subsequence(self):
+        r"""
+        Returns a list of the longest increasing subsequences of
+        the permutation p.
+
+        EXAMPLES:
+            sage: Permutation([2,3,4,1]).longest_increasing_subsequence()
+            [[2, 3, 4]]
+        """
+        runs = self.runs()
+        lis = []
+        max_length = max([len(r) for r in runs])
+        for run in runs:
+            if len(run) == max_length:
+                lis.append(run)
+        return lis
+
+    def cycle_type(self):
+        r"""
+        Returns a partition of len(p) corresponding to the cycle
+        type of p.  This is a non-increasing sequence of the
+        cycle lengths of p.
+
+        EXAMPLES:
+            sage: Permutation([3,1,2,4]).cycle_type()
+            [3, 1]
+        """
+        cycle_type = [len(c) for c in self.to_cycles()]
+        cycle_type.sort(reverse=True)
+        return sage.combinat.partition.Partition(cycle_type)
+
+    def to_lehmer_code(self):
+        r"""
+        Returns the Lehmer code of the permutation p.
+
+        EXAMPLES:
+            sage: p = Permutation([2,1,3])
+            sage: p.to_lehmer_code()
+            [1, 0, 0]
+            sage: q = Permutation([3,1,2])
+            sage: q.to_lehmer_code()
+            [2, 0, 0]
+        """
+        p = self[:]
+        n = len(p)
+        lehmer = [None]*n
+        checked = [0]*n
+        ident = range(1,n+1)
+
+        #Compute the factoradic / Lehmer code of the permutation
+        for i in range(n):
+            j = 0
+            pos = 0
+            while j < n:
+                if checked[j] != 1:
+                    if ident[j] == p[i]:
+                        checked[j] = 1
+                        break
+                    pos += 1
+                j += 1
+            lehmer[i] = pos
+
+        return lehmer
+
+
+    def to_lehmer_cocode(self):
+        r"""
+        Returns the Lehmer cocode of p.
+
+        EXAMPLES:
+            sage: p = Permutation([2,1,3])
+            sage: p.to_lehmer_cocode()
+            [0, 1, 0]
+            sage: q = Permutation([3,1,2])
+            sage: q.to_lehmer_cocode()
+            [0, 1, 1]
+        """
+        p = self[:]
+        n = len(p)
+        cocode = [0] * n
+        for i in range(1, n):
+            for j in range(0, i):
+                if p[j] > p[i]:
+                    cocode[i] += 1
+        return cocode
+
+
+
+    #################
+    # Reduced Words #
+    #################
+
+    def reduced_word(self):
+        r"""
+        Returns the reduced word of a permutation.
+
+        EXAMPLES:
+            sage: Permutation([3,5,4,6,2,1]).reduced_word()
+            [2, 1, 4, 3, 2, 4, 3, 5, 4, 5]
+
+        """
+        code = self.to_lehmer_code()
+        reduced_word = []
+        for piece in  [ [ i + code[i] - j for j in range(code[i])] for i in range(len(code))]:
+            reduced_word += piece
+
+        return reduced_word
+
+    def reduced_words(self):
+        r"""
+        Returns a list of the reduced words of the permutation p.
+
+        EXAMPLES:
+            sage: Permutation([2,1,3]).reduced_words()
+            [[1]]
+            sage: Permutation([3,1,2]).reduced_words()
+            [[2, 1]]
+            sage: Permutation([3,2,1]).reduced_words()
+            [[1, 2, 1], [2, 1, 2]]
+            sage: Permutation([3,2,4,1]).reduced_words()
+            [[1, 2, 3, 1], [1, 2, 1, 3], [2, 1, 2, 3]]
+        """
+        p = self[:]
+        n = len(p)
+        rws = []
+        descents = self.descents()
+
+        if len(descents) == 0:
+            return [[]]
+
+        for d in descents:
+            pp = p[:d] + [p[d+1]] + [p[d]] + p[d+2:]
+            z = lambda x: x + [d+1]
+            rws += (map(z, Permutation(pp).reduced_words()))
+
+        return rws
+
+
+
+    def reduced_word_lexmin(self):
+        r"""
+        Returns a lexicographically minimal reduced word of a permutation.
+
+        EXAMPLES:
+            sage: Permutation([3,4,2,1]).reduced_word_lexmin()
+            [1, 2, 1, 3, 2]
+        """
+        cocode = self.inverse().to_lehmer_cocode()
+
+        rw = []
+        for i in range(len(cocode)):
+            piece = [j+1 for j in range(i-cocode[i],i)]
+            piece.reverse()
+            rw += piece
+
+        return rw
+
+
+    ################
+    # Fixed Points #
+    ################
+
+    def fixed_points(self):
+        r"""
+        Returns a list of the fixed points of the permutation p.
+
+        EXAMPLES:
+            sage: Permutation([1,3,2,4]).fixed_points()
+            [1, 4]
+            sage: Permutation([1,2,3,4]).fixed_points()
+            [1, 2, 3, 4]
+        """
+        fixed_points = []
+        for i in range(len(self)):
+            if i+1 == self[i]:
+                fixed_points.append(i+1)
+
+        return fixed_points
+
+    def number_of_fixed_points(self):
+        r"""
+        Returns the number of fixed points of the permutation p.
+
+        EXAMPLES:
+            sage: Permutation([1,3,2,4]).number_of_fixed_points()
+            2
+            sage: Permutation([1,2,3,4]).number_of_fixed_points()
+            4
+        """
+
+        return len(self.fixed_points())
+
+
+    ############
+    # Recoils  #
+    ############
+    def recoils(self):
+        r"""
+        Returns the list of the positions of the recoils of the permutation p.
+
+        A recoil of a permutation is an integer i such that i+1 is to the
+        left of it.
+
+
+        EXAMPLES:
+            sage: Permutation([1,4,3,2]).recoils()
+            [2, 3]
+        """
+        p = self
+        recoils  = []
+        for i in range(len(p)):
+            if p[i] != len(self) and self.index(p[i]+1) < i:
+                recoils.append(i)
+
+        return recoils
+
+    def number_of_recoils(self):
+        r"""
+        Returns the number of recoils of the permutation p.
+
+        EXAMPLES:
+            sage: Permutation([1,4,3,2]).number_of_recoils()
+            2
+
+        """
+        return len(self.recoils())
+
+    def recoils_composition(self):
+        """
+        Returns the composition corresponding to recoils of
+        the permutation.
+
+        EXAMPLES:
+            sage: Permutation([1,3,2,4]).recoils_composition()
+            [3]
+        """
+        d = self.recoils()
+        d = [ -1 ] + d
+        return [ d[i+1]-d[i] for i in range(len(d)-1)]
+
+
+    ############
+    # Descents #
+    ############
+
+    def descents(self, final_descent=False):
+        r"""
+        Returns the list of the descents of the permutation p.
+
+        A descent of a permutation is an integer i such that p[i]>p[i+1].
+        With the final_descent option, the last position of a non empty permutation
+        is also considered as a descent.
+
+        EXAMPLES:
+            sage: Permutation([1,4,3,2]).descents()
+            [1, 2]
+            sage: Permutation([1,4,3,2]).descents(final_descent=True)
+            [1, 2, 3]
+        """
+        p = self
+        descents = []
+        for i in range(len(p)-1):
+            if p[i] > p[i+1]:
+                descents.append(i)
+
+        if final_descent:
+            descents.append(len(p)-1)
+
+        return descents
+
+    def number_of_descents(self, final_descent=False):
+        r"""
+        Returns the number of descents of the permutation p.
+
+        EXAMPLES:
+            sage: Permutation([1,4,3,2]).number_of_descents()
+            2
+            sage: Permutation([1,4,3,2]).number_of_descents(final_descent=True)
+            3
+        """
+        return len(self.descents(final_descent))
+
+    def descents_composition(self):
+        """
+        Returns the composition corresponding to the descents of
+        the permutation.
+
+        EXAMPLES:
+            sage: Permutation([1,3,2,4]).descents_composition()
+            [2, 2]
+        """
+        d = self.descents()
+        d = [ -1 ] + d + [len(self)-1]
+        return [ d[i+1]-d[i] for i in range(len(d)-1)]
+
+    def descent_polynomial(self):
+        r"""
+        Returns the descent polynomial of the permutation p.
+
+        The descent polymomial of p is the product of all the
+        z[p[i]] where i ranges over the descents of p.
+
+        REFERENCES:
+            Garsia and Stanton 1984
+
+        EXAMPLES:
+            sage: Permutation([2,1,3]).descent_polynomial()
+            z1
+            sage: Permutation([4,3,2,1]).descent_polynomial()
+            z1*z2^2*z3^3
+        """
+        p = self
+        z = []
+        P = PolynomialRing(ZZ, len(p), 'z')
+        z = P.gens()
+        result = 1
+        pol = 1
+        for i in range(len(p)-1):
+            pol *= z[p[i]-1]
+            if p[i] > p[i+1]:
+                result *= pol
+
+        return result
+
+
+    ##############
+    # Major Code #
+    ##############
+
+    def major_index(self, final_descent=False):
+        r"""
+        Returns the major index of the permutation p.
+
+        The major index is the sum of the descents of p. Since our permutation
+        indices are 0-based, we need to add one the number of descents.
+
+        EXAMPLES:
+            sage: Permutation([2,1,3]).major_index()
+            1
+            sage: Permutation([3,4,1,2]).major_index()
+            2
+            sage: Permutation([4,3,2,1]).major_index()
+            6
+        """
+        descents = self.descents(final_descent)
+
+        return sum(descents)+len(descents)
+
+
+    def to_major_code(self, final_descent=False):
+        r"""
+        Returns the major code of the permutation p, which is defined
+        as the list [m1-m2, m2-m3,..,mn] where mi := maj(pi) is the
+        major indices of the permutation math obtained by erasing the
+        letters smaller than math in p.
+
+        REFERENCES:
+            Carlitz, L. 'q-Bernoulli and Eulerian Numbers' Trans. Amer. Math. Soc. 76 (1954) 332-350
+            Skandera, M. 'An Eulerian Partner for Inversions', Sem. Lothar. Combin. 46 (2001) B46d.
+
+        EXAMPLES:
+            sage: Permutation([9,3,5,7,2,1,4,6,8]).to_major_code()
+            [5, 0, 1, 0, 1, 2, 0, 1, 0]
+            sage: Permutation([2,8,4,3,6,7,9,5,1]).to_major_code()
+            [8, 3, 3, 1, 4, 0, 1, 0, 0]
+        """
+        p = self
+        major_indices = [0]*(len(p)+1)
+        smaller = p[:]
+        for i in range(len(p)):
+            major_indices[i] = Permutation(smaller).major_index(final_descent)
+            #Create the permutation that "erases" all the numbers
+            #smaller than i+1
+            smaller.remove(1)
+            smaller = [i-1 for i in smaller]
+
+        major_code = [ major_indices[i] - major_indices[i+1] for i in range(len(p)) ]
+        return major_code
+
+    #########
+    # Peaks #
+    #########
+
+    def peaks(self):
+        r"""
+        Returns a list of the peaks of the permutation p.
+
+        A peak of a permutation is an integer i such that
+        p[i-1] <= p[i] and p[i] > p[i+1].
+
+        EXAMPLES:
+            sage: Permutation([1,3,2,4,5]).peaks()
+            [1]
+            sage: Permutation([4,1,3,2,6,5]).peaks()
+            [2, 4]
+        """
+        p = self
+        peaks = []
+        for i in range(1,len(p)-1):
+            if p[i-1] <= p[i] and p[i] > p[i+1]:
+                peaks.append(i)
+
+        return peaks
+
+
+    def number_of_peaks(self):
+        r"""
+        Returns the number of peaks of the permutation p.
+
+        A peak of a permutation is an integer i such that
+        p[i-1] <= p[i] and p[i] > p[i+1].
+
+        EXAMPLES:
+            sage: Permutation([1,3,2,4,5]).number_of_peaks()
+            1
+            sage: Permutation([4,1,3,2,6,5]).number_of_peaks()
+            2
+        """
+        return len(self.peaks())
+
+    #############
+    # Saliances #
+    #############
+
+    def saliances(self):
+        r"""
+        Returns a list of the saliances of the permutation p.
+
+        A saliance of a permutation p is an integer i such that
+        p[i] > p[j] for all j > i.
+
+        EXAMPLES:
+            sage: Permutation([2,3,1,5,4]).saliances()
+            [3, 4]
+            sage: Permutation([5,4,3,2,1]).saliances()
+            [0, 1, 2, 3, 4]
+        """
+        p = self
+        saliances = []
+        for i in range(len(p)):
+            is_saliance = True
+            for j in range(i+1, len(p)):
+                if p[i] <= p[j]:
+                    is_saliance = False
+            if is_saliance:
+                saliances.append(i)
+
+        return saliances
+
+
+    def number_of_saliances(self):
+        r"""
+        Returns the number of saliances of the permutation p.
+
+        EXAMPLES:
+            sage: Permutation([2,3,1,5,4]).number_of_saliances()
+            2
+            sage: Permutation([5,4,3,2,1]).number_of_saliances()
+            5
+        """
+        return len(self.saliances())
+
+    ################
+    # Bruhat Order #
+    ################
+    def bruhat_lequal(self, p2):
+        r"""
+        Returns True if self is less than p2 in the Bruhat order.
+
+        EXAMPLES:
+            sage: Permutation([2,4,3,1]).bruhat_lequal(Permutation([3,4,2,1])) 
+            True
+
+        """
+        p1 = self
+        n1 = len(p1)
+        n2 = len(p2)
+
+        if n1 == 0:
+            return True
+
+        if p1[0] > p2[0] or p1[n1-1] < p2[n1-1]:
+            return False
+
+        for i in range(n1):
+            c = 0
+            for j in range(n1):
+                if p2[j] > i+1:
+                    c += 1
+                if p1[j] > i+1:
+                    c -= 1
+                if c < 0:
+                    return False
+
+        return True
+
+
+    def bruhat_inversions(self):
+        r"""
+        Returns the list of inversions of p such that the application of
+        this inversion to p decrements its number of inversions.
+
+        Equivalently, it returns the list of pairs (i,j), i<j  such that
+        p[i] > p[j] and such that there exists no k between i and j
+        satisfying p[i] > p[k].
+
+
+        EXAMPLES:
+            sage: Permutation([5,2,3,4,1]).bruhat_inversions()
+            [[0, 1], [0, 2], [0, 3], [1, 4], [2, 4], [3, 4]]
+            sage: Permutation([6,1,4,5,2,3]).bruhat_inversions()
+            [[0, 1], [0, 2], [0, 3], [2, 4], [2, 5], [3, 4], [3, 5]]
+        """
+        return __builtin__.list(self.bruhat_inversions_iterator())
+
+    def bruhat_inversions_iterator(self):
+        p = self
+        n = len(p)
+
+        for i in range(n-1):
+            for j in range(i+1,n):
+                if p[i] > p[j]:
+                    ok = True
+                    for k in range(i+1, j):
+                        if p[i] > p[k] and p[k] > p[j]:
+                            ok = False
+                            break
+                    if ok:
+                        yield [i,j]
+
+
+    def bruhat_succ(self):
+        r"""
+        Returns a list of the permutations strictly greater than p in the
+        Bruhat order such that there is no permutation between one of those
+        and p.
+
+        EXAMPLES:
+            sage: Permutation([6,1,4,5,2,3]).bruhat_succ()
+            [[6, 4, 1, 5, 2, 3],
+             [6, 2, 4, 5, 1, 3],
+             [6, 1, 5, 4, 2, 3],
+             [6, 1, 4, 5, 3, 2]]
+
+        """
+        return __builtin__.list(self.bruhat_succ_iterator())
+
+    def bruhat_succ_iterator(self):
+        """
+        An iterator for the permutations that are strictly greater than p in
+        the Bruhat order such that there is no permutation between one of
+        those and p.
+
+        EXAMPLES:
+            sage: [x for x in Permutation([6,1,4,5,2,3]).bruhat_succ_iterator()]
+            [[6, 4, 1, 5, 2, 3],
+             [6, 2, 4, 5, 1, 3],
+             [6, 1, 5, 4, 2, 3],
+             [6, 1, 4, 5, 3, 2]]            
+        """
+        p = self
+        n = len(p)
+
+        for z in Permutation(map(lambda x: n+1-x, p)).bruhat_inversions_iterator():
+            pp = p[:]
+            pp[z[0]] = p[z[1]]
+            pp[z[1]] = p[z[0]]
+            yield Permutation(pp)
+
+
+
+    def bruhat_pred(self):
+        r"""
+        Returns a list of the permutations strictly smaller than p in the
+        Bruhat order such that there is no permutation between one of those
+        and p.
+
+
+        EXAMPLES:
+        sage: Permutation([6,1,4,5,2,3]).bruhat_pred()
+        [[1, 6, 4, 5, 2, 3],
+         [4, 1, 6, 5, 2, 3],
+         [5, 1, 4, 6, 2, 3],
+         [6, 1, 2, 5, 4, 3],
+         [6, 1, 3, 5, 2, 4],
+         [6, 1, 4, 2, 5, 3],
+         [6, 1, 4, 3, 2, 5]]
+
+        """
+        return __builtin__.list(self.bruhat_pred_iterator())
+
+    def bruhat_pred_iterator(self):
+        """
+        An iterator for the permutations strictly smaller than p in the
+        Bruhat order such that there is no permutation between one of those
+        and p.
+
+
+        EXAMPLES:
+        sage: [x for x in Permutation([6,1,4,5,2,3]).bruhat_pred_iterator()]
+        [[1, 6, 4, 5, 2, 3],
+         [4, 1, 6, 5, 2, 3],
+         [5, 1, 4, 6, 2, 3],
+         [6, 1, 2, 5, 4, 3],
+         [6, 1, 3, 5, 2, 4],
+         [6, 1, 4, 2, 5, 3],
+         [6, 1, 4, 3, 2, 5]]
+
+        """
+        p = self
+        n = len(p)
+        for z in p.bruhat_inversions_iterator():
+            pp = p[:]
+            pp[z[0]] = p[z[1]]
+            pp[z[1]] = p[z[0]]
+            yield Permutation(pp)
+
+
+    def bruhat_smaller(self):
+        r"""
+        Returns a the combinatorial class of  permutations smaller than or equal
+        to p in the Bruhat order.
+
+        EXAMPLES:
+            sage: Permutation([4,1,2,3]).bruhat_smaller().list()
+            [[1, 2, 3, 4],
+             [1, 2, 4, 3],
+             [1, 3, 2, 4],
+             [1, 4, 2, 3],
+             [2, 1, 3, 4],
+             [2, 1, 4, 3],
+             [3, 1, 2, 4],
+             [4, 1, 2, 3]]
+
+        """
+        return StandardPermutations_bruhat_smaller(self)
+
+
+    def bruhat_greater(self):
+        r"""
+        Returns the combinatorial class of permutations greater than or equal
+        to p in the Bruhat order.
+
+        EXAMPLES:
+            sage: Permutation([4,1,2,3]).bruhat_greater().list()
+            [[4, 1, 2, 3],
+             [4, 1, 3, 2],
+             [4, 2, 1, 3],
+             [4, 2, 3, 1],
+             [4, 3, 1, 2],
+             [4, 3, 2, 1]]
+
+        """
+
+        return StandardPermutations_bruhat_greater(self)
+
+    ########################
+    # Permutohedron  Order #
+    ########################
+
+    def permutohedron_lequal(self, p2, side="right"):
+        r"""
+        Returns True if self is less than p2 in the permutohedron order.
+
+        By default, the computations are done in the right permutohedron.
+        If you pass the option side='left', then they will be done in the
+        left permutohedron.
+
+        EXAMPLES:
+            sage: p = Permutation([3,2,1,4])
+            sage: p.permutohedron_lequal(Permutation([4,2,1,3]))
+            False
+            sage: p.permutohedron_lequal(Permutation([4,2,1,3]), side='left') 
+            True
+        """
+        p1 = self
+        n1 = len(p1)
+        n2 = len(p2)
+
+        l1 = p1.number_of_inversions()
+        l2 = p2.number_of_inversions()
+
+        if l1 > l2:
+            return False
+
+        if side == "right":
+            prod = p1._left_to_right_multiply_on_right(p2.inverse())
+        else:
+            prod = p1._left_to_right_multiply_on_left(p2.inverse())
+
+        return prod.number_of_inversions() == l2 - l1
+
+    def permutohedron_succ(self, side="right"):
+        r"""
+        Returns a list of the permutations strictly greater than p in the
+        permutohedron order such that there is no permutation between
+        one of those and p.
+
+        By default, the computations are done in the right permutohedron.
+        If you pass the option side='left', then they will be done in the
+        left permutohedron.
+
+        EXAMPLES:
+            sage: p = Permutation([4,2,1,3])
+            sage: p.permutohedron_succ()
+            [[4, 2, 3, 1]]
+            sage: p.permutohedron_succ(side='left')
+            [[4, 3, 1, 2]]
+
+        """
+        p = self
+        n = len(p)
+        succ = []
+        if side == "right":
+            rise = lambda perm: filter(lambda i: perm[i] < perm[i+1], range(0,n-1))
+            for i in rise(p):
+                pp = p[:]
+                pp[i] = p[i+1]
+                pp[i+1] = p[i]
+                succ.append(Permutation(pp))
+        else:
+            advance = lambda perm: filter(lambda i: perm.index(i) < perm.index(i+1), range(1,n))
+            for i in advance(p):
+                pp = p[:]
+                pp[p.index(i)] = i+1
+                pp[p.index(i+1)] = i            
+                succ.append(Permutation(pp))
+
+        return succ
+
+
+    def permutohedron_pred(self, side="right"):
+        r"""
+        Returns a list of the permutations strictly smaller than p in the
+        permutohedron order such that there is no permutation between
+        one of those and p.
+
+        By default, the computations are done in the right permutohedron.
+        If you pass the option side='left', then they will be done in the
+        left permutohedron.
+
+        EXAMPLES:
+            sage: p = Permutation([4,2,1,3])
+            sage: p.permutohedron_pred()            
+            [[2, 4, 1, 3], [4, 1, 2, 3]]
+            sage: p.permutohedron_pred(side='left')
+            [[4, 1, 2, 3], [3, 2, 1, 4]]
+
+
+        """
+        p = self
+        n = len(p)
+        pred = []
+        if side == "right":
+            for d in p.descents():
+                pp = p[:]
+                pp[d] = p[d+1]
+                pp[d+1] = p[d]
+                pred.append(Permutation(pp))
+        else:
+            recoil = lambda perm: filter(lambda j: perm.index(j) > perm.index(j+1), range(1,n))
+            for i in recoil(p):
+                pp = p[:]
+                pp[p.index(i)] = i+1
+                pp[p.index(i+1)] = i
+                pred.append(Permutation(pp))
+        return pred
+
+
+    def permutohedron_smaller(self, side="right"):
+        r"""
+        Returns a list of permutations smaller than or equal to p in the
+        permutohedron order.
+
+        By default, the computations are done in the right permutohedron.
+        If you pass the option side='left', then they will be done in the
+        left permutohedron.
+
+        EXAMPLES:
+            sage: Permutation([4,2,1,3]).permutohedron_smaller()
+            [[1, 2, 3, 4],
+             [1, 2, 4, 3],
+             [1, 4, 2, 3],
+             [2, 1, 3, 4],
+             [2, 1, 4, 3],
+             [2, 4, 1, 3],
+             [4, 1, 2, 3],
+             [4, 2, 1, 3]]
+
+            sage: Permutation([4,2,1,3]).permutohedron_smaller(side='left')
+            [[1, 2, 3, 4],
+             [1, 3, 2, 4],
+             [2, 1, 3, 4],
+             [2, 3, 1, 4],
+             [3, 1, 2, 4],
+             [3, 2, 1, 4],
+             [4, 1, 2, 3],
+             [4, 2, 1, 3]]
+
+
+        """
+
+        return transitive_ideal(lambda x: x.permutohedron_pred(side), self)
+
+
+    def permutohedron_greater(self, side="right"):
+        r"""
+        Returns a list of permutations greater than or equal to p in the
+        permutohedron order.
+
+        By default, the computations are done in the right permutohedron.
+        If you pass the option side='left', then they will be done in the
+        left permutohedron.
+
+        EXAMPLES:
+            sage: Permutation([4,2,1,3]).permutohedron_greater()
+            [[4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 2, 1]]
+            sage: Permutation([4,2,1,3]).permutohedron_greater(side='left')
+            [[4, 2, 1, 3], [4, 3, 1, 2], [4, 3, 2, 1]]
+
+
+        """
+
+        return transitive_ideal(lambda x: x.permutohedron_succ(side), self)
+
+
+    ############
+    # Patterns #
+    ############
+
+    def has_pattern(self, patt):
+        r"""
+        Returns the boolean answering the question 'Is patt a patter appearing in
+        permutation p?'
+
+        EXAMPLES:
+            sage: Permutation([3,5,1,4,6,2]).has_pattern([1,3,2])
+            True
+        """
+        p = self
+        n = len(p)
+        l = len(patt)
+        if l > n:
+            return False
+        for pos in subword.Subwords(range(n),l):
+            if to_standard(map(lambda z: p[z] , pos)) == patt:
+                return True
+        return False
+
+    def avoids(self, patt):
+        """
+        Returns True if the permutation avoid the pattern patt and False
+        otherwise.
+
+        EXAMPLES:
+            sage: Permutation([6,2,5,4,3,1]).avoids([4,2,3,1])
+            False
+            sage: Permutation([6,1,2,5,4,3]).avoids([4,2,3,1])
+            True
+            sage: Permutation([6,1,2,5,4,3]).avoids([3,4,1,2])
+            True
+        """
+        return not self.has_pattern(patt)
+
+    def pattern_positions(self, patt):
+        r"""
+        Returns the list of positions where the pattern patt appears
+        in p.
+
+        EXAMPLES:
+            sage: Permutation([3,5,1,4,6,2]).pattern_positions([1,3,2])
+            [[0, 1, 3], [2, 3, 5], [2, 4, 5]]
+
+        """
+        p = self
+
+        return __builtin__.list(itertools.ifilter(lambda pos: to_standard(map(lambda z: p[z], pos)) == patt, subword.Subwords(range(len(p)), len(patt)).iterator() ))
+
+
+    def reverse(self):
+        """
+        Returns the permutation obtained by reversing the list.
+        
+        EXAMPLES:
+            sage: Permutation([3,4,1,2]).reverse()
+            [2, 1, 4, 3]
+            sage: Permutation([1,2,3,4,5]).reverse()
+            [5, 4, 3, 2, 1]
+        """
+        return Permutation_class( [i for i in reversed(self)] )
+
+
+    def complement(self):
+        """
+        Returns the complement of the permutation which is obtained
+        by replacing each value x in the list with n - x + 1
+        
+        EXAMPLES:
+            sage: Permutation([1,2,3]).complement()
+            [3, 2, 1]
+            sage: Permutation([1, 3, 2]).complement()
+            [3, 1, 2]
+        """
+        n = len(self)
+        return Permutation_class( map(lambda x: n - x + 1, self) )
+
+    def dict(self):
+        """
+        Returns a dictionary corresponding to the permutation.
+        
+        EXAMPLES:
+            sage: p = Permutation([2,1,3])
+            sage: d = p.dict()
+            sage: d[1]
+            2
+            sage: d[2]
+            1
+            sage: d[3]
+            3
+        """
+        d = {}
+        for i in range(len(self)):
+            d[i+1] = self[i]
+        return d
+
+    def action(self, a):
+        """
+        Return the action of the permutation on a list.
+        
+        EXAMPLES:
+            sage: p = Permutation([2,1,3])
+            sage: a = range(3)
+            sage: p.action(a)
+            [1, 0, 2]
+            sage: b = [1,2,3,4]
+            sage: p.action(b)
+            Traceback (most recent call last):
+            ...
+            ValueError: len(a) must equal len(self)
+        """
+        if len(a) != len(self):
+            raise ValueError, "len(a) must equal len(self)"
+        return map(lambda i: a[self[i]-1], range(len(a)))
+        
+    ######################
+    # Robinson-Schensted #
+    ######################
+
+    def robinson_schensted(self):
+        """
+        Returns the pair of standard tableau obtained by running the
+        Robinson-Schensted Algorithm on self.
+
+        EXAMPLES:
+            sage: p = Permutation([6,2,3,1,7,5,4])
+            sage: p.robinson_schensted()
+            [[[1, 3, 4], [2, 5], [6, 7]], [[1, 3, 5], [2, 6], [4, 7]]]
+
+        """
+
+        p = [[]]
+        q = [[]]
+
+        for i in range(1, len(self)+1):
+            #Row insert self[i-1] into p
+            row_counter = 0
+            r = p[row_counter]
+            x = self[i-1]
+            while max(r+[0]) > x:
+                y = min(filter(lambda z: z > x, r))
+                r[r.index(y)] = x
+                x = y
+                row_counter += 1
+                if row_counter == len(p):
+                    p.append([])
+                r = p[row_counter]
+            r.append(x)
+
+            
+            #Insert i into q in the same place as we inserted
+            #i into p
+            if row_counter == len(q):
+                q.append([])
+            q[row_counter].append(i)
+
+
+        return [Tableau(p),Tableau(q)]
+
+################################################################
+
+def Arrangements(mset, k):
+    r"""
+    An arrangement of mset is an ordered selection without repetitions
+    and is represented by a list that contains only elements from
+    mset, but maybe in a different order.
+
+    \code{Arrangements} returns the combinatorial class of arrangements
+    of the multiset mset that contain k elements.
+
+    EXAMPLES:
+        sage: mset = [1,1,2,3,4,4,5]
+        sage: Arrangements(mset,2).list()
+        [[1, 1],
+         [1, 2],
+         [1, 3],
+         [1, 4],
+         [1, 5],
+         [2, 1],
+         [2, 3],
+         [2, 4],
+         [2, 5],
+         [3, 1],
+         [3, 2],
+         [3, 4],
+         [3, 5],
+         [4, 1],
+         [4, 2],
+         [4, 3],
+         [4, 4],
+         [4, 5],
+         [5, 1],
+         [5, 2], 
+         [5, 3],
+         [5, 4]]
+         sage: Arrangements(mset,2).count()
+         22
+         sage: Arrangements( ["c","a","t"], 2 ).list()
+         [['c', 'a'], ['c', 't'], ['a', 'c'], ['a', 't'], ['t', 'c'], ['t', 'a']]
+         sage: Arrangements( ["c","a","t"], 3 ).list()
+         [['c', 'a', 't'],
+          ['c', 't', 'a'],
+          ['a', 'c', 't'],
+          ['a', 't', 'c'],
+          ['t', 'c', 'a'],
+          ['t', 'a', 'c']]
+    """
+    return Arrangements_msetk(mset, k)
+
+
+
+class Permutations_nk(CombinatorialClass):
+    def __init__(self, n, k):
+        """
+        TESTS:
+            sage: P = Permutations([3,2])
+            sage: P == loads(dumps(P))
+            True
+        """
+        self.n = n
+        self.k = k
+        
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(3,2))
+            'Permutations of {1,...,3} of length 2'
+        """
+        return "Permutations of {1,...,%s} of length %s"%(self.n, self.k)
+        
+    def iterator(self):
+        """
+        EXAMPLES:
+            sage: [p for p in Permutations(3,2)]
+            [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
+            sage: [p for p in Permutations(3,0)]
+            [[]]
+            sage: [p for p in Permutations(3,4)]
+            []
+        """
+        def label(x):
+            return x+1
+        for x in permutation_nk.iterator(self.n, self.k):
+            yield map(label, x)
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: Permutations(3,0).count()
+            1
+            sage: Permutations(3,1).count()
+            3
+            sage: Permutations(3,2).count()
+            6
+            sage: Permutations(3,3).count()
+            6
+            sage: Permutations(3,4).count()
+            0
+        """
+        if self.k <= self.n and self.k >= 0:
+            return factorial(self.n)/factorial(self.n-self.k)
+        else:
+            return 0
+
+class Permutations_mset(CombinatorialClass):
+    def __init__(self, mset):
+        """
+        TESTS:
+            sage: S = Permutations(['c','a','t'])
+            sage: S == loads(dumps(S))
+            True
+        """
+        self.mset = mset
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(['c','a','t']))
+            "Permutations of the (multi-)set ['c', 'a', 't']"
+        """
+        return "Permutations of the (multi-)set %s"%self.mset
+    
+    def iterator(self):
+        """
+        Algorithm based on:
+        http://marknelson.us/2002/03/01/next-permutation/
+
+        EXAMPLES:
+            sage: [ p for p in Permutations(['c','a','t'])]
+            [['c', 'a', 't'],
+             ['c', 't', 'a'],
+             ['a', 'c', 't'],
+             ['a', 't', 'c'],
+             ['t', 'c', 'a'],
+             ['t', 'a', 'c']]
+            sage: [ p for p in Permutations(['c','t','t'])]
+            [['c', 't', 't'], ['t', 'c', 't'], ['t', 't', 'c']]
+        """
+        mset = self.mset
+        n = len(self.mset)
+        lmset = __builtin__.list(mset)
+        mset_list = map(lambda x: lmset.index(x), lmset)
+        mset_list.sort()
+        
+        def label(x):
+            return lmset[x]
+
+        yield map(label, mset_list)
+
+        if n == 1:
+            return
+
+        while True:
+            one = n - 2
+            two = n - 1
+            j   = n - 1
+
+            #starting from the end, find the first o such that
+            #mset_list[o] < mset_list[o+1]
+            while two > 0 and mset_list[one] >= mset_list[two]:
+                one -= 1
+                two -= 1    
+
+            if two == 0:
+                return
+
+            #starting from the end, find the first j such that
+            #mset_list[j] > mset_list[one]
+            while mset_list[j] <= mset_list[one]:
+                j -= 1
+
+            #Swap positions one and j
+            t = mset_list[one]
+            mset_list[one] = mset_list[j]
+            mset_list[j] = t
+
+
+            #Reverse the list between two and last
+            i = int((n - two)/2)-1
+            #mset_list = mset_list[:two] + [x for x in reversed(mset_list[two:])]
+            while i >= 0:
+                t = mset_list[ i + two ]
+                mset_list[ i + two ] = mset_list[n-1 - i]
+                mset_list[n-1 - i] = t
+                i -= 1
+
+            #Yield the permutation
+            yield map(label, mset_list)
+
+        def count(self):
+            """
+            EXAMPLES:
+                sage: Permutations([1,2,3]).count()
+                6
+                sage: Permutations([1,2,2]).count()
+                3
+            """
+            lmset = __builtin__.list(mset)
+            mset_list = map(lambda x: lmset.index(x), lmset)
+            d = {}
+            for i in mset_list:
+                d[i] = d.get(i, 0) + 1
+
+            c = factorial(len(lmset))
+            for i in d:
+                if i != 1:
+                    c /= factorial(i)
+
+            return c
+                
+
+class Permutations_msetk(CombinatorialClass):
+    def __init__(self, mset, k):
+        """
+        TESTS:
+            sage: P = Permutations([1,2,2],2)
+            sage: P == loads(dumps(P))
+            True
+        """
+        self.mset = mset
+        self.k = k
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations([1,2,2],2))
+            'Permutations of the (multi-)set [1, 2, 2] of length 2'
+        """
+        return "Permutations of the (multi-)set %s of length %s"%(self.mset,self.k)
+
+    def list(self):
+        """
+        EXAMPLES:
+            sage: Permutations([1,2,3],2).list()
+            [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
+            sage: Permutations([1,2,2],2).list()
+            [[1, 2], [2, 1], [2, 2]]
+         """
+        mset = self.mset
+        n = len(self.mset)
+        lmset = __builtin__.list(mset)
+        mset_list = map(lambda x: lmset.index(x), lmset)
+
+        def label(x):
+            return lmset[x]
+
+        indices = eval(gap.eval('Arrangements(%s,%s)'%(mset_list, self.k)))
+        return map(lambda ktuple: map(label, ktuple), indices)
+
+
+class Arrangements_msetk(Permutations_msetk):
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Arrangements([1,2,3],2))
+            'Arrangements of the (multi-)set [1, 2, 3] of length 2'
+        """
+        return "Arrangements of the (multi-)set %s of length %s"%(self.mset,self.k)
+
+
+class StandardPermutations_all(CombinatorialClass):
+    def __init__(self):
+        """
+        TESTS:
+            sage: SP = Permutations()
+            sage: SP == loads(dumps(SP))
+            True
+        """
+        self.object_class = Permutation_class
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations())
+            'Standard permutations'
+        """
+        return "Standard permutations"
+
+    def __contains__(self,x):
+        """
+        TESTS:
+            sage: [] in Permutations()
+            False
+            sage: [1] in Permutations()
+            True
+            sage: [2] in Permutations()
+            False
+            sage: [1,2] in Permutations()
+            True
+            sage: [2,1] in Permutations()
+            True
+            sage: [1,2,2] in Permutations()
+            False
+            sage: [3,1,5,2] in Permutations()
+            False
+            sage: [3,4,1,5,2] in Permutations()
+            True
+        """
+        if isinstance(x, Permutation_class):
+            return True
+        elif isinstance(x, __builtin__.list):
+            if len(x) == 0:
+                return False
+            copy = x[:]
+            copy.sort()
+            if copy != range(1, len(x)+1):
+                return False
+            return True
+        else:
+            return False
+
+    def list(self):
+        """
+        EXAMPLES:
+            sage: Permutations().list()
+            Traceback (most recent call last):
+            ...
+            NotImplementedError
+        """
+        raise NotImplementedError
+    
+
+class StandardPermutations_n(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: SP = Permutations(3)
+            sage: SP == loads(dumps(SP))
+            True
+        """
+        self.n = n
+        self.object_class = Permutation_class
+
+
+    def __contains__(self,x):
+        """
+        TESTS:
+            sage: [1,2] in Permutations(2)
+            True
+            sage: [1,2] in Permutations(3)
+            False
+            sage: [3,2,1] in Permutations(3)
+            True
+        """
+        
+        return x in Permutations() and len(x) == self.n
+    
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(3))
+            'Standard permutations of 3'
+        """
+        return "Standard permutations of %s"%self.n
+    
+    def iterator(self):
+        """
+        EXAMPLES:
+            sage: [p for p in Permutations(3)]
+            [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
+        """
+        for p in Permutations_mset(range(1,self.n+1)):
+            yield Permutation_class(p)
+ 
+    def count(self):
+        """
+        EXAMPLES:
+            sage: Permutations(3).count()
+            6
+            sage: Permutations(4).count()
+            24
+        """
+        return factorial(self.n)
+
+    
+    def identity(self):
+        r"""
+        Returns the identity permutation of length n.
+
+        EXAMPLES:
+            sage: Permutations(4).identity()
+            [1, 2, 3, 4]
+        """
+
+        return Permutation_class(range(1,self.n+1))
+
+    def unrank(self, r):
+        """
+        EXAMPLES:
+            sage: SP3 = Permutations(3)
+            sage: l = map(SP3.unrank, range(6))
+            sage: l == SP3.list()
+            True
+        """
+        return from_rank(self.n, r)
+
+    def rank(self, p):
+        """
+        EXAMPLES:
+            sage: SP3 = Permutations(3)
+            sage: map(SP3.rank, SP3)
+            [0, 1, 2, 3, 4, 5]
+        """
+        return Permutation(p).rank()
+
+    def random(self):
+        """
+        EXAMPLES:
+            sage: Permutations(4).random() #random
+            [3, 4, 1, 2]
+        """
+        r = randint(0, int(factorial(self.n)-1))
+        return self.unrank(r)
+
+
+
+#############################
+# Constructing Permutations #
+#############################
+def from_permutation_group_element(pge):
+    """
+    Returns a Permutation give a PermutationGroupElement pge.
+
+    EXAMPLES:
+        sage: pge = PermutationGroupElement([(1,2),(3,4)])
+        sage: permutation.from_permutation_group_element(pge)
+        [2, 1, 4, 3]
+    """
+
+    if not isinstance(pge, PermutationGroupElement):
+        raise TypeError, "pge (= %s) must be a PermutationGroupElement"%pge
+
+    return Permutation(pge.list())
+
+    
+
+def from_rank(n, rank):
+    r"""
+    Returns the permutation with the specified lexicographic
+    rank.  The permutation is of the set [1,...,n].
+
+    The permutation is computed without iteratiing through all
+    of the permutations with lower rank.  This makes it efficient
+    for large permutations.
+
+    EXAMPLES:
+        sage: Permutation([3, 6, 5, 4, 2, 1]).rank()
+        359
+        sage: [permutation.from_rank(3, i) for i in range(6)]
+        [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
+        sage: Permutations(6)[10]
+        [1, 2, 4, 6, 3, 5]
+        sage: permutation.from_rank(6,10)
+        [1, 2, 4, 6, 3, 5]
+
+    """
+
+    #Find the factoradic of rank
+    factoradic = [None] * n
+    for j in range(1,n+1):
+        factoradic[n-j] = Integer(rank % j)
+        rank = int(rank) / int(j)
+
+    return from_lehmer_code(factoradic)
+
+def from_inversion_vector(iv):
+    r"""
+    Returns the permutation corresponding to inversion vector iv.
+
+    EXAMPLES:
+        sage: permutation.from_inversion_vector([3,1,0,0,0])
+        [3, 2, 4, 1, 5]
+        sage: permutation.from_inversion_vector([2,3,6,4,0,2,2,1,0])
+        [5, 9, 1, 8, 2, 6, 4, 7, 3]
+
+    """
+
+    p = [None] * len(iv)
+    open_spots = range(len(iv))
+    
+    for i in range(len(iv)):
+        if iv[i] != 0:
+            p[open_spots[iv[i]]] = i+1
+            open_spots.remove(open_spots[iv[i]])
+        else:
+            p[open_spots[0]] = i+1
+            open_spots.remove(open_spots[0])
+    return Permutation(p)
+
+
+
+
+def from_cycles(n, cycles):
+    r"""
+    Returns the permutation corresponding to cycles.
+
+    EXAMPLES:
+        sage: permutation.from_cycles(4, [[1,2]])
+        [2, 1, 3, 4]
+        
+    """
+    
+    p = range(1,n+1)
+    for cycle in cycles:
+        first = cycle[0]
+        for i in range(len(cycle)-1):
+            p[cycle[i]-1] = cycle[i+1]
+        p[cycle[-1]-1] = first
+    return Permutation(p)
+
+def from_lehmer_code(lehmer):
+    r"""
+    Returns the permutation with Lehmer code lehmer.
+
+    EXAMPLES: 
+        sage: Permutation([2,1,5,4,3]).to_lehmer_code()
+        [1, 0, 2, 1, 0]
+        sage: permutation.from_lehmer_code(_)  
+        [2, 1, 5, 4, 3]
+
+    """
+    
+    n = len(lehmer)
+    perm = [None] * n
+    
+    #Convert the factoradic to a permutation
+    temp = [None] * n
+    for i in range(n):
+        lehmer[i] += 1
+        temp[i] = lehmer[i]
+
+    perm[n-1] = 1
+    for i in reversed(range(n-1)):
+        perm[i] = temp[i]
+        for j in range(i+1, n):
+            if perm[j] >= perm[i]:
+                perm[j] += 1
+
+    return Permutation([ p for p in perm ])
+
+def from_reduced_word(rw):
+    r"""
+    Returns the permutation corresponding to the reduced
+    word rw.
+
+    EXAMPLES:
+        sage: permutation.from_reduced_word([3,2,3,1,2,3,1])
+        [3, 4, 2, 1]
+    """
+
+    p = [i+1 for i in range(max(rw)+1)]
+
+    for i in rw:
+        (p[i-1], p[i]) = (p[i], p[i-1])
+
+    return Permutation(p)
+
+
+class StandardPermutations_descents(CombinatorialClass):
+    def __init__(self, d, n):
+        """
+        TESTS:
+            sage: P = Permutations(descents=([1,0,4,8],12))
+            sage: P == loads(dumps(P))
+            True
+        """
+        self.d = d
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(descents=([1,0,4,8],12)))
+            'Standard permutations of 12 with descents [1, 0, 4, 8]'
+        """
+        return "Standard permutations of %s with descents %s"%(self.n, self.d)
+
+    __object_class = Permutation_class
+
+    def first(self):
+        """
+        Returns the first permutation with descents d.
+
+        EXAMPLES:
+            sage: Permutations(descents=([1,0,4,8],12)).first()
+            [3, 2, 1, 4, 6, 5, 7, 8, 10, 9, 11, 12]
+
+        """
+        return descents_composition_first(Composition(descents=(self.d,self.n)))       
+
+
+    def last(self):
+        """
+        Returns the last permutation with descents d.
+
+        EXAMPLES:
+            sage: Permutations(descents=([1,0,4,8],12)).last()
+            [12, 11, 8, 9, 10, 4, 5, 6, 7, 1, 2, 3]
+        """
+        return descents_composition_last(Composition(descents=(self.d,self.n)))
+
+    def list(self):
+        """
+        Returns a list of all the permutations that have the
+        descents d.
+
+        EXAMPLES:
+             sage: Permutations(descents=([2,4,0],5)).list()
+             [[2, 1, 4, 3, 5],
+              [2, 1, 5, 3, 4],
+              [3, 1, 4, 2, 5],
+              [3, 1, 5, 2, 4],
+              [4, 1, 3, 2, 5],
+              [5, 1, 3, 2, 4],
+              [4, 1, 5, 2, 3],
+              [5, 1, 4, 2, 3],
+              [3, 2, 4, 1, 5],
+              [3, 2, 5, 1, 4],
+              [4, 2, 3, 1, 5],
+              [5, 2, 3, 1, 4],
+              [4, 2, 5, 1, 3],
+              [5, 2, 4, 1, 3],
+              [4, 3, 5, 1, 2],
+              [5, 3, 4, 1, 2]]
+         """
+
+        return descents_composition_list(Composition(descents=(self.d,self.n)))
+
+
+
+def descents_composition_list(dc):
+    """
+    Returns a list of all the permutations that have a descent
+    compositions dc.
+
+    EXAMPLES:
+        sage: permutation.descents_composition_list([1,2,2])
+        [[2, 1, 4, 3, 5],
+         [2, 1, 5, 3, 4],
+         [3, 1, 4, 2, 5],
+         [3, 1, 5, 2, 4],
+         [4, 1, 3, 2, 5],
+         [5, 1, 3, 2, 4],
+         [4, 1, 5, 2, 3],
+         [5, 1, 4, 2, 3],
+         [3, 2, 4, 1, 5],
+         [3, 2, 5, 1, 4],
+         [4, 2, 3, 1, 5],
+         [5, 2, 3, 1, 4],
+         [4, 2, 5, 1, 3],
+         [5, 2, 4, 1, 3],
+         [4, 3, 5, 1, 2],
+         [5, 3, 4, 1, 2]]
+    """
+    return map(lambda p: p.inverse(), StandardPermutations_recoils(dc).list())
+
+def descents_composition_first(dc):
+    r"""
+    Computes the smallest element of a descent class having
+    a descent decomposition dc.
+
+    EXAMPLES:
+        sage: permutation.descents_composition_first([1,1,3,4,3])
+        [3, 2, 1, 4, 6, 5, 7, 8, 10, 9, 11, 12]
+    """
+
+    if not isinstance(dc, Composition_class):
+        try:
+            dc = Composition(dc)
+        except TypeError:
+            raise TypeError, "The argument must be of type Composition"
+
+    cpl = [x for x in reversed(dc.conjugate())]
+    res = []
+    s = 0
+    for i in range(len(cpl)):
+        res += [s + cpl[i]-j for j in range(cpl[i])]
+        s   += cpl[i]
+
+    return Permutation(res)
+
+def descents_composition_last(dc):
+    r"""
+    Returns the largest element of a descent class having
+    a descent decomposition dc.
+
+    EXAMPLES:
+        sage: permutation.descents_composition_last([1,1,3,4,3])
+        [12, 11, 8, 9, 10, 4, 5, 6, 7, 1, 2, 3]
+
+    """
+    if not isinstance(dc, Composition_class):
+        try:
+            dc = Composition(dc)
+        except TypeError:
+            raise TypeError, "The argument must be of type Composition"
+    s = 0
+    res = []
+    for i in reversed(range(len(dc))):
+        res = [j for j in range(s+1,s+dc[i]+1)] + res
+        s += dc[i]
+
+    return Permutation(res)
+
+
+class StandardPermutations_recoilsfiner(CombinatorialClass):
+    def __init__(self, recoils):
+        """
+        TESTS:
+            sage: P = Permutations(recoils_finer=[2,2])
+            sage: P == loads(dumps(P))
+            True
+        """
+        self.recoils = recoils
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(recoils_finer=[2,2]))
+            'Standard permutations whose recoils composition is finer than [2, 2]'
+        """
+        return "Standard permutations whose recoils composition is finer than %s"%self.recoils
+
+    __object_class = Permutation_class
+    
+    def list(self):
+        """
+        Returns a list of all of the permutations whose
+        recoils composition is finer than recoils.
+
+        EXAMPLES:
+            sage: Permutations(recoils_finer=[2,2]).list()
+            [[1, 2, 3, 4],
+             [1, 3, 2, 4],
+             [1, 3, 4, 2],
+             [3, 1, 2, 4],
+             [3, 1, 4, 2],
+             [3, 4, 1, 2]]
+        """
+        recoils = self.recoils
+        dag = DiGraph()
+
+        #Add the nodes
+        for i in range(1, sum(recoils)+1):
+            dag.add_vertex(i)
+
+        #Add the edges to guarantee a finer recoil composition
+        pos = 1
+        for part in recoils:
+            for i in range(part-1):
+                dag.add_edge(pos, pos+1)
+                pos += 1
+            pos += 1
+
+        rcf = []
+        for le in dag.topological_sort_generator():
+            rcf.append(Permutation(le))
+        return rcf
+
+    
+class StandardPermutations_recoilsfatter(CombinatorialClass):
+    def __init__(self, recoils):
+        """
+        TESTS:
+            sage: P = Permutations(recoils_fatter=[2,2])
+            sage: P == loads(dumps(P))
+            True
+        """
+        self.recoils = recoils
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(recoils_fatter=[2,2]))
+            'Standard permutations whose recoils composition is fatter than [2, 2]'
+        """
+        return "Standard permutations whose recoils composition is fatter than %s"%self.recoils
+
+    __object_class = Permutation_class
+
+    def list(self):
+        """
+        Returns a list of all of the permutations whose
+        recoils composition is fatter than recoils.
+
+        EXAMPLES:
+            sage: Permutations(recoils_fatter=[2,2]).list()
+            [[1, 3, 2, 4],
+             [1, 3, 4, 2],
+             [1, 4, 3, 2],
+             [3, 1, 2, 4],
+             [3, 1, 4, 2],
+             [3, 2, 1, 4],
+             [3, 2, 4, 1],
+             [3, 4, 1, 2],
+             [3, 4, 2, 1],
+             [4, 1, 3, 2],
+             [4, 3, 1, 2],
+             [4, 3, 2, 1]]
+        """
+        recoils = self.recoils
+        dag = DiGraph()
+
+        #Add the nodes
+        for i in range(1, sum(recoils)+1):
+            dag.add_vertex(i)
+
+        #Add the edges to guarantee a fatter recoil composition
+        pos = 0
+        for i in range(len(recoils)-1):
+            pos += recoils[i]
+            dag.add_edge(pos+1, pos)
+
+
+        rcf = []
+        for le in dag.topological_sort_generator():
+            rcf.append(Permutation(le))
+        return rcf
+
+class StandardPermutations_recoils(CombinatorialClass):
+    def __init__(self, recoils):
+        """
+        TESTS:
+            sage: P = Permutations(recoils=[2,2])
+            sage: P == loads(dumps(P))
+            True
+        """
+        self.recoils = recoils
+        
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(recoils=[2,2]))
+            'Standard permutations whose recoils composition is [2, 2]'
+        """
+        return "Standard permutations whose recoils composition is %s"%self.recoils
+
+    __object_class = Permutation_class
+
+
+    def list(self):
+        """
+        Returns a list of all of the permutations whose
+        recoils composition is equal to recoils.
+
+        EXAMPLES:
+            sage: Permutations(recoils=[2,2]).list()
+            [[1, 3, 2, 4], [1, 3, 4, 2], [3, 1, 2, 4], [3, 1, 4, 2], [3, 4, 1, 2]]
+        """
+        
+        recoils = self.recoils
+        dag = DiGraph()
+
+        #Add all the nodes
+        for i in range(1, sum(recoils)+1):
+            dag.add_vertex(i)
+
+        #Add the edges which guarantee a finer recoil comp.
+        pos = 1
+        for part in recoils:
+            for i in range(part-1):
+                dag.add_edge(pos, pos+1)
+                pos += 1
+            pos += 1
+
+        #Add the edges which guarantee a fatter recoil comp.
+        pos = 0
+        for i in range(len(recoils)-1):
+            pos += recoils[i]
+            dag.add_edge(pos+1, pos)
+
+        rcf = []
+        for le in dag.topological_sort_generator():
+            rcf.append(Permutation(le))
+        return rcf
+
+
+
+def from_major_code(mc, final_descent=False):
+    r"""
+    Returns the permutation corresponding to major code mc.
+
+    REFERENCES:
+        Skandera, M. 'An Eulerian Partner for Inversions', Sem. Lothar. Combin. 46 (2001) B46d.
+
+    EXAMPLES:
+        sage: permutation.from_major_code([5, 0, 1, 0, 1, 2, 0, 1, 0])
+        [9, 3, 5, 7, 2, 1, 4, 6, 8]
+        sage: permutation.from_major_code([8, 3, 3, 1, 4, 0, 1, 0, 0])
+        [2, 8, 4, 3, 6, 7, 9, 5, 1]
+        sage: Permutation([2,1,6,4,7,3,5]).to_major_code()
+        [3, 2, 0, 2, 2, 0, 0]
+        sage: permutation.from_major_code([3, 2, 0, 2, 2, 0, 0])
+        [2, 1, 6, 4, 7, 3, 5]
+
+    """
+    #define w^(n) to be the one-letter word n
+    w = [len(mc)]
+
+    #for i=n-1,..,1 let w^i be the unique word obtained by inserting
+    #the letter i into the word w^(i+1) in such a way that 
+    #maj(w^i)-maj(w^(i+1)) = mc[i]
+    for i in reversed(range(1,len(mc))):
+        #Lemma 2.2 in Skandera
+
+        #Get the descents of w and place them in reverse order
+        d = Permutation(w).descents()
+        d.reverse()
+
+        #a is the list of all positions which are not descents
+        a = filter(lambda x: x not in d, range(len(w)))
+
+        #k is the number of desecents
+        k = len(d)
+
+        #d_k = -1    -- 0 in the lemma, but -1 due to 0-based indexing
+        d.append(-1)
+
+        
+        l = mc[i-1]
+
+
+        indices = d + a
+        w.insert(indices[l]+1, i)
+
+    #pi = 
+    return Permutation(w)
+
+
+class StandardPermutations_bruhat_smaller(CombinatorialClass):
+    def __init__(self, p):
+        """
+        TESTS:
+            sage: P = Permutations(bruhat_smaller=[3,2,1])
+            sage: P == loads(dumps(P))
+            True
+        """
+        self.p = p
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(bruhat_smaller=[3,2,1]))
+            'Standard permutations that are less than or equal to [3, 2, 1] in the Bruhat order'
+        """
+        return "Standard permutations that are less than or equal to %s in the Bruhat order"%self.p
+
+    def list(self):
+        r"""
+        Returns a list of permutations smaller than or equal to p in the
+        Bruhat order.
+
+        EXAMPLES:
+            sage: Permutations(bruhat_smaller=[4,1,2,3]).list()
+            [[1, 2, 3, 4],
+             [1, 2, 4, 3],
+             [1, 3, 2, 4],
+             [1, 4, 2, 3],
+             [2, 1, 3, 4],
+             [2, 1, 4, 3],
+             [3, 1, 2, 4],
+             [4, 1, 2, 3]]
+        """
+        return transitive_ideal(lambda x: x.bruhat_pred(), self.p)
+
+
+
+class StandardPermutations_bruhat_greater(CombinatorialClass):
+    def __init__(self, p):
+        """
+        TESTS:
+            sage: P = Permutations(bruhat_greater=[3,2,1])
+            sage: P == loads(dumps(P))
+            True
+        """
+        self.p = p
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(bruhat_greater=[3,2,1]))
+            'Standard permutations that are greater than or equal to [3, 2, 1] in the Bruhat order'
+        """
+        return "Standard permutations that are greater than or equal to %s in the Bruhat order"%self.p
+
+    def list(self):
+        r"""
+        Returns a list of permutations greater than or equal to p in the
+        Bruhat order.
+
+        EXAMPLES:
+            sage: Permutations(bruhat_greater=[4,1,2,3]).list()
+            [[4, 1, 2, 3],
+             [4, 1, 3, 2],
+             [4, 2, 1, 3],
+             [4, 2, 3, 1],
+             [4, 3, 1, 2],
+             [4, 3, 2, 1]]
+        """
+        return transitive_ideal(lambda x: x.bruhat_succ(), self.p)
+
+
+################
+# Bruhat Order #
+################
+
+def bruhat_lequal(p1, p2):
+    r"""
+    Returns True if p1 is less than p2in the Bruhat order.
+
+    Algorithm from mupad-combinat.
+
+    EXAMPLES:
+        sage: permutation.bruhat_lequal([2,4,3,1],[3,4,2,1]) 
+        True
+    """
+
+    n1 = len(p1)
+    n2 = len(p2)
+
+    if n1 == 0:
+        return True
+    
+    if p1[0] > p2[0] or p1[n1-1] < p2[n1-1]:
+        return False
+
+    for i in range(n1):
+        c = 0
+        for j in range(n1):
+            if p2[j] > i+1:
+                c += 1
+            if p1[j] > i+1:
+                c -= 1
+            if c < 0:
+                return False
+
+    return True
+
+
+
+#################
+# Permutohedron #
+#################
+
+def permutohedron_lequal(p1, p2, side="right"):
+    r"""
+    Returns True if p1 is less than p2in the permutohedron order.
+
+    By default, the computations are done in the right permutohedron.
+    If you pass the option side='left', then they will be done in the
+    left permutohedron.
+
+
+    EXAMPLES:
+        sage: permutation.permutohedron_lequal(Permutation([3,2,1,4]),Permutation([4,2,1,3]))
+        False
+        sage: permutation.permutohedron_lequal(Permutation([3,2,1,4]),Permutation([4,2,1,3]), side='left')
+        True
+    
+    
+    """
+
+    n1 = len(p1)
+    n2 = len(p2)
+
+    l1 = p1.number_of_inversions()
+    l2 = p2.number_of_inversions()
+
+    if l1 > l2:
+        return Fal
+
+    if side == "right":
+        prod = p1._left_to_right_multiply_on_right(p2.inverse())
+    else:
+        prod = p1._left_to_right_multiply_on_left(p2.inverse())
+
+
+    return prod.number_of_inversions() == l2 - l1
+
+
+############
+# Patterns #
+############
+
+def to_standard(p):
+    r"""
+    Returns a standard permutation corresponding to the
+    permutation p.
+
+    EXAMPLES:
+        sage: permutation.to_standard([4,2,7])
+        [2, 1, 3]
+        sage: permutation.to_standard([1,2,3])
+        [1, 2, 3]
+    """
+
+    s = p[:]
+    biggest = max(p) + 1
+    i = 1
+    for j in range(len(p)):
+        smallest = min(p)
+        smallest_index = p.index(smallest)
+        s[smallest_index] = i
+        i += 1
+        p[smallest_index] = biggest
+
+    return Permutation(s)
+
+
+
+##########################################################
+
+
+def CyclicPermutations(mset):
+    """
+    Returns the combinatorial class of all cyclic permutations of mset in
+    cycle notation.
+    
+    EXAMPLES:
+        sage: CyclicPermutations(range(4)).list()
+        [[0, 1, 2, 3],
+         [0, 1, 3, 2],
+         [0, 2, 1, 3],
+         [0, 2, 3, 1],
+         [0, 3, 1, 2],
+         [0, 3, 2, 1]]
+        sage: CyclicPermutations([1,1,1]).list()
+        [[1, 1, 1]]
+    """
+    return CyclicPermutations_mset(mset)
+
+class CyclicPermutations_mset(CombinatorialClass):
+    def __init__(self, mset):
+        """
+        TESTS:
+            sage: CP = CyclicPermutations(range(4))
+            sage: CP == loads(dumps(CP))
+            True
+        """
+        self.mset = mset
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(CyclicPermutations(range(4)))
+            'Cyclic permutations of [0, 1, 2, 3]'
+        """
+        return "Cyclic permutations of %s"%self.mset
+
+    def list(self, distinct=False):
+        return [p for p in self.iterator(distinct=distinct)]
+
+    def iterator(self, distinct=False):
+        """
+        EXAMPLES:
+            sage: CyclicPermutations(range(4)).list()
+            [[0, 1, 2, 3],
+             [0, 1, 3, 2],
+             [0, 2, 1, 3],
+             [0, 2, 3, 1],
+             [0, 3, 1, 2],
+             [0, 3, 2, 1]]
+             sage: CyclicPermutations([1,1,1]).list()
+             [[1, 1, 1]]
+             sage: CyclicPermutations([1,1,1]).list(distinct=True)
+             [[1, 1, 1], [1, 1, 1]]
+        """
+        if distinct:
+            content = [1]*len(self.mset)
+        else:
+            content = [0]*len(self.mset)
+            index_list = map(self.mset.index, self.mset)
+            for i in index_list:
+                content[i] += 1
+            
+        def label(x):
+            return self.mset[x-1]
+        
+        for necklace in Necklaces(content):
+            yield map(label, necklace)
+
+##########################################3
+
+def CyclicPermutationsOfPartition(partition):
+    """
+    Returns the combinatorial class of all combinations of cyclic permutations of
+    each cell of the partition.
+
+    EXAMPLES:
+        sage: CyclicPermutationsOfPartition([[1,2,3,4],[5,6,7]]).list()
+        [[[1, 2, 3, 4], [5, 6, 7]],
+         [[1, 2, 4, 3], [5, 6, 7]],
+         [[1, 3, 2, 4], [5, 6, 7]],
+         [[1, 3, 4, 2], [5, 6, 7]],
+         [[1, 4, 2, 3], [5, 6, 7]],
+         [[1, 4, 3, 2], [5, 6, 7]],
+         [[1, 2, 3, 4], [5, 7, 6]],
+         [[1, 2, 4, 3], [5, 7, 6]],
+         [[1, 3, 2, 4], [5, 7, 6]],
+         [[1, 3, 4, 2], [5, 7, 6]],
+         [[1, 4, 2, 3], [5, 7, 6]],
+         [[1, 4, 3, 2], [5, 7, 6]]]
+         
+        sage: CyclicPermutationsOfPartition([[1,2,3,4],[4,4,4]]).list()
+        [[[1, 2, 3, 4], [4, 4, 4]],
+         [[1, 2, 4, 3], [4, 4, 4]],
+         [[1, 3, 2, 4], [4, 4, 4]],
+         [[1, 3, 4, 2], [4, 4, 4]],
+         [[1, 4, 2, 3], [4, 4, 4]],
+         [[1, 4, 3, 2], [4, 4, 4]]]
+         
+        sage: CyclicPermutationsOfPartition([[1,2,3],[4,4,4]]).list()
+        [[[1, 2, 3], [4, 4, 4]], [[1, 3, 2], [4, 4, 4]]]
+        
+        sage: CyclicPermutationsOfPartition([[1,2,3],[4,4,4]]).list(distinct=True)
+        [[[1, 2, 3], [4, 4, 4]],
+         [[1, 3, 2], [4, 4, 4]],
+         [[1, 2, 3], [4, 4, 4]],
+         [[1, 3, 2], [4, 4, 4]]]
+    """
+    return CyclicPermutationsOfPartition_partition(partition)
+
+class CyclicPermutationsOfPartition_partition(CombinatorialClass):
+    def __init__(self, partition):
+        """
+        TESTS:
+            sage: CP = CyclicPermutationsOfPartition([[1,2,3,4],[5,6,7]])
+            sage: CP == loads(dumps(CP))
+            True
+        """
+        self.partition = partition
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(CyclicPermutationsOfPartition([[1,2,3,4],[5,6,7]]))
+            'Cyclic permutations of partition [[1, 2, 3, 4], [5, 6, 7]]'
+        """
+        return "Cyclic permutations of partition %s"%self.partition
+
+    def iterator(self, distinct=False):
+        """
+        AUTHOR: Robert Miller
+
+        EXAMPLES:
+            sage: CyclicPermutationsOfPartition([[1,2,3,4],[5,6,7]]).list()
+            [[[1, 2, 3, 4], [5, 6, 7]],
+             [[1, 2, 4, 3], [5, 6, 7]],
+             [[1, 3, 2, 4], [5, 6, 7]],
+             [[1, 3, 4, 2], [5, 6, 7]],
+             [[1, 4, 2, 3], [5, 6, 7]],
+             [[1, 4, 3, 2], [5, 6, 7]],
+             [[1, 2, 3, 4], [5, 7, 6]],
+             [[1, 2, 4, 3], [5, 7, 6]],
+             [[1, 3, 2, 4], [5, 7, 6]],
+             [[1, 3, 4, 2], [5, 7, 6]],
+             [[1, 4, 2, 3], [5, 7, 6]],
+             [[1, 4, 3, 2], [5, 7, 6]]]
+
+            sage: CyclicPermutationsOfPartition([[1,2,3,4],[4,4,4]]).list()
+            [[[1, 2, 3, 4], [4, 4, 4]],
+             [[1, 2, 4, 3], [4, 4, 4]],
+             [[1, 3, 2, 4], [4, 4, 4]],
+             [[1, 3, 4, 2], [4, 4, 4]],
+             [[1, 4, 2, 3], [4, 4, 4]],
+             [[1, 4, 3, 2], [4, 4, 4]]]
+
+            sage: CyclicPermutationsOfPartition([[1,2,3],[4,4,4]]).list()
+            [[[1, 2, 3], [4, 4, 4]], [[1, 3, 2], [4, 4, 4]]]
+
+            sage: CyclicPermutationsOfPartition([[1,2,3],[4,4,4]]).list(distinct=True)
+            [[[1, 2, 3], [4, 4, 4]],
+             [[1, 3, 2], [4, 4, 4]],
+             [[1, 2, 3], [4, 4, 4]],
+             [[1, 3, 2], [4, 4, 4]]]
+        """
+        
+        if len(self.partition) == 1:
+            for i in CyclicPermutations_mset(self.partition[0]).iterator(distinct=distinct):
+                yield [i]
+        else:
+            for right in CyclicPermutationsOfPartition_partition(self.partition[1:]).iterator(distinct=distinct):
+                for perm in CyclicPermutations_mset(self.partition[0]).iterator(distinct=distinct):
+                    yield [perm] + right
+
+
+    def list(self, distinct=False):
+        """
+        EXAMPLES:
+            sage: CyclicPermutationsOfPartition([[1,2,3],[4,4,4]]).list()
+            [[[1, 2, 3], [4, 4, 4]], [[1, 3, 2], [4, 4, 4]]]
+            sage: CyclicPermutationsOfPartition([[1,2,3],[4,4,4]]).list(distinct=True)
+            [[[1, 2, 3], [4, 4, 4]],
+             [[1, 3, 2], [4, 4, 4]],
+             [[1, 2, 3], [4, 4, 4]],
+             [[1, 3, 2], [4, 4, 4]]]
+        """
+
+        return [p for p in self.iterator(distinct=distinct)]
+
+
+
+######
+#Avoiding
+
+
+class StandardPermutations_avoiding_12(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: p = Permutations(3, avoiding=[1,2])
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(3, avoiding=[1,2]))
+            'Standard permutations of 3 avoiding [1, 2]'
+        """
+        return "Standard permutations of %s avoiding [1, 2]"%self.n
+
+    def list(self):
+        """
+        EXAMPLES:
+            sage: Permutations(3, avoiding=[1,2]).list()
+            [[3, 2, 1]]
+        """
+        return [Permutation_class(range(self.n, 0, -1))]
+
+class StandardPermutations_avoiding_21(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: p = Permutations(3, avoiding=[2,1])
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(3, avoiding=[2,1]))
+            'Standard permutations of 3 avoiding [2, 1]'
+        """
+        return "Standard permutations of %s avoiding [2, 1]"%self.n
+
+    def list(self):
+        """
+        EXAMPLES:
+            sage: Permutations(3, avoiding=[2,1]).list()
+            [[1, 2, 3]]
+        """
+        return [Permutation_class(range(1, self.n+1))]
+
+
+class StandardPermutations_avoiding_132(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: p = Permutations(3, avoiding=[1,3,2])
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(3, avoiding=[1,3,2]))
+            'Standard permutations of 3 avoiding [1, 3, 2]'
+        """
+        return "Standard permutations of %s avoiding [1, 3, 2]"%self.n
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: Permutations(5, avoiding=[1, 3, 2]).count()
+            42
+            sage: len( Permutations(5, avoiding=[1, 3, 2]).list() )
+            42
+        """
+        return catalan_number(self.n)
+
+    def iterator(self):
+        """
+        EXAMPLES:
+            sage: Permutations(3, avoiding=[1,3,2]).list()
+            [[1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
+            sage: Permutations(4, avoiding=[1,3,2]).list()
+            [[4, 1, 3, 2],
+             [4, 2, 1, 3],
+             [4, 2, 3, 1],
+             [4, 3, 1, 2],
+             [4, 3, 2, 1],
+             [3, 4, 1, 2],
+             [3, 4, 2, 1],
+             [2, 3, 4, 1],
+             [3, 2, 4, 1],
+             [1, 3, 2, 4],
+             [2, 1, 3, 4],
+             [2, 3, 1, 4],
+             [3, 1, 2, 4],
+             [3, 2, 1, 4]]
+
+        """
+        if self.n == 0:
+            return
+        
+        elif self.n < 3:
+            for p in StandardPermutations_n(self.n):
+                yield p
+            return
+
+        elif self.n == 3:
+            for p in StandardPermutations_n(self.n):
+                if p != [1, 2, 3]:
+                    yield p
+            return 
+
+
+        
+        #Yield all the 132 avoiding permutations to the right.
+        for right in StandardPermutations_avoiding_132(self.n - 1):
+            yield Permutation_class([self.n] + list(right))
+
+        #yi
+        for i in range(1, self.n-1):
+            for left in StandardPermutations_avoiding_132(i):
+                for right in StandardPermutations_avoiding_132(self.n-i-1):
+                    yield Permutation_class( map(lambda x: x+(self.n-i-1), left) + [self.n] + list(right) )
+
+
+        #Yield all the 132 avoiding permutations to the left
+        for left in StandardPermutations_avoiding_132(self.n - 1):
+            yield Permutation_class(list(left) + [self.n])
+
+
+class StandardPermutations_avoiding_123(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: p = Permutations(3, avoiding=[1, 2, 3])
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(3, avoiding=[1, 2, 3]))
+            'Standard permutations of 3 avoiding [1, 2, 3]'
+        """
+        return "Standard permutations of %s avoiding [1, 2, 3]"%self.n
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: Permutations(5, avoiding=[1, 2, 3]).count()
+            42
+            sage: len( Permutations(5, avoiding=[1, 2, 3]).list() )
+            42
+        """
+        return catalan_number(self.n)
+    
+    def iterator(self):
+        """
+        EXAMPLES:
+            sage: Permutations(3, avoiding=[1, 2, 3]).list()
+             [[1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
+            sage: Permutations(2, avoiding=[1, 2, 3]).list()
+            [[1, 2], [2, 1]]
+            sage: Permutations(3, avoiding=[1, 2, 3]).list()
+            [[1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
+        """
+        if self.n == 0:
+            return
+        
+        elif self.n < 3:
+            for p in StandardPermutations_n(self.n):
+                yield p
+            return
+
+        elif self.n == 3:
+            for p in StandardPermutations_n(self.n):
+                if p != [1, 2, 3]:
+                    yield p
+            return 
+
+        
+        for p in StandardPermutations_avoiding_132(self.n):
+            #Convert p to a 123 avoiding permutation by
+            m = self.n+1
+            minima_pos = []
+            minima = []
+            for i in range(self.n):
+                if p[i] < m:
+                    minima_pos.append(i)
+                    minima.append(p[i])
+                    m = p[i]
+
+            
+            new_p = []
+            non_minima = filter(lambda x: x not in minima, range(self.n, 0, -1))
+            a = 0
+            b = 0
+            for i in range(self.n):
+                if i in minima_pos:
+                    new_p.append( minima[a] )
+                    a += 1
+                else:
+                    new_p.append( non_minima[b] )
+                    b += 1
+
+            yield Permutation_class( new_p )
+                
+
+class StandardPermutations_avoiding_321(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: p = Permutations(3, avoiding=[3, 2, 1])
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(3, avoiding=[3, 2, 1]))
+            'Standard permutations of 3 avoiding [3, 2, 1]'
+        """
+        return "Standard permutations of %s avoiding [3, 2, 1]"%self.n
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: Permutations(5, avoiding=[3, 2, 1]).count()
+            42
+            sage: len( Permutations(5, avoiding=[3, 2, 1]).list() )
+            42
+        """
+        return catalan_number(self.n)
+
+    def iterator(self):
+        for p in StandardPermutations_avoiding_123(self.n):
+            yield p.reverse()
+
+
+class StandardPermutations_avoiding_231(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: p = Permutations(3, avoiding=[2, 3, 1])
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(3, avoiding=[2, 3, 1]))
+            'Standard permutations of 3 avoiding [2, 3, 1]'
+        """
+        return "Standard permutations of %s avoiding [2, 3, 1]"%self.n
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: Permutations(5, avoiding=[2, 3, 1]).count()
+            42
+            sage: len( Permutations(5, avoiding=[2, 3, 1]).list() )
+            42
+        """
+        return catalan_number(self.n)
+
+    def iterator(self):
+        for p in StandardPermutations_avoiding_132(self.n):
+            yield p.reverse()
+
+
+class StandardPermutations_avoiding_312(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: p = Permutations(3, avoiding=[3, 1, 2])
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(3, avoiding=[3, 1, 2]))
+            'Standard permutations of 3 avoiding [3, 1, 2]'
+        """
+        return "Standard permutations of %s avoiding [3, 1, 2]"%self.n
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: Permutations(5, avoiding=[3, 1, 2]).count()
+            42
+            sage: len( Permutations(5, avoiding=[3, 1, 2]).list() )
+            42
+        """
+        return catalan_number(self.n)
+
+    def iterator(self):
+        for p in StandardPermutations_avoiding_132(self.n):
+            yield p.complement()
+
+
+class StandardPermutations_avoiding_213(CombinatorialClass):
+    def __init__(self, n):
+        """
+        TESTS:
+            sage: p = Permutations(3, avoiding=[2, 1, 3])
+            sage: p == loads(dumps(p))
+            True
+        """
+        self.n = n
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(Permutations(3, avoiding=[2, 1, 3]))
+            'Standard permutations of 3 avoiding [2, 1, 3]'
+        """
+        return "Standard permutations of %s avoiding [2, 1, 3]"%self.n
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: Permutations(5, avoiding=[2, 1, 3]).count()
+            42
+            sage: len( Permutations(5, avoiding=[2, 1, 3]).list() )
+            42
+        """
+        return catalan_number(self.n)
+
+    def iterator(self):
+        for p in StandardPermutations_avoiding_132(self.n):
+            yield p.complement().reverse()
+
+
+class StandardPermutations_avoiding_generic(CombinatorialClass):
+    def __init__(self, n, a):
+        self.n = n
+        self.a = a
+
+    def __repr__(self):
+        return "Standard permutations of %s avoiding %s"%(self.n, self.a)
+
+    def iterator(self):
+        for p in StandardPermutations_n(self.n):
+            ls = map(len, self.a)
+            found = False
+            for l in ls:
+                for pos in subword.Subwords(range(self.n),l):
+                    if to_standard(map(lambda z: p[z] , pos)) in self.a:
+                        found = True
+                        break
+                if found:
+                    break
+
+            if found:
+                continue
+            else:
+                yield p
+
+
+
+
+def Permutations(n=None,k=None, **kwargs):
+    """
+    Returns a combinatorial class of permutations.
+
+    EXAMPLES:
+
+        sage: p = Permutations(3); p
+        Standard permutations of 3
+        sage: p.list()
+        [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
+
+        sage: p = Permutations(3, 2); p
+        Permutations of {1,...,3} of length 2
+        sage: p.list()
+        [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
+
+        sage: p = Permutations(['c', 'a', 't']); p
+        Permutations of the (multi-)set ['c', 'a', 't']
+        sage: p.list()
+        [['c', 'a', 't'],
+         ['c', 't', 'a'],
+         ['a', 'c', 't'],
+         ['a', 't', 'c'],
+         ['t', 'c', 'a'],
+         ['t', 'a', 'c']]
+
+        sage: p = Permutations(['c', 'a', 't'], 2); p
+        Permutations of the (multi-)set ['c', 'a', 't'] of length 2
+        sage: p.list()
+        [['c', 'a'], ['c', 't'], ['a', 'c'], ['a', 't'], ['t', 'c'], ['t', 'a']]
+
+
+        sage: p = Permutations([1,1,2]); p
+        Permutations of the (multi-)set [1, 1, 2]
+        sage: p.list()
+        [[1, 1, 2], [1, 2, 1], [2, 1, 1]]
+
+
+        sage: p = Permutations([1,1,2], 2); p
+        Permutations of the (multi-)set [1, 1, 2] of length 2
+        sage: p.list()
+        [[1, 1], [1, 2], [2, 1]]
+
+        sage: p = Permutations(descents=[1,3]); p
+        Standard permutations of 4 with descents [1, 3]
+        sage: p.list()
+        [[1, 3, 2, 4], [1, 4, 2, 3], [2, 3, 1, 4], [2, 4, 1, 3], [3, 4, 1, 2]]
+
+        sage: p = Permutations(bruhat_smaller=[1,3,2,4]); p
+        Standard permutations that are less than or equal to [1, 3, 2, 4] in the Bruhat order
+        sage: p.list()
+        [[1, 2, 3, 4], [1, 3, 2, 4]]
+
+        sage: p = Permutations(bruhat_greater=[4,2,3,1]); p
+        Standard permutations that are greater than or equal to [4, 2, 3, 1] in the Bruhat order
+        sage: p.list()
+        [[4, 2, 3, 1], [4, 3, 2, 1]]
+
+        sage: p = Permutations(recoils_finer=[2,1]); p
+        Standard permutations whose recoils composition is finer than [2, 1]
+        sage: p.list()
+        [[1, 2, 3], [1, 3, 2], [3, 1, 2]]
+
+        sage: p = Permutations(recoils_fatter=[2,1]); p
+        Standard permutations whose recoils composition is fatter than [2, 1]
+        sage: p.list()
+        [[1, 3, 2], [3, 1, 2], [3, 2, 1]]
+
+        sage: p = Permutations(recoils=[2,1]); p
+        Standard permutations whose recoils composition is [2, 1]
+        sage: p.list()
+        [[1, 3, 2], [3, 1, 2]]
+
+        sage: p = Permutations(4, avoiding=[1,3,2]); p
+        Standard permutations of 4 avoiding [1, 3, 2]
+        sage: p.list()
+        [[4, 1, 3, 2],
+         [4, 2, 1, 3],
+         [4, 2, 3, 1],
+         [4, 3, 1, 2],
+         [4, 3, 2, 1],
+         [3, 4, 1, 2],
+         [3, 4, 2, 1],
+         [2, 3, 4, 1],
+         [3, 2, 4, 1],
+         [1, 3, 2, 4],
+         [2, 1, 3, 4],
+         [2, 3, 1, 4],
+         [3, 1, 2, 4],
+         [3, 2, 1, 4]]
+
+        sage: p = Permutations(5, avoiding=[[3,4,1,2], [4,2,3,1]]); p
+        Standard permutations of 5 avoiding [[3, 4, 1, 2], [4, 2, 3, 1]]
+        sage: p.count()
+        88
+        sage: p.random()
+        [1, 4, 2, 5, 3]
+
+    """
+
+    valid_args = ['descents', 'bruhat_smaller', 'bruhat_greater',
+                  'recoils_finer', 'recoils_fatter', 'recoils', 'avoiding']
+
+    number_of_arguments = 0
+    if n is not None:
+            number_of_arguments += 1
+    else:
+        if k is not None:
+            number_of_arguments += 1
+            
+
+    #Make sure that exactly one keyword was passed
+    for key in kwargs:
+        if key not in valid_args:
+            raise ValueError, "unknown keyword argument: %s"%key
+        if key not in [ 'avoiding' ]:
+            number_of_arguments += 1
+
+    if number_of_arguments == 0:
+        return StandardPermutations_all()
+    
+    if number_of_arguments != 1:
+        raise ValueError, "you must specify exactly one argument"     
+
+    if n is not None:
+        if isinstance(n, (int, Integer)):
+            if k is None:
+                if 'avoiding' in kwargs:
+                    a = kwargs['avoiding']
+                    if a in StandardPermutations_all():
+                        if a == [1,2]:
+                            return StandardPermutations_avoiding_12(n)
+                        elif a == [2,1]:
+                            return StandardPermutations_avoiding_21(n)
+                        elif a == [1,2,3]:
+                            return StandardPermutations_avoiding_123(n)
+                        elif a == [1,3,2]:
+                            return StandardPermutations_avoiding_132(n)
+                        elif a == [2,1,3]:
+                            return StandardPermutations_avoiding_213(n)
+                        elif a == [2,3,1]:
+                            return StandardPermutations_avoiding_231(n)
+                        elif a == [3,1,2]:
+                            return StandardPermutations_avoiding_312(n)
+                        elif a == [3,2,1]:
+                            return StandardPermutations_avoiding_321(n)
+                        else:
+                            return StandardPermutations_avoiding_generic(n, [a])
+                    elif isinstance(a, __builtin__.list):
+                        return StandardPermutations_avoiding_generic(n, a)
+                    else:
+                        raise ValueError, "do not know how to avoid %s"%a
+                else:
+                    return StandardPermutations_n(n)
+            else:
+                return Permutations_nk(n,k)
+        else:
+            if k is None:
+                return Permutations_mset(n)
+            else:
+                return Permutations_msetk(n,k)
+    elif 'descents' in kwargs:
+        if isinstance(kwargs['descents'], tuple):
+            return StandardPermutations_descents(*kwargs['descents'])
+        else:
+            return StandardPermutations_descents(kwargs['descents'], max(kwargs['descents'])+1)
+    elif 'bruhat_smaller' in kwargs:
+        return StandardPermutations_bruhat_smaller(Permutation(kwargs['bruhat_smaller']))
+    elif 'bruhat_greater' in kwargs:
+        return StandardPermutations_bruhat_greater(Permutation(kwargs['bruhat_greater']))
+    elif 'recoils_finer' in kwargs:
+        return StandardPermutations_recoilsfiner(kwargs['recoils_finer'])
+    elif 'recoils_fatter' in kwargs:
+        return StandardPermutations_recoilsfatter(kwargs['recoils_fatter'])
+    elif 'recoils' in kwargs:
+        return StandardPermutations_recoils(kwargs['recoils'])
Index: sage/combinat/permutation_nk.py
===================================================================
--- sage/combinat/permutation_nk.py	(revision 6439)
+++ sage/combinat/permutation_nk.py	(revision 6439)
@@ -0,0 +1,108 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from sage.rings.arith import factorial
+import random as rnd
+from sage.combinat.misc import DoublyLinkedList
+
+def count(n,k):
+    """
+    Returns the number of permutations of k things from a list
+    of n things.
+
+    EXAMPLES:
+        sage: permutation_nk.count(3,2)
+        6
+    """
+    return factorial(n)/factorial(n-k)
+
+def iterator(n,k):
+    """
+    An iterator for all permutations of k thinkgs from range(n).
+
+    EXAMPLES:
+        sage: [ p for p in permutation_nk.iterator(3,2)]
+        [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
+
+    """
+    if k == 0:
+        yield []
+        return
+
+    if k>n:
+        return
+
+
+    range_n = range(n)
+    available = range(n)
+    dll = DoublyLinkedList(range_n)
+
+    
+    L = range(k)
+    L[-1] = 'begin'
+    for i in range(k-1):
+        dll.hide(i)
+
+    finished = False
+    while not finished:    
+        L[-1] = dll.next_value[L[-1]]
+        if L[-1] != 'end':
+            yield L[:]
+            continue
+
+        finished = True
+        for i in reversed(range(k-1)):
+            value = L[i]
+            dll.unhide(value)
+            value = dll.next_value[value]
+            if value != 'end':
+                L[i] = value
+                dll.hide(value)
+                value = 'begin'
+                for j in reversed(range(i+1, k-1)):
+                    value = dll.next_value[value]
+                    L[j] = value
+                    dll.hide(value)
+                L[-1] = dll.next_value[value]
+                yield L[:]
+                finished = False
+                break
+
+    return 
+        
+def list(n,k):
+    """
+    Returns a list of all the permutation of k things from range(n).
+
+    EXAMPLES:
+        sage: permutation_nk.list(3,2)
+        [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
+
+    """
+
+    return [c for c in iterator(n,k)]
+
+def random(n,k):
+    """
+    Returns a random permutation of k things from range(n).
+
+    EXAMPLES:
+        sage: permutation_nk.random(3,2) #random
+        [2, 1]
+    """
+    rng = range(n)
+    r = rnd.sample(rng, k)
+        
+    return r
Index: sage/combinat/q_analogues.py
===================================================================
--- sage/combinat/q_analogues.py	(revision 6594)
+++ sage/combinat/q_analogues.py	(revision 6594)
@@ -0,0 +1,97 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from sage.misc.misc import prod
+from sage.rings.all import ZZ
+from dyck_word import DyckWords
+
+def q_int(n, p=None):
+    """
+    Returns the q-analogue of the integer n.
+
+    If p is unspecified, then it defaults to using
+    the generator q for a univariate polynomial
+    ring over the integers.
+    
+    EXAMPLES:
+        sage: q_analogues.q_int(3)
+        q^2 + q + 1
+        sage: p = ZZ['p'].0
+        sage: q_analogues.q_int(3,p)
+        p^2 + p + 1
+    """
+    if p == None:
+        p = ZZ['q'].gens()[0]
+        #pass
+    return sum([p**i for i in range(n)])
+
+def q_factorial(n, p=None):
+    """
+    Returns the q-analogue of the n!.
+
+    If p is unspecified, then it defaults to using
+    the generator q for a univariate polynomial
+    ring over the integers.
+
+    EXAMPLES:
+        sage: q_analogues.q_factorial(3)
+        q^3 + 2*q^2 + 2*q + 1
+        sage: p = ZZ['p'].0
+        sage: q_analogues.q_factorial(3, p)
+        p^3 + 2*p^2 + 2*p + 1
+    """
+    return prod([q_int(i,p) for i in range(1, n+1)])
+
+def q_binomial(n,k,p=None):
+    """
+    Returns the q-binomial coefficient.
+
+    If p is unspecified, then it defaults to using
+    the generator q for a univariate polynomial
+    ring over the integers.
+
+    EXAMPLES:
+        sage: q_analogues.q_binomial(4,2)
+        q^4 + q^3 + 2*q^2 + q + 1
+        sage: p = ZZ['p'].0
+        sage: q_analogues.q_binomial(4,2,p)
+        p^4 + p^3 + 2*p^2 + p + 1
+    """
+
+    return q_factorial(n,p)/(q_factorial(k,p)*q_factorial(n-k,p))
+
+
+def qt_catalan_number(n):
+    """
+    Returns the q,t-Catalan number.
+
+    EXAMPLES:
+        sage: q_analogues.qt_catalan_number(1)
+        1
+        sage: q_analogues.qt_catalan_number(2)
+        q + t
+        sage: q_analogues.qt_catalan_number(3)
+        q^3 + q^2*t + q*t^2 + t^3 + q*t
+        sage: q_analogues.qt_catalan_number(4)
+        q^6 + q^5*t + q^4*t^2 + q^3*t^3 + q^2*t^4 + q*t^5 + t^6 + q^4*t + q^3*t^2 + q^2*t^3 + q*t^4 + q^3*t + q^2*t^2 + q*t^3
+
+    """
+    ZZqt = ZZ['q','t']
+
+    d = {}
+    for dw in DyckWords(n):
+        tup = (dw.a_statistic(),dw.b_statistic())
+        d[tup] = d.get(tup,0)+1
+    return ZZqt(d)
Index: sage/combinat/ranker.py
===================================================================
--- sage/combinat/ranker.py	(revision 6439)
+++ sage/combinat/ranker.py	(revision 6439)
@@ -0,0 +1,89 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+def from_list(l):
+    """
+    Returns a ranker from the list l.
+
+    INPUT:
+        l -- a list
+
+    OUTPUT
+        [rank, unrank] -- functions
+
+    EXAMPLES:
+        sage: l = [1,2,3]
+        sage: r,u = sage.combinat.ranker.from_list(l)
+        sage: r(1)
+        0
+        sage: r(3)
+        2
+        sage: u(2)
+        3
+        sage: u(0)
+        1
+    """
+
+    n = len(l)
+    def unrank(j):
+        if j < 0 or j >= n:
+            raise ValueError, "Argument j ( = %s ) must be between 0 and %d"%(str(j), n)
+
+        return l[j]
+
+    def rank(obj):
+        return l.index(obj)
+
+    return [rank, unrank]
+
+
+def rank_from_list(l):
+    """
+    Returns a rank function given a list l.
+
+    EXAMPLES:
+        sage: l = [1,2,3]
+        sage: r = sage.combinat.ranker.rank_from_list(l)
+        sage: r(1)
+        0
+        sage: r(3)
+        2
+    """
+    def rank(obj):
+        return l.index(obj)
+
+    return rank
+
+
+def unrank_from_list(l):
+    """
+    Returns an unrank function from a list.
+
+    EXAMPLES:
+        sage: l = [1,2,3]
+        sage: u = sage.combinat.ranker.unrank_from_list(l)
+        sage: u(2)
+        3
+        sage: u(0)
+        1
+    """
+    n = len(l)
+    def unrank(j):
+        if j < 0 or j >= n:
+            raise ValueError, "Argument j ( = %s ) must be between 0 and %d"%(str(j), n)
+
+        return l[j]
+
+    return unrank
Index: sage/combinat/ribbon.py
===================================================================
--- sage/combinat/ribbon.py	(revision 6439)
+++ sage/combinat/ribbon.py	(revision 6439)
@@ -0,0 +1,328 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+import sage.combinat.misc as misc
+import sage.combinat.skew_tableau
+import sage.combinat.word as word
+import sage.combinat.permutation as permutation
+from combinat import CombinatorialClass, CombinatorialObject
+
+def Ribbon(r):
+    """
+    Returns a ribbon tableau object.
+
+    EXAMPLES:
+        sage: Ribbon([[2,3],[1,4,5]])
+        [[2, 3], [1, 4, 5]]
+    """
+    return Ribbon_class(r)
+        
+class Ribbon_class(CombinatorialObject):
+    def ribbon_shape(self):
+        """
+        Returns the ribbon shape.  The ribbon shape is given
+        just by the number of boxes in each row.
+
+        EXAMPLES:
+            sage: Ribbon([[2,3],[1,4,5]]).ribbon_shape()
+            [2, 3]
+        """
+
+        return [len(row) for row in self]
+
+    def height(self):
+        """
+        Returns the height of the ribbon.
+
+        EXAMPLES:
+            sage: Ribbon([[2,3],[1,4,5]]).height()
+            2
+        """
+        return len(self)
+
+    def width(self):
+        """
+        Returns the width of the ribbon.
+
+        EXAMPLES:
+            sage: Ribbon([[2,3],[1,4,5]]).width()
+            4
+        """
+        return 1+sum([len(r)-1 for r in self])
+
+    def size(self):
+        """
+        Returns the size ( number of boxes ) in the ribbon.
+
+        EXAMPLES:
+            sage: Ribbon([[2,3],[1,4,5]]).size()
+            5
+        """
+        return sum([len(r) for r in self])
+
+    def is_standard(self):
+        """
+        Returns True is the ribbon is standard and False otherwise.
+        ribbon are standard if they are filled with the numbers
+        1...size and they are increasing along both rows and columns.
+
+        EXAMPLES:
+            sage: Ribbon([[2,3],[1,4,5]]).is_standard()
+            True
+            sage: Ribbon([[2,2],[1,4,5]]).is_standard()
+            False
+            sage: Ribbon([[4,5],[1,2,3]]).is_standard()
+            False
+        """
+
+        return self.to_skew_tableau().is_standard()
+
+    def to_skew_tableau(self):
+        """
+        Returns the skew tableau corresponding to the ribbon
+        tableau.
+
+        EXAMPLES:
+            sage: Ribbon([[2,3],[1,4,5]]).to_skew_tableau()
+            [[None, None, 2, 3], [1, 4, 5]]
+        """
+        st = []
+        space_count = 0
+        for row in reversed(self):
+            st.append( [None]*space_count + row )
+            space_count += len(row) - 1
+        st.reverse()
+        return sage.combinat.skew_tableau.SkewTableau(st)
+
+    def to_permutation(self):
+        """
+        Returns the permutation corresponding to the ribbon
+        tableau.
+
+        EXAMPLES:
+            sage: r = Ribbon([[1], [2,3], [4, 5, 6]])
+            sage: r.to_permutation()
+            [1, 2, 3, 4, 5, 6]
+        """
+        return permutation.Permutation(self.to_word())
+    
+    def shape(self):
+        """
+        Returns the skew partition corresponding to the shape of the
+        ribbon.
+
+        EXAMPLES:
+            sage: Ribbon([[2,3],[1,4,5]]).shape()
+            [[4, 3], [2]]
+        """
+        return self.to_skew_tableau().shape()
+
+    def to_word_by_row(self):
+        """
+        Returns a word obtained from a row reading of the ribbon.
+
+        EXAMPLES:
+            sage: Ribbon([[1],[2,3]]).to_word_by_row()
+            [1, 2, 3]
+            sage: Ribbon([[2, 4], [3], [1]]).to_word_by_row()
+            [2, 4, 3, 1]
+        """
+        word = []
+        for row in self:
+            word += row
+
+        return word
+
+
+    def to_word_by_column(self):
+        """
+        Returns the word obtained from a column reading of the ribbon
+
+        EXAMPLES:
+            sage: Ribbon([[1],[2,3]]).to_word_by_column()
+            [2, 1, 3]
+            sage: Ribbon([[2, 4], [3], [1]]).to_word_by_column()
+            [2, 3, 1, 4]      
+
+        """
+        return self.to_skew_tableau().to_word_by_column()
+
+    def to_word(self):
+        """
+        An alias for Ribbon.to_word_by_row().
+
+        EXAMPLES:
+            sage: Ribbon([[1],[2,3]]).to_word_by_row()
+            [1, 2, 3]
+            sage: Ribbon([[2, 4], [3], [1]]).to_word_by_row()
+            [2, 4, 3, 1]
+        """
+        return self.to_word_by_row()
+
+    def evaluation(self):
+        """
+        Returns the evaluation of the word from ribbon.
+
+        EXAMPLES:
+            sage: Ribbon([[1,2],[3,4]]).evaluation()
+            [1, 1, 1, 1]
+        """
+
+        return word.evaluation(self.to_word())
+
+    
+
+def from_shape_and_word(shape, word):
+    """
+    Returns the ribbon corresponding to the given
+    ribbon shape and word.
+
+    EXAMPLES:
+        sage: ribbon.from_shape_and_word([2,3],[1,2,3,4,5])
+        [[1, 2], [3, 4, 5]]
+    """
+    pos = 0
+    r = []
+    for l in shape:
+        r.append(word[pos:pos+l])
+        pos += l
+    return Ribbon(r)
+
+def StandardRibbonTableaux(shape):
+    """
+    Returns the combinatorial class of standard ribbon
+    tableaux of shape shape.
+
+    EXAMPLES:
+        sage: StandardRibbonTableaux([2,2])
+        Standard ribbon tableaux of shape [2, 2]
+        sage: StandardRibbonTableaux([2,2]).first()
+        [[1, 3], [2, 4]]
+        sage: StandardRibbonTableaux([2,2]).last()
+        [[3, 4], [1, 2]]
+        sage: StandardRibbonTableaux([2,2]).count()
+        5
+        sage: StandardRibbonTableaux([2,2]).list()
+        [[[1, 3], [2, 4]],
+         [[1, 4], [2, 3]],
+         [[2, 3], [1, 4]],
+         [[2, 4], [1, 3]],
+         [[3, 4], [1, 2]]]
+
+        sage: StandardRibbonTableaux([2,2]).list()
+        [[[1, 3], [2, 4]],
+         [[1, 4], [2, 3]],
+         [[2, 3], [1, 4]],
+         [[2, 4], [1, 3]],
+         [[3, 4], [1, 2]]]    
+        sage: StandardRibbonTableaux([3,2,2]).count()
+        155
+
+    """
+    return StandardRibbonTableaux_shape(shape)
+
+class StandardRibbonTableaux_shape(CombinatorialClass):
+    def __init__(self, shape):
+        """
+        TESTS:
+            sage: S = StandardRibbonTableaux([2,2])
+            sage: S == loads(dumps(S))
+            True
+        """
+        self.shape = shape
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(StandardRibbonTableaux([2,2]))
+            'Standard ribbon tableaux of shape [2, 2]'
+        """
+        return "Standard ribbon tableaux of shape %s"%self.shape
+
+
+    def first(self):
+        """
+        Returns the first standard ribbon of
+        ribbon shape shape.
+
+        EXAMPLES:
+            sage: StandardRibbonTableaux([2,2]).first()
+            [[1, 3], [2, 4]]
+
+        """
+        return from_permutation(permutation.descents_composition_first(self.shape))
+
+    def last(self):
+        """
+        Returns the first standard ribbon of
+        ribbon shape shape.
+
+        EXAMPLES:
+            sage: StandardRibbonTableaux([2,2]).last()
+            [[3, 4], [1, 2]]
+        """
+        return from_permutation(permutation.descents_composition_last(self.shape))
+
+
+    def iterator(self):
+        """
+        An iterator for the standard ribbon of ribbon
+        shape shape.
+
+        EXAMPLES:
+            sage: [t for t in StandardRibbonTableaux([2,2])]
+            [[[1, 3], [2, 4]],
+             [[1, 4], [2, 3]],
+             [[2, 3], [1, 4]],
+             [[2, 4], [1, 3]],
+             [[3, 4], [1, 2]]]    
+        """
+
+        for p in permutation.descents_composition_list(self.shape):
+            yield from_permutation(p)
+
+def from_permutation(p):
+    """
+    Returns a standard ribbon of size len(p) from a Permutation p.
+    The lengths of each row are given by the distance between the descents
+    of the permutation p.
+    
+    EXAMPLES:
+        sage: [ribbon.from_permutation(p) for p in Permutations(3)]
+        [[[1, 2, 3]],
+         [[1, 3], [2]],
+         [[2], [1, 3]],
+         [[2, 3], [1]],
+         [[3], [1, 2]],
+         [[3], [2], [1]]]
+
+    """
+    if p == []:
+        return Ribbon([])
+    
+    comp = p.descents()
+
+    if comp == []:
+        return Ribbon([p[:]])
+
+    
+    #[p[j]$j=compo[i]+1..compo[i+1]] $i=1..nops(compo)-1, [p[j]$j=compo[nops(compo)]+1..nops(p)]
+    r = [] 
+    r.append([p[j] for j in range(comp[0]+1)])
+    for i in range(len(comp)-1):
+        r.append([ p[j] for j in range(comp[i]+1,comp[i+1]+1) ])
+    r.append( [ p[j] for j in range(comp[-1]+1, len(p))] )
+
+    return Ribbon(r)
Index: sage/combinat/schubert_polynomial.py
===================================================================
--- sage/combinat/schubert_polynomial.py	(revision 6439)
+++ sage/combinat/schubert_polynomial.py	(revision 6439)
@@ -0,0 +1,141 @@
+
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from combinatorial_algebra import CombinatorialAlgebra, CombinatorialAlgebraElement
+from sage.rings.integer import Integer
+import permutation
+import sage.libs.symmetrica.all as symmetrica
+
+def SchubertPolynomialRing(R):
+    """
+    Returns the Schubert polynomial ring over R on the X basis.
+
+    EXAMPLES:
+        sage: X = SchubertPolynomialRing(ZZ); X
+        Schubert polynomial ring with X basis over Integer Ring
+        sage: X(1)
+        X[1]
+        sage: X([1,2,3])*X([2,1,3])
+        X[2, 1, 3]
+        sage: X([2,1,3])*X([2,1,3])
+        X[3, 1, 2]
+        sage: X([2,1,3])+X([3,1,2,4])
+        X[2, 1, 3] + X[3, 1, 2, 4]
+        sage: a = X([2,1,3])+X([3,1,2,4])
+        sage: a^2
+        X[3, 1, 2] + X[5, 1, 2, 3, 4] + 2*X[4, 1, 2, 3]
+    """
+    return SchubertPolynomialRing_xbasis(R)
+
+def is_SchubertPolynomial(x):
+    """
+    Returns True if x is a Schubert polynomial and False otherwise.
+    
+    EXAMPLES:
+        sage: X = SchubertPolynomialRing(ZZ)
+        sage: a = 1
+        sage: is_SchubertPolynomial(a)
+        False
+        sage: b = X(1)
+        sage: is_SchubertPolynomial(b)
+        True
+        sage: c = X([2,1,3])
+        sage: is_SchubertPolynomial(c)
+        True
+    """
+    return isinstance(x, SchubertPolynomial_class)
+
+class SchubertPolynomial_class(CombinatorialAlgebraElement):
+    def expand(self):
+        """
+        EXAMPLES:
+            sage: X = SchubertPolynomialRing(ZZ)
+            sage: X([2,1,3]).expand()
+            x0
+            sage: map(lambda x: x.expand(), [X(p) for p in Permutations(3)])
+            [1, x0 + x1, x0, x0*x1, x0^2, x0^2*x1]
+        """
+        return symmetrica.t_SCHUBERT_POLYNOM(self)
+
+    def divided_difference(self, i):
+        if isinstance(i, Integer):
+            return symmetrica.divdiff_schubert(i, self)
+        elif i in permutation.Permutations():
+            return symmetrica.divdiff_perm_schubert(i, self)
+        else:
+            raise TypeError, "i must either be an integer or permutation"
+
+    def scalar_product(self, x):
+        """
+        Returns the standard scalar product of self and x.
+
+        EXAMPLES:
+            sage: X = SchubertPolynomialRing(ZZ)
+            sage: a = X([3,2,4,1])
+            sage: a.scalar_product(a)
+            0
+            sage: b = X([4,3,2,1])
+            sage: b.scalar_product(a)
+            X[1, 3, 4, 6, 2, 5, 7]
+            sage: Permutation([1, 3, 4, 6, 2, 5, 7]).to_lehmer_code()
+            [0, 1, 1, 2, 0, 0, 0]
+            sage: s = SFASchur(ZZ)
+            sage: c = s([2,1,1])
+            sage: b.scalar_product(a).expand()
+            x0^2*x1*x2 + x0*x1^2*x2 + x0*x1*x2^2 + x0^2*x1*x3 + x0*x1^2*x3 + x0^2*x2*x3 + 3*x0*x1*x2*x3 + x1^2*x2*x3 + x0*x2^2*x3 + x1*x2^2*x3 + x0*x1*x3^2 + x0*x2*x3^2 + x1*x2*x3^2
+            sage: c.expand(4)
+            x0^2*x1*x2 + x0*x1^2*x2 + x0*x1*x2^2 + x0^2*x1*x3 + x0*x1^2*x3 + x0^2*x2*x3 + 3*x0*x1*x2*x3 + x1^2*x2*x3 + x0*x2^2*x3 + x1*x2^2*x3 + x0*x1*x3^2 + x0*x2*x3^2 + x1*x2*x3^2
+
+        """
+        if is_SchubertPolynomial(x):
+            return symmetrica.scalarproduct_schubert(self, x)
+        else:
+            raise TypeError, "x must be a Schubert polynomial"
+
+    def multiply_variable(self, i):
+        """
+        Returns the Schubert polynomial obtained by multiplying self by
+        the variable x_i.
+
+        EXAMPLES:
+            sage: X = SchubertPolynomialRing(ZZ)
+            sage: a = X([3,2,4,1])
+            sage: a.multiply_variable(0)
+            X[4, 2, 3, 1, 5]
+            sage: a.multiply_variable(1)
+            X[3, 4, 2, 1, 5]
+            sage: a.multiply_variable(2)
+            -X[3, 4, 2, 1, 5] - X[4, 2, 3, 1, 5] + X[3, 2, 5, 1, 4]
+            sage: a.multiply_variable(3)
+            X[3, 2, 4, 5, 1]
+
+        """
+        if isinstance(i, Integer):
+            return symmetrica.mult_schubert_variable(self, i)
+        else:
+            raise TypeError, "i must be an integer"
+        
+
+
+class SchubertPolynomialRing_xbasis(CombinatorialAlgebra):
+    _name = "Schubert polynomial ring with X basis"
+    _prefix = "X"
+    _combinatorial_class = permutation.Permutations()
+    _one = permutation.Permutation([1])
+    _element_class = SchubertPolynomial_class
+    
+    def _multiply_basis(self, left, right):
+        return symmetrica.mult_schubert_schubert(left, right).monomial_coefficients()
Index: sage/combinat/set_partition.py
===================================================================
--- sage/combinat/set_partition.py	(revision 6594)
+++ sage/combinat/set_partition.py	(revision 6594)
@@ -0,0 +1,389 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from sage.sets.set import Set, EnumeratedSet, is_Set
+import sage.combinat.partition as partition
+import sage.rings.integer
+import __builtin__
+import itertools
+from cartesian_product import CartesianProduct
+import sage.combinat.subset as subset
+import sage.combinat.set_partition_ordered as set_partition_ordered
+import copy
+from combinat import CombinatorialClass, CombinatorialObject, bell_number, stirling_number2
+from subword import Subwords
+
+
+def SetPartitions(s, part=None):
+    """
+    An {\it unordered partition} of a set $S$ is a set of pairwise disjoint 
+    nonempty subsets with union $S$ and is represented by a sorted 
+    list of such subsets.
+
+    partitions_set returns the set of all unordered partitions of the 
+    list $S$ of increasing positive integers into k pairwise disjoint 
+    nonempty sets. If k is omitted then all partitions are returned.
+
+    The Bell number $B_n$, named in honor of Eric Temple Bell, is 
+    the number of different partitions of a set with n elements. 
+
+    EXAMPLES:
+        sage: S = [1,2,3,4]
+        sage: SetPartitions(S,2)
+        Set partitions of [1, 2, 3, 4] with 2 parts
+
+         
+    REFERENCES:
+       http://en.wikipedia.org/wiki/Partition_of_a_set
+
+    """
+    if isinstance(s, (int, sage.rings.integer.Integer)):
+        set = range(1, s+1)
+    elif isinstance(s, str):
+        set = [x for x in s]
+    else:
+        set = s
+    
+    if part is not None:
+        if isinstance(part, (int, sage.rings.integer.Integer)):
+            if len(set) < part:
+                raise ValueError, "part must be <= len(set)"
+            else:
+                return SetPartitions_setn(set,part)
+        else:
+            if part not in partition.Partitions(len(set)):
+                raise ValueError, "part must be a partition of %s"%len(set)
+            else:
+                return SetPartitions_setparts(set, [partition.Partition(part)])
+    else:
+        return SetPartitions_set(set)
+
+
+
+class SetPartitions_setparts(CombinatorialClass):
+    def __init__(self, set, parts):
+        """
+        TESTS:
+            sage: S = SetPartitions(4, [2,2])
+            sage: S == loads(dumps(S))
+            True
+        """
+        self.set = set
+        self.parts = parts
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitions(4, [2,2]))
+            'Set partitions of [1, 2, 3, 4] with sizes in [[2, 2]]'
+        """
+        return "Set partitions of %s with sizes in %s"%(self.set, self.parts)
+
+    def __contains__(self, x):
+        """
+        TESTS:
+            sage: S = SetPartitions(4, [2,2])
+            sage: all([sp in S for sp in S])
+            True            
+        """
+        #x must be a set
+        if not is_Set(x):
+            return False
+
+        #Make sure that the number of elements match up
+        if sum(map(len, x)) != len(self.set):
+            return False
+
+        #Check to make sure each element of x
+        #is a set
+        u = Set([])
+        for s in x:
+            if not is_Set(s):
+                return False
+            u = u.union(s)
+
+        #Make sure that the union of all the
+        #sets is the original set
+        if u != Set(self.set):
+            return False
+
+        return True
+
+    def count(self):
+        """
+        Returns the number of set partitions of set.  This
+        number is given by the n-th Bell number where n is
+        the number of elements in the set.
+
+        If a partition or partition length is specified, then
+        count will generate all of the set partitions.
+
+        EXAMPLES:
+            sage: SetPartitions([1,2,3,4]).count()
+            15
+            sage: SetPartitions(3).count()
+            5
+            sage: SetPartitions(3,2).count()
+            3
+            sage: SetPartitions([]).count()
+            1
+        """
+        return len(self.list())
+
+
+    def __iterator_part(self, part):
+        set = self.set
+
+        nonzero = []
+        p = partition.Partition(part)
+        expo = p.to_exp()
+
+        for i in range(len(expo)):
+            if expo[i] != 0:
+                nonzero.append([i, expo[i]])
+
+        taillesblocs = map(lambda x: (x[0])*(x[1]), nonzero)
+
+        blocs = set_partition_ordered.OrderedSetPartitions(copy.copy(set), taillesblocs).list()
+
+        for b in blocs:
+            lb = [ _listbloc(nonzero[i][0], nonzero[i][1], b[i]) for i in range(len(nonzero)) ]
+            for x in itertools.imap(lambda x: _union(x), CartesianProduct( *lb )):
+                yield x
+
+
+    
+    def iterator(self):
+        """
+        An iterator for all the set partitions of the set.
+
+        EXAMPLES:
+            sage: SetPartitions(3).list()
+            [{{1, 2, 3}}, {{2, 3}, {1}}, {{1, 3}, {2}}, {{1, 2}, {3}}, {{2}, {3}, {1}}]
+        """
+        for p in self.parts:
+            for sp in self.__iterator_part(p):
+                yield sp
+
+
+class SetPartitions_setn(SetPartitions_setparts):
+    def __init__(self, set, n):
+        """
+        TESTS:
+            sage: S = SetPartitions(5, 3)
+            sage: S == loads(dumps(S))
+            True
+        """
+        self.n = n
+        SetPartitions_setparts.__init__(self, set, partition.Partitions(len(set), length=n).list())
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr(SetPartitions(5, 3))
+            'Set partitions of [1, 2, 3, 4, 5] with 3 parts'
+        """
+        return "Set partitions of %s with %s parts"%(self.set,self.n)
+
+    def count(self):
+        """
+        The Stirling number of the second kind is the number
+        of partitions of a set of size n into k blocks.
+
+        EXAMPLES:
+            sage: SetPartitions(5, 3).count()
+            25
+            sage: stirling_number2(5,3)
+            25
+        """
+        return stirling_number2(len(self.set), self.n)
+    
+class SetPartitions_set(SetPartitions_setparts):
+    def __init__(self, set):
+        """
+        TESTS:
+            sage: S = SetPartitions([1,2,3])
+            sage: S == loads(dumps(S))
+            True
+        """
+        SetPartitions_setparts.__init__(self, set, partition.Partitions(len(set)))
+
+    def __repr__(self):
+        """
+        TESTS:
+            sage: repr( SetPartitions([1,2,3]) )
+            'Set partitions of [1, 2, 3]'
+        """
+        return "Set partitions of %s"%(self.set)
+
+    def count(self):
+        """
+        EXAMPLES:
+            sage: SetPartitions(4).count()
+            15
+            sage: bell_number(4)
+            15
+        """
+        return bell_number(len(self.set))
+
+
+
+def _listbloc(n, nbrepets, listint=None):
+    """
+    listbloc decomposes a set of n*nbrepets integers (the list listint)
+    in nbrepets parts.
+
+    It is used in the algorithm to generate all set partitions.
+
+    Not to be called by the user.
+
+    EXAMPLES:
+        sage: sage.combinat.set_partition._listbloc(2,1)
+        [{{1, 2}}]
+        sage: l = [Set([Set([3, 4]), Set([1, 2])]), Set([Set([2, 4]), Set([1, 3])]), Set([Set([2, 3]), Set([1, 4])])]
+        sage: sage.combinat.set_partition._listbloc(2,2,[1,2,3,4]) == l
+        True
+
+
+    """
+    if isinstance(listint, (int, sage.rings.integer.Integer)) or listint is None:
+        listint = Set(range(1,n+1))
+
+
+    if nbrepets == 1:
+        return [Set([listint])]
+    
+    l = __builtin__.list(listint)
+    l.sort()
+    smallest = Set(l[:1])
+    new_listint = Set(l[1:])
+    
+    f = lambda u, v: u.union(_set_union([smallest,v]))
+    res = []
+    
+    for ssens in subset.Subsets(new_listint, n-1):
+        for z in _listbloc(n, nbrepets-1, new_listint-ssens):
+            res.append(f(z,ssens))
+
+    return res
+
+def _union(s):
+    """
+    TESTS:
+        sage: s = Set([ Set([1,2]), Set([3,4]) ])
+        sage: sage.combinat.set_partition._union(s)
+        {1, 2, 3, 4}
+    """
+    result = Set([])
+    for ss in s:
+        result = result.union(ss)
+    return result
+
+def _set_union(s):
+    """
+    TESTS:
+        sage: s = Set([ Set([1,2]), Set([3,4]) ])
+        sage: sage.combinat.set_partition._set_union(s)
+        {{1, 2, 3, 4}}
+    """
+    result = Set([])
+    for ss in s:
+        result = result.union(ss)
+    return EnumeratedSet([result])
+
+def inf(s,t):
+    """
+    Returns the infimum of the two set partitions s and t.
+
+    EXAMPLES:
+        sage: sp1 = Set([Set([2,3,4]),Set([1])])
+        sage: sp2 = Set([Set([1,3]), Set([2,4])])
+        sage: s = Set([ Set([2,4]), Set([3]), Set([1])]) #{{2, 4}, {3}, {1}}
+        sage: sage.combinat.set_partition.inf(sp1, sp2) == s
+        True
+
+    """
+    temp = [ss.intersection(ts) for ss in s for ts in t]
+    temp = filter(lambda x: x != Set([]), temp)
+    return EnumeratedSet(temp)
+
+def sup(s,t):
+    """
+    Returns the supremum of the two set partitions s and t.
+
+    EXAMPLES:
+        sage: sp1 = Set([Set([2,3,4]),Set([1])])
+        sage: sp2 = Set([Set([1,3]), Set([2,4])])
+        sage: s = Set([ Set([1,2,3,4]) ])
+        sage: sage.combinat.set_partition.sup(sp1, sp2) == s
+        True
+
+    """
+    res = s
+    for p in t:
+        inters = Set(filter(lambda x: x.intersection(p) != Set([]), __builtin__.list(res)))
+        res = res.difference(inters).union(_set_union(inters))
+
+    return res
+
+   
+def standard_form(sp):
+    """
+    Returns the set partition as a list of lists.
+
+    EXAMPLES:
+        sage: map(sage.combinat.set_partition.standard_form, SetPartitions(4, [2,2]))
+        [[[3, 4], [1, 2]], [[2, 4], [1, 3]], [[2, 3], [1, 4]]]
+    """
+
+    return [__builtin__.list(x) for x in sp]
+
+
+def less(s, t):
+    """
+    Returns True if s < t otherwise it returns False.
+
+    EXAMPLES:
+        sage: z = SetPartitions(3).list()
+        sage: sage.combinat.set_partition.less(z[0], z[1])
+        False
+        sage: sage.combinat.set_partition.less(z[4], z[1])
+        True
+        sage: sage.combinat.set_partition.less(z[4], z[0])
+        True
+        sage: sage.combinat.set_partition.less(z[3], z[0])
+        True
+        sage: sage.combinat.set_partition.less(z[2], z[0])
+        True
+        sage: sage.combinat.set_partition.less(z[1], z[0])
+        True
+        sage: sage.combinat.set_partition.less(z[0], z[0])
+        False
+    """
+
+    if _union(s) != _union(t):
+        raise ValueError, "cannont compare partitions of different sets"
+
+    if s == t:
+        return False
+
+    for p in s:
+        f = lambda z: z.intersection(p) != Set([])
+        if len(filter(f, __builtin__.list(t)) ) != 1:
+            return False
+
+    return True
+        
+
Index: sage/combinat/set_partition_ordered.py
===================================================================
--- sage/combinat/set_partition_ordered.py	(revision 6439)
+++ sage/combinat/set_partition_ordered.py	(revision 6439)
@@ -0,0 +1,346 @@
+#*****************************************************************************
+#       Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, 
+#
+#  Distributed under the terms of the GNU General Public License (GPL)
+#
+#    This code is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#    General Public License for more details.
+#
+#  The full text of the GPL is available at:
+#
+#                  http://www.gnu.org/licenses/
+#*****************************************************************************
+
+from sage.rings.arith import factorial, binomial
+import itertools
+import __builtin__
+import sage.combinat.composition as composition
+import sage.combinat.word as word
+import sage.combinat.permutation as permutation
+import sage.rings.integer
+from sage.combinat.combinat import stirling_number2
+from sage.sets.set import Set, is_Set
+from combinat import CombinatorialClass, CombinatorialObject
+from sage.misc.misc import prod
+
+
+def OrderedSetPartitions(s, c=None):
+    """
+    Returns the combinatorial class of ordered set partitions
+    of s.
+
+    EXAMPLES:
+        sage: OS = OrderedSetPartitions([1,2,3,4]); OS
+        Ordered set partitions of {1, 2, 3, 4}
+        sage: OS.count()
+        75
+        sage: OS.first()
+        [{1}, {2}, {3}, {4}]
+        sage: OS.last()
+        [{1, 2, 3, 4}]
+        sage: OS.random() #random
+        [{1}, {3}, {2, 4}]
+
+        sage: OS = OrderedSetPartitions([1,2,3,4], [2,2]); OS
+        Ordered set partitions of {1, 2, 3, 4} into parts of size [2, 2]
+        sage: OS.count()
+        6
+        sage: OS.first()
+        [{1, 2}, {3, 4}]
+        sage: OS.last()
+        [{3, 4}, {1, 2}]
+        sage: OS.list()
+        [[{1, 2}, {3, 4}],
+         [{1, 3}, {2, 4}],
+         [{1, 4}, {2, 3}],
+         [{