HECKE PROJECT
TO DO LIST 
----------

[ ] Add feature for changing the real precision. 

[ ] Motive Calculator: ?? shouldn't reset the "." command!

[ ] w1,w2 normalization seems a bit nondeterministic, e.g.,
    when computing invariants for 9k4a.

[ ] 



[ ] CyclicModule -- apply standard "saving algorithm".  The integral
    CyclicModule can simply overwrite after computing the basis once!
    Check dimension to know if reduced. 

[X] It is possible to compute any T_n using HeilbronnC, as proved
   in Merel.

[ ] ordering of factors in factorization in nondeterministic.
    this is very annoying to user!

[ ] level 100, weight 4, eisenstein, then compute T_p says,
    TpResTo: asked to compute on space of invalid dimension.


[ ] aplist_g1 sorts incorrectly. e.g., level 7.

[ ]  HECKE>  M

Define a space M_k(N,chi;K) of modular symbols.
[EXPERT MODE]
characteristic of K = 5
Work in plus space M_k/<I>?  [y]  y
level N = 900
(900 = 2^2*3^2*5^2)
character chi = 2 3 5
Loading 2_3_5_Chi
weight k = 3
Initializing 30-th cyclotomic field/F_5.
5 is ramified in Q(zeta_30)
so in characteristic 5 there is no primitive 30-th root of unity
Initializing F=F_{5}[x]/f(x), f(x)=x^2 + 2 mod 5

Loading Manin symbols list (size=4320, name = 2_3_5_MSymbols_3):
	0% 6% 13% 20% 26% 33% 40% 46% 53% 60% 66% 73% 80% 86% 93% 
*****************************************************
Initializing M_3(Gamma_0(900=2^2*3^2*5^2), eps=[2 3 5])^+
*****************************************************
Making binomial table. Done.
Now computing M_k = (Manin Symbols) / (S, T, and I Relations).
Step 1: mod out by S and I relations.It is impossible to cast zeta_30^  to a 20
ffield_element for the default finite field
[was@yomomma debug]$ 

[ ] Compute Gamma_1(N) recurrence correctly.

[ ] Way to automatically specify kronecker symbol.

[ ]
HECKE>  M

Define a space M_k(N,chi;K) of modular symbols.
[EXPERT MODE]
characteristic of K = 5
Work in plus space M_k/<I>?  [y]  y
level N = 2000
(2000 = 2^4*5^3)
character chi = 0
Loading 0_Chi
weight k = 4
Initializing (charmod) F_5
Aborted (core dumped)


[ ] Make it so that individual spaces have their filename prepended with
    the name of the space in which they live, to help avoid problems.

[ ] finish mesg, in particular, allow for file 

[ ] In algorithm to compute Vdual, perhaps it would save
    time to avoid primes dividing the level, as they tend
    to not be of much use. 

[ ] Date: Mon, 9 Nov 1998 18:17:09 +0000 (GMT)
From: Kevin Buzzard <buzzard@ic.ac.uk>
To: was@math.berkeley.edu
Subject: *doh*

I forgot to say the stupid comment! I think that I can "trick" hecke
into saying something stupid. If I use g and then use g again, I can
cut down V to quite a small space maybe, but the "s" command only
says that V is ker(f(Tn)) for the last polynomial f you typed in.
I think.

Your programs rock. Don't forget you have to write a thesis! But
your programs rock regardless.                                             

You're right -- I remember programming it that way, but not thinking
much about why.   So what should V be called?

Another thing which would be useful would be able to go back up after
cutting down to a smaller eigenspace.

Maybe V should be replaced by a chain of subspaces, and then the user
moves up and down.  The "s" command then gives a nicely indented list
showing the subspaces in the chain:

Ambient space: M_2(Gamma_0(512=2^9); Q)

  1:  M_2, dim 66
  2:    S_2, dim 49
  3:      S_2^{new}, dim 16
  4:        ker(T_3^2-2), dim 8
  5:          ker(T_5-2), dim 2  <-------- current space

Then typing a number allows one to move up to any of the previous
spaces, without recomputing it.  I think maybe all lower spaces would
then be freed from memory because it might be too complicated keeping
track of many spaces "both above and below you".  It's mainly
complicated because of the constraint of not using a graphical user
interface, which is something I will definitely not use for this
project.                                                                    

[ ] Minimal integral basis. 
       
[ ] Interupt computations as they are going.

[ ] Annoying input format:
      =========================================================
        M_2 (20, chi(20/20_2_4); Q[x]/(x^2 + 1) )
        dim(M_2) = 3
        V = S_2,    dim(V) = 1
        ....................................................
                           [ ] Matrix         [X] Charpoly
        v = change V       m = toggle matrix  c = toggle charpoly
        t = compute Tn     a = atkin-lehner   e = eigenspaces
        ===================================== x = exit ==========
-------> ? e
What to call common eigenspace: b
Now enter a list of prime, eigenvalue pairs terminated by q:
? 3 0 q

 error_handler::base_vector::read :: [ expected
Aborted
[was@cusp hecke]$ hecke 

s
charpoly(T)=T^3 + (-3*x+3)*T^2 + + (8*x+8)
n =                                                 
                              


==================== EFFICIENCY ============================
[ ] Factoring polynomials / algnum is much too slow.

[ ] It is embarassing and annoying that the modformulas.cc 
    code runs *much* more slowly than the equivalent PARI code!

[ ] Impliment Lenstra's suggestion to compute L(f,s)==0 more quickly.

[ ] In atkin-lehner map, the MSym::x() function is used in an inefficient
    manner by the Hecke operators part of h1nchi.  A given M-symbol (c,d) 
    is lifted to (a,b;c',d') once for each matrix in the sum.  

[ ] Optimize action of certain matrices on M-symbols when the
    weight is high.  For example, it is completely uneccessary
    to multiply everything out when computing the action of 
    (-1,0;0,1) on 


================== P-ADIC ====================

[ ] Integrate Hecke series into main program. 
      1) create a padichecke class which will contain all kinds of
         algorithms for computing hecke series type things. 

================== DEFFICIENCIES ============

[ ] Determine why the Atkin-Lehner maps, as programmed,
    don't work for Gamma_1(N).
    (Note: feature currently disabled.)
       Notes: 
	It does *NOT* work for S_2(Gamma_1(20)).
    ---> LOW PRIORITY, as I'll probably never use this, anyway. 

================== KNOWN BUGS ==============

[ ] N=900, chi=[2,3,5], dim S_3 = 356, but with h1nchi over F_97 the 
    dimn is reported as 0.  The program works correctly for F_7 and F_23.
    I'm not sure if this is a bug, or the result of me not understanding 
    something about char. p. 
    ---> LOW PRIORITY, as I hardly use finite field stuff. 


DONE LIST
---------
[X] Extend aplist implimentation to work over number fields. 
    The only thing which is needed is a routine for factoring
    poly's over a number field.  This can be accomplished once
    I have a function for taking norms, by using the theorem
    in Cohen's book. 

[X]---------------------------------------------------------------
Current space:   M_3(Gamma_0(40=2^3*5), eps=[1 1 4]; Q[a]/(x^2 + 1) )^+, dim=12
Hecke action on: V=S_3, dim=8
---------------------------------------------------------------
M_3(40) ? n
Switching to S_k^{new}
get_Mknew ..M=20    Error in class Array. argument for operator[] out of bounds

---------------------------------------------------------------
Current space:   M_3(Gamma_0(50=2*5^2), eps=[4]; Q[a]/(x^2 + 1) )^+, dim=15
Hecke action on: V=S_k^{new}, dim=5
---------------------------------------------------------------
<<... also, gives errors when computing ap>>

Finding e.
Computing the values 1/<e,f>. [(0.01s)0% (0.01s)20% (0s)40% (0.01s)60% (0s)80% ]
Computing ap:  [2 Error in class Matrix.
Bad indices in Matrix::setrow

ANS: Factor algnum left too many 0's in the vectors which represent the
irreducible factors. 


[XX] Fix mesg system so that it uses a global flag instead of a compile
    time flag. 
DESIGN:
What should a message class do?
  * client code shouldn't have to do much
  * messages should be able to go to any stream, including files
  * messages should be sent by client code using the overloaded
    mesg() function, which should not require instantiation of
    objects by the calling function. 
  * pvm code should be able to send messages to a file
  * a user should have control of whether or not he sees any messages
  * setting of verbosity level (later, but easy to add with below class)

class Mesg {
  bool show;
  ostream& out;      // any output stream should be allowed
public:
  Mesg() : on(true), out(cerr) ;
  ~Mesg() {}
  void on() { show=true; } 
  void off() {show=false; }
  void output(ostream& os) { out=os; }
  void mesg(const char* str);
  void mesg(const char* str, const int n);
  void mesg(const int n, const char* str);
  void mesg(const double f);
} ;

static Mesg Messages;

void mesg(const char* str) { Messages.mesg(str); }

[X] Make computing of Skdual faster by finding Skdual more directly
    using a splitting of Delta. 
UN-SOLN:  I tried using a splitting of delta, but this can't work
because not any splitting will do.  It is necessary to have some
sort of Hecke equivariant splitting.  I wonder how Hecke acts on
the cusps?
    Soln -->  Finding a canonical Hecke-invariant splitting is essentially 
the same as locating the Eisenstein series as a subspace of M_k.  This
can be accomplished directly, using Hecke operators, but it takes way too 
long to be useful in producing a faster aglorithm for computing Sknew. 
UNLESS, I can think of a much quicker way to separate out the Eisenstein part.

[X] Loading MatVecList's takes WAY WAY too long.  Find a better
    way to input rational numbers!!!!!!!!
UN-SOLN: FIRST, it seems that this is *not* the bottleneck.  
    The bottleneck comes when computing the values 1/<e,f>, probably
    in the polinv_polymod function, when computing inverses modulo
    polynomials of very large degree. 
    So the new problem is to optimize this function.
    I compared my bigrational implimentation of xgcd with that in LiDIA
    and found:
             LiDIA                   Mine
            129.5s                   116s           CPU time
    I think it just takes a long time to compute inverses in large
    extensions of Q. 

[X] Bug: intmod charpoly causes SIGSEV
    ANS: I accidentally omitted this line
              ZZ_p::init(ZZ(INIT_VAL,p));

[X] Some reasons why EigenDecomposition is so inefficient:
     -- recursive instead of iterative -- wasteful on memory!
     -- probably should wait until the very end to find the dual
        vectors -- because then the dual vector will be instantly found.
     -- computing kernels could probably be done more quickly in
        LiDIA over the integers. 
                  
[X] good recursive algorithm for finding the eigenspace 
    decomposition.  I think this should be done inside of
    PARI and it should be easily adapted to work with matrices
    over a *number field.*  SEE factornf(), for example.  
WRONG: do with C++, etc. 

[X]  Change everyone to use Heilbronn, not HeilbronnC.  It seems that
     everything still works fine -- after all it should.  It's much
     faster using Heilbronn.

[X] make finite fields deterministic
  done -- in obvious dumb way, just loop through all polys deterministically
      checking for irreducibility. -- works fine. 

[X] change all verbose timing info to go to stderr so redirecting standard
    error to a file eliminates it. 

    hecke 2>a
    tail -f a 
     # very nice!

[X] Fix hecke input problem.
ANS: trying to read from a stream which is EOF does not result in 
     a wait situation -- it results in "garbage" being read in. 
SOLN: write a complete get_int interface with full error checking.
      do the same for other forms of input. 

[X] v option should also have an eigenspace option, which calls
    eigenspace, but doesn't go through the save to userdata phase.
    Eigenspaces cut out by polynomials!



[X] userdata directly should automatically be created. 
 ANS: In system, make a "dataopen" function which automatically
      creates directories. 

[XX] BUG!!:
It computes the new subspace of M_{12}(Gamma_1(N)) as
having dimension 0.

===================== TABLE OF EIGENFORMS ==========================
[X] There were _very_ serious problems with the database of pre-computed
    results because the number of files exceeded the OS limit.  
   ANS:
    The solution is to have a directory for each conductor.  I changed
    character.cc and methodofgraphs.cc so that they do this, and the
    change propogates to everything else :).  I also wrote a shell
    script to convert from my old format to this new one.  
    
i=1;
while [ ${i} -lt 1000 ]; do
  echo
  echo
  echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
  echo "making directory for N = " $i
  echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
  echo
  mkdir $i
  for j in ${i}_*; do
    echo "copying " $j
    mv $j $i
  done
  i=`./ao $i`      # add one to i.
done

ao is a c program whose source i lost. :(


[X] Goal: Automate finding
    q-expansion basis of eigenforms and Hecke action for 
      S_2^{new}(N)
    for N<=1000. 
            * for 2<=n<=100, the following information:
                 * charpoly(T_p), p-prime (?)
                 * n-th coefficient of q-expansion of eigenform 
                   expressed in terms of root of first T_p which
                   has distinct characteristic roots. 
                 * fields over which eigenforms are defined and
                   the corresponding discriminants.
                 * dimensions of atkin-lehner eigenspaces    
     --> easy / Q, more difficult over number fields. 

[X] Construct tables in machine readable form. 

[X] Program to typeset tables. 

[X] Use MethodOfGraphs class plus some thought to construct a table
    of eigenforms for prime levels p < 1000, expressed
    in terms of the supersingular basis.  Do this in a much more
    readable way than I did for Loic last May, i.e., don't simply work
    over F_{p^lcm deg's of factors}, but work over the field for 
    each factor.   

    ---------> ANSWERS: new tables class added.  It turns out that
    the WEB is by far the easiest place to put tables!

[X] BUG! When computing the new subspace with nontrivial
    character, it's important only to take lower levels
    for which the character is prime to N, or something like
    that -- remember Kevin's example. 
   ANS: Take only M so that chi is trivial at p=N/M. 
   In fixing this I found a serious stupid bug in 
      Character::Character(int M, const Character& chi) 
   I had put 
      Character::Character(int M, const Character& chi) 
       : N(M), CHI(NULL), CHIP(NULL), do_save(chi.do_save), _type(chi._type)
    {...}
   and, for whatever reason, this *DOES NOT INITIALIZE do_save and _type,
   except with *random* values.  Instead, I guess one must do this:
     { do_save = chi.do_save;
      _type = chi._type; 
      ...}

[X] It would be better if the irred poly's for finite fields were
    generated in a deterministic manner. 
     XX-->I don't know a good solution.

[X] Add discriminants to list of options in hecke. 
     XX--> No, this would clutter the interface.

[X] Figure out how to compute vanishing - or not - of L(f,s) given
    a manin symbols repn of f. 
   ANS: There is a straightforward generalization of the method described in
   Cremona's book.

[X] Super singular basis should be displayed after it is first
    computed -- not only when loading. 
   ANS: Modify MethodOfGraphs::interface() to be more
    user-friendly.

[X]
-------> ? m
char(K) = 0
N = 64
(N = 2^6)
Chi = 2 1
Arbitrary Dirichlet character. 
Chi is a character of degree 2.
Error in class Array. argument for operator[] out of bounds
   ANSWER: There was a simple bug in the Character::init_arbitrary
   routine: 
   It's fixed by inserting the line 
         if(fac.base(i)==2) continue;
   in the loop
         for(int i=0; i<npd; i++) {    
           bigint bi_pn, bi_pnone;

[X] Nice printing of polynomials with coefficients in an algebraic 
    number field, or a finite field, along with factoring them. 

[X] Add pretty print names for fields.

[X] Make field names unique so that arbitrary fields
    can be saved and loaded correctly. 

[X] Saving and loading over all base fields correctly.
    Fix Matrix algnum save. Right now it uses the wrong output format.
    The same goes for ffield save.  Somehow the poly defining the field
    must be saved.  This is tricky; I'm not sure how to go about it yet. 

[X] clean up interface:

[X] saving and loading of all fields correctly and consistently.

[X] methodofgraphs -- save computed data.

[X] Compute newton polygons. 
   ANS: Pari has a function called newtonpoly.

[X] Fixed a bug in the saving of common eigenspace in hecke.cc, compute_eigen. 
    ANS: It wasn't closing and reopening the file -- instead it just 
         wrote each successive Hecke operator to the end.

[X] Saving and loading Atkin-Lehner involution.
    ANS: trivial, it took 2 minutes to program.

[X] Write a function to compute the kernel of delta on an arbitrary
    subspace of M_k.  This is useful for searching for cusp forms and
    simultaneously reducing the complexity.
    (Added: 18Aug98)

[X] BUG
? dimSk1new
N = 30
k = 2
Error computing genus1(2). Got -1/8
ModularFormulas error.  genus1: not an integer, programming error
[was@cusp hecke]$                                                
    ANS: mu1(N) =/= idxg1(N)/2 for all N, as I had thought.  In the special
         case N=2, they are equal because -1=1 mod (2).  Also, idxg1 gave the
         wrong answer for N=1.

    *************** important **** important ***** important **********
[X] Idea to figure out the "dimension bug".  1) Find the smallest case
    where hecke and hijikata give different dimensions.  2) Compute
    the q-expansion of an Eisenstein series in this space.  3) Find 
    the Eisenstein series as a linear combination of Manin symbols. 
    4) It shouldn't map to zero, but maybe it will.  WHY????
    *******************************************************************
    ANS: change the cusps to use bigint instead of int. 

[X] I've *also* discovered that method of graphs doesn't work in characteristic  
    97 either!!!!!!  there must be something wrong with lidia's finite fields.
    i need an updated version. 
    ANS: NO, there wasn't a problem with F_97.  Instead, the *bug* in LiDIA is that
    the JACOBI FUNCTION ONLY WORKS CORRECTLY when the first argument is positive!!!!
          jacobi(-7,97) doesn't work but jacobi(92,97) does.
                          ****************************

[X] Impliment Atkin-Lehner maps W(q) for all q|N. 
    ANS: simple.  important to change the matrices which sum over.

[X] Finish writing a procedure to compute the new subspace.
     --> more work than it looks.  
         a) it will be tedious to take care of all special cases, i.e., 
            level 1, etc. 
         b) lots of new things to test. 
    ANS: not so bad.  trick: just use the eta for M|N s.t. N/M is prime.

[X] Move mestre.gp into this class library.
       O) find the bug in ffield_element!
       I) Create a class methodgraphs.h methodgraphs.cc
          a) create files. 
          b) basic framework: class, constructor is a prime p. 
          c) add program mog=method of graphs to makefile
          d) test interface
       II) Move gp code over.  Most of mestre.gp has to do with
          factoring and charpolys, neither of which I will probably
          need.  LiDIA has routines for factoring over F_p. 
       III) Optimizations: The thing to optimize is finding the  
          isogeneous curves, i.e., the Hecke action. 
          Perhaps, after computed, the s.s.
          j's should be saved and used in the future to avoid 
          using a factoring algorithm to find roots.  This *might*
          be much faster -- I don't know.  
           * These should be saved, and furthermore, there should
             be a function which returns the s.s. j-s if they've been
             computed.  Many applications will require them. 
                     Array<ffield_element> ssj; 
     	   * This ensures that all T_p are computed wrt the same basis.
       IV) Understand that letter from joe better, so we can compute
           T_p for p>7. 

    -- do all j-invariant arithmetic using my class ffield_element,
       but find isogeneous j's using LiDIA's native types. 
       If too slow change from factoring pols over gf_p^2


[X] bruce.gp --> C++
     I) Bring bruce.gp ---> C++ program.
         1) make sure that kronecker of pari agrees with
              jacobi of LiDIA.  if not, write a wrapper.
         2) just copy it over, and *expand* to c++.
            these will go in the ModularFormulas class. 
	 3) test -- just run a few hundred N, for various k, 
            through each function of each program, get two 
            lists of PARI readable numbers,
            and check that they are the same.   
	SOLN: straightforward and very tedious. nothing interesting.

[X] ??Hijikata implies the dimension of S_2(15020,chi) is 
      2250 whereas my program gives dim(S_2)=dim(M_2)=2256.
      Can there really be no Eisenstein series???  I doubt it!
    SOLN: I changed the cusps class to use arbitrary precision
      arithmetic and, viola, all known discrepancies between
      hijikata dimensions and mod. symbols dimensions disappeared!
              Yes! Yes! Yes!       Yes! Yes! Yes!
      Such a simple solution for a problem which bugged me 
      for a long time.  

[X] make finite field characters like char 0.  i.e., give the
    characteristic and the program takes care of selecting
    the right degree and type, based on the characteristic and
    the character. 
   
    -- think more about how casts work for finite fields.  e.g. in
    char. p, how is zeta_p cast?

[X] Make a "modular formulas" class.  It will contain things like:
      * Shimura's formulas as implimented by Bruce, converted to c++
      * Hijikata's trace formula for dimension.
     I) Structure:
        1) Create the new modformulas.h and .cc files with templates for
           hijikata and bruce's functions, etc.
           a) hijikata(const Character& chi, int k)
           b) index_gamma0(const int& N)
           c) index_gamma1(const int& N), etc. 
           d) error() functions. 
        2) Make a test() interface, compile, and make sure
           the framework works.  
                   
     II)Extend some basic functionality.
        1) Modify character class to compute chi_p:
           a) Add an extra rootof1** CHIP data member, and 
              npd=num prime divisors of N. 
              and save the factorization of N.
           b) When first called, character::ofp(p,a)
              will construct the table:
              i) XXXXX factor N  
              ii) CHIP = new (rootof1*)[p^ord_p(N)]
              iii) construct CHIP table using CRT. 
                   just copy some code. 
           c) table deleted iff CHIP != 0.
                   for i=0,to npd-1
                      delete[] CHIP[i]
                   delete[] CHIP
	   d) TEST: different N, both prime and composite 
                    / various F_p having large degree
                    use CRT in pari to verify
               N, degrees, |  test
              --------------------------------------------------------
                  17, 1     |   ofp
                  20, 2, 4  |  ofp(5,1)=1, ofp(5,2)=zeta_4, ofp(5,10)=0
                            |  ofp(5,-1)=(zeta_4)^2.
               11*389, 5, 1 |  ofp(389,2)=1, ofp(389,389)=0, ofp(11,2)=zeta_5
                            |  ofp(11,8)=zeta_5^3
               2*389, 97    |  ofp(389,4)=(zeta_194)^4

           e) document well with precise defn of ofp:
                 (Z/p^n)* \--> (Z/NZ)* = prod_{p|N} (Z/p^n)*
                  a |----------> thing = a at p^n and 1 at N/(p^n).
                  
        2) Impliment needed arithmetic functions for hijikata and shimura.
           a) floor, ceil (make sure these are the same as in PARI)
                1.2 1.5 1 2 1.75 -1.5 -1.2 -1.7 
	ANS: easy
           b) compute square root mod p^n, when they exist. 
              copy from over.cc, no problem!
	ANS: the above didn't work at all.  instead i had to
	use the LiDIA sqrtmod p function combined with a simple
	itterative algorithm to find square roots modulo p^n. 
           c) Find an element whose 4-th power is one, but
              whose square is not, modulo p^n.  Use code like
              around line 120 of character.cc
                   write #def DEBUG self-verifying code here. 
	ANS: -- or -- simply find a square root of -1 using 2b). 
	
     III) Convert hijikata.gp to C++ program.
           a) define private member functions 
           b) use arrays/switch-case more than if statements
           c) test against miyake, dim.gp, and bruce.gp



[X] Found a bug when computing M_6(37,chiofdegree6;F_25)
	The problem was the following code in h1nchi.cc:
	    n[0]=n[nonzero_one];
	    c[0]=c[nonzero_one];
	When nonzero_one=0, and the base field was ffield_element,
	this caused n[0]=0.  
              ** BE VERY CAREFUL NEVER TO ASSIGN A 
         	 VARIABLE TO ITSELF!!!!!!!!!!!!!!!! **

[X] Compute the n-th cyclotomic polynomial if I enter Q (or char. =0)
    as the field and the character of degree > 2.  This only requires
    changing hecke.cc and would be much nicer than the current interface.
    Add the function polcyclo to arith.h.  Look on page 299 for the
    recursive definition.  Have it return a pari type.  
    ANS: no surprises, straightforward. 


[X] finite_fields don't seem to work right *at all*!-- For example it
    gives the wrong matrix repn' for the Atkin-Lehner operator
    when N=37 and working in F_17.   The best thing to do here
    is to carefully test the finite_fields class outside of the
    context of Hecke operators. 
       I) carefully re-read my implimentation of ffield_element.
      II) modify atkin-lehner code so that it detects the faulty
          arithmetic operation by redundantly doing the computing
          with ints mod F_17.  

    ANS: a) I found the following code in fields.cc !
       if (ffield_element::def_base == 0) {
         delete ffield_element::def_base ;	
         delete ffield_element::prim_elem ;
       }
    This can't be right.  Deleting it iff it doesn't exist yet is stupid.
    Also, it is, by definition, ok to delete the null pointer so the
    the thing to do here is to not check at all.
        This did *not* stop the error message
            error_handler::gf_p_element::multiply: different bases
    which I received upon calling the UserInitField function twice and 
    then using ffield_element objects. 

      b) STATIC DATA MEMBERS OF MEMBER FUNCTIONS ARE STATIC TO THE
         WHOLE DAMN CLASS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         I didn't think this was the case.  I thought they were static
         to any particular instantiation of the class. Upon further 
         reflection that is nonsense.  There is no way the compiler
         could reasonably create such static variables!  I must be 
         very careful about this henceforth. 

      c) observation : for some primes like 19, 11, and 73 atkin
         works -- for others like 5, 7, 13 or 17, it doesn't. 

      d) T_17 acting on S_2(37;F_7) proves that the problem is 
         *not* restricted to atkin-lehner.  Now it might even be in 
         the matrix stuff...
 
      e) !!!!!!! The LiDIA gf_p_element power() function does not 
         work correctly, at least not when used THROUGH my ffield_element
         class !!!!!!!!!!!!!
         I wrote a ffield_element power function and stuck it in fields.cc.
         Now everything works fine! Yeah!  Just to be safe, I'll do the
         same for algnum.

[X] Debug the function eta meant to compute the natural 
    raising level maps.  
    ANS: Loic was completely wrong!!!!!! He computed the action
    by summing over coset reps for Gamma1(N')\Gamma1(N)T instead
    of Gamma1(N')\TGamma1(N), which is completely different!!!!
    It's necessary to work out coset representatives all over
    again from scratch, but in the end it works beautifully. 
   
[X] Make a characteristic polynomial computation system that 
    doesn't run into trouble because of overflow. 
    ANS: This is easy because both LiDIA and NTL can read and
    write their arbitrary precision integers as strings.

[X] Optimize by pre-computing a table of binomial coefficients.

[X] MSymbols list doesn't depend on the character, right, so its
    filename shouldn't either! 
    ANS: Simply change MSymbols::filename(). 

[X] Move all status printing into #ifdef VERBOSE blocks in *all* files.
    It turns out that I either want all information or none when I'm
    using this program. 

[X] Re-write character specification system to use the 
    easier format discussed with Hendrik.  Note that this
    will make *all* data I previously computed incompatible.
    This is because the character *must* be the same.
    Consequently I shall wait on this step.  OR, make it
    so that characters save/load their values and *only*
    use the labels for initializing the character once in
    the first place.  This is good. 
    ANS: I decided not to worry about compatibility with 
    previous data -- it can all be re-generated in a day anyway.
    I timed this task. It took me 5 hours total, including testing.
    I had to write some elementary arith.h stuff.  I didn't
    do the most general character one, because it never comes up in practice.
    

[XX] Impliment the method I worked out in my head a few
    weeks ago to chop the size of the relations matrix
    in "half". 
    ANS: I did this by adding an option to sparse::kernel
    which causes it to return the kernel basis but with 
    the free rows deleted and the data to work with that matrix.
    This is better than deleting later because that would take
    over twice as much memory. 

[XX] Move main linalg code up one directory!
    ANS: But this clutters the directory more.  It does keep me
    from making lots of stupid typing mistakes.  If linalg stuff
    ever becomes stable it can go back to it's own dir. 
[XX] Change sparse::kernel so that it switches to Dense if it runs
    out of memory. 
    ANS?: Maybe I partially solved this by making it switch to Dense
    if a certain low_mem_warning flag is set by the get_more_space
    function.  This isn't clearly fullproof.

[XX] charmod matrices should save themselves in a more compact way! 
     ANS: Change matrix.cc by adding an overloaded "Load" function, e.g.,
       void Load (ifstream& in, Matrix<charmod>& M, bool verbose)
       void Save (ofstream& of, const Matrix<charmod>& M) 	
     one for each class which will be instantiated.  Each provides the
     best way of loading/saving objects of that class.  It was necessary
     to call them using the :: scoping operator since they were not
     member functions.  Also, it was important to read the extra byte
     after loading the numrows and numcols data. 
  
[XX] Optimize act_on_MSym to do all arithmetic over base field.

[XX] User field initialization code should be moved from try.cc to fields.cc.
     ANS: Straightforward.   Created an function UserInitField(object of the 
     field's type).  Call it with something like:
               F a ;
               UserInitField (a); 

[XX] Gamma_1(N), with odd weight, gives completely bogus answers!  Error is
    not in cusps, and probably not in msymbols.cc. 
    ANS: The error was that (-c,-d)=(-1)^k(c,d) instead of (-c,-d)=(c,d).
    This problem didn't appear for Gamma_0 with character because the 
    fact that chi(-1)=-1 forced it.  To fix the problem I changed 
    msymbols::MSym_to_list so that it set lambda=-1 appropriately and 
    I also changed character so that chi.of(-1)=-1 when chi is of
    type ALLCHARS. 

[XX] Fix T_{p^r} so that it works for arbitrary characters, not
     just the trivial character.  ANS: change the line
            M = A*B - p*C;
     of h1nchi.cc to 
	    M = A*B - F(chi.of(p))*p*C;
     This is explained on page 107 of Lang's "Intro. to Mod. Forms".

[XX] There seems to be a bug in the program even
    when computing something as simple as 
          S_2 (Gamma_0(131))  !!!!
           N=137, also gives an obvious wrong answer!
    ANS: the "data" directory was corrupted, but the program
         itself was working fine. 


[X] Gamma_1(N) works only for N prime.  Fix it.  The problem is
    probably *not* in cusps.cc, because the program even gets [...]
    ANS: The msymbol list was constructed incorrectly in the first
    place!  The problem was that (N/2,a)~(N/2,-a) when N is even.
    I noticed this because the index for level 22 was 190 instead
    of 180.










