al = alginit(nfinit(y), [Mat(1)]); \\reported by Bill
J = varhigher("J",y);
Q=nfinit(y); T=polcyclo(5, 'x); F=rnfinit(Q, T);
A = alginit(F, [Mod(x^2,T), 3]);
print("contains nfabs: ", algsplittingfield(A)[12][1] != 0);
A[1][12][1] = 0;
A

qamt(a,b) =
{
  my(m_i,m_j,m_k);
  m_i = [0,a,0,0;
         1,0,0,0;
         0,0,0,a;
         0,0,1,0];
  m_j = [0, 0,b, 0;
         0, 0,0,-b;
         1, 0,0, 0;
         0,-1,0, 0];
  m_k = [0, 0,0,-a*b;
         0, 0,b,   0;
         0,-a,0,   0;
         1, 0,0,   0];
  [matid(4), m_i, m_j, m_k]
};

do(name, test) = {
 setrand(1);
 print(name,": ", iferr(test(), E, E));
}
gusuite(name, tests) = print("Suite: ", name); tests();

searchin(hf,pr,h) =
{
  my(i,n);
  for(i=1,#hf[1],
    if(hf[1][i]==pr, return(hf[2][i]==h))
  );
  return(h==0);
};

samehasse(hf1,hi1,hf2,hi2) =
{
  my(i,n);
  if(hi1 != hi2, return(0));

  n = #hf1[1];
  for(i=1,n,
    if(!searchin(hf2,hf1[1][i],hf1[2][i]), return(0));
  );

  n = #hf2[1];
  for(i=1,n,
    if(!searchin(hf1,hf2[1][i],hf2[2][i]), return(0));
  );

  return(1);
};

hassetriv(hf,hi) = samehasse(hf,hi,[[],Vecsmall([])],Vecsmall(vector(#hi,i,0)));
altriv(al) = hassetriv(alghassef(al),alghassei(al));
alsame(al,hf,hi) = samehasse(alghassef(al),alghassei(al),hf,hi);

testcharpol(al,a)=
{ my (T = algcharpoly(al,a));
  print(T);
  !algpoleval(al,T,a);
}
get() = gusuite("get", ()->{
  my(s='s,i='i,poli,nf,ii,pols,rnf,ss,al);
  poli = i^2+1;
  nf = nfinit(poli);
  ii = Mod(i,poli);
  pols = s^2+2;
  rnf = rnfinit(nf, pols);
  ss = Mod(s,pols);
  al = alginit(rnf,[-ss,ii]);

  do("degree", ()->algdegree(al)==2);
  do("center", ()->algcenter(al)==nf);
  do("splitting", ()->algsplittingfield(al)==rnf);
  do("automorphism", ()->algaut(al)==-ss);
  do("b", ()->algb(al)==ii);
  do("trivial hasse invariants", ()->altriv(al));
  do("charac", ()->algchar(al)==0);
  do("dim", ()->algdim(al)==4);
  do("absdim", ()->algdim(al,1)==8);
  do("basis", ()->#algbasis(al)==8);
  do("invbasis", ()->#alginvbasis(al)==8);
  do("basis*invbasis", ()->algbasis(al)*alginvbasis(al)==matid(8));
  do("iscyclic", ()->algtype(al)==3);
  do("radical", ()->algradical(al)==0); \\cyclic => simple
});

operations() = gusuite("operations", ()->{
  my(s='s,i='i,poli,nf,ii,pols,rnf,ss,al,n,un,u,j);
  poli = i^2+1;
  nf = nfinit(poli);
  ii = Mod(i,poli);
  pols = s^2+2;
  rnf = rnfinit(nf, pols);
  ss = Mod(s,pols);
  ss = ss*Mod(1,poli);
  al = alginit(rnf,[-ss,ii]);

  do("radical", ()->algradical(al)==0); \\cyclic => simple

  nfii = ii;
  ii = ii*Mod(1,pols);

  n = [-ss,ii-1]~;
  un = [1,0]~;
  u = [1-ss,ii-1]~;
  j = [0,1]~;
  do("addition", ()->algadd(al,n,un)==u);
  do("negation", ()->algneg(al,u)==[ss-1,1-ii]~);
  do("soustraction", ()->algsub(al,u,n)==un);
  do("multiplication", ()->algmul(al,n,un)==n);
  do("non-commutativity", ()->algmul(al,n,j)==algmul(al,j,n));
  do("left division", ()->algdivl(al,u,n)==n);
  do("right division", ()->algdivr(al,n,u)==n);
  do("noncommutative left division", ()->algdivl(al,u,j)==[ii+1,1-ss]~);
  do("noncommutative right division", ()->algdivr(al,j,u)==[ii+1,1+ss]~);
  do("division by non-invertible", ()->algdivl(al,n,u));
  do("nilpotent", ()->algsqr(al,n)==[0,0]~);
  do("square", ()->algsqr(al,u)==algadd(al,u,n));
  do("square j", ()->algsqr(al,j)==[ii,0]~);
  do("inverse", ()->alginv(al,u)==algsub(al,un,n));
  do("powers", ()->algpow(al,u,124)==algadd(al,un,algmul(al,[124,0]~,n)));
  do("negative powers", ()->algpow(al,j,-56)==un);
  do("multiplication table j", ()->algtomatrix(al,j)==[0,ii;1,0]);
  do("multiplication table", ()->algtomatrix(al,u)==[1-ss,-1-ii;ii-1,1+ss]);
  do("characteristic polynomial", ()->algcharpoly(al,u,'y)==y^2-2*y+1);
  do("characteristic polynomial j", ()->algcharpoly(al,j,'y)==y^2-nfii);
  do("trace zero", ()->algtrace(al,n)==0);
  do("trace commutator", ()->algtrace(al,algsub(al,algmul(al,j,u),algmul(al,u,j)))==0);
  do("trace", ()->algtrace(al,algmul(al,u,j))==-2-2*nfii);
  do("norm zero", ()->algnorm(al,n)==0);
  do("norm one", ()->algnorm(al,u)==1);
  do("norm j", ()->algnorm(al,j)==-nfii);
  a = algadd(al,u,j); b = algadd(al, n, [12-4*ii+ss*(4-ii),7+3*ii+ss*(1+7*ii)]~);
  do("norm is multiplicative a*b", ()->nfalgtobasis(nf,algnorm(al,algmul(al,a,b)))==nfalgtobasis(nf,nfeltmul(nf,algnorm(al,a),algnorm(al,b))));
  do("norm is multiplicative b*a", ()->nfalgtobasis(nf,algnorm(al,algmul(al,b,a)))==nfalgtobasis(nf,nfeltmul(nf,algnorm(al,b),algnorm(al,a))));
  do("poleval", ()->algbasistoalg(al,algpoleval(al,x^3-2,u)) ==\
algsub(al,algpow(al,u,3),[2,0]~));
  do("poleval b", ()->algbasistoalg(al,algpoleval(al,x^3+i*x-3*i,u)) ==\
algsub(al,algadd(al,algpow(al,u,3), algmul(al,[i,0]~,u)), [3*i,0]~));
});

tensor() = gusuite("tensor product of cyclic algebras", ()->{
  my(nf,pol,jj,al1,al2,al3,hf12,hf23,p7,p7b,p3,p5);
  pol = y^2+y+1;
  nf = nfinit(pol);
  jj = Mod(y,pol);
  al1 = alginit(rnfinit(nf,x^2-(1+jj)), [-x, 4*jj+5]);
  al2 = alginit(rnfinit(nf,x^3-2), [jj*x, 7]);
  al3 = alginit(rnfinit(nf,x^4+x^3+x^2+x+1), [x^2, 7]);
  do("radical 1", ()->algradical(al1)==0); \\cyclic => simple
  do("radical 2", ()->algradical(al2)==0); \\cyclic => simple
  do("radical 3", ()->algradical(al3)==0); \\cyclic => simple
  p3 = idealprimedec(nf,3)[1];
  p5 = idealprimedec(nf,5)[1];
  p7 = idealprimedec(nf,7)[1];
  p7b = idealprimedec(nf,7)[2];

  hf12 = [[p3,p7,p7b],Vecsmall([3,4,5])];
  hf23 = [[p5,p7,p7b],Vecsmall([6,11,7])];

  do("tensor of degree 2 and 3 no mo", ()->alsame(algtensor(al1,al2,0),hf12,Vecsmall([])));
});

rnfprimedec2(rnf,pp,nf2) = {
  my(nf = rnf.nf,pp2,pp3);
  pp2 = rnfidealup(rnf,pp);
  pp3 = idealadd(nf2,pp2[1],pp2[2]);
  for(i=3, #pp2,
    pp3 = idealadd(nf2,pp3,pp2[i]));
  return(idealfactor(nf2,pp3));
};

rnfprimedec(rnf,pp) = rnfprimedec2(rnf,pp,nfinit(rnf.polabs));

testgwa(nf,Lpr,Ld,pl) = ()->{
  my(rnf, d, n, nf2);
  rnf = rnfinit(nf,nfgrunwaldwang(nf,Lpr,Ld,pl,x));
  d = rnf.disc[1];
  n = poldegree(rnf.pol);
  return(1);
  nf2 = nfinit(rnf.polabs);
  for(i=1,#Lpr,
    if(#mattranspose(rnfprimedec2(rnf,Lpr[i],nf2))*Ld[i] != n, return(0)));
  return(1);
};

gw() = gusuite("Grunwald-Wang", ()->{
  my(p2,p3,p5,p7,p11,p13,p17,pp,ppp,nf);
  nf = nfinit(y);
  p2 = idealprimedec(nf,2)[1];
  p3 = idealprimedec(nf,3)[1];
  p5 = idealprimedec(nf,5)[1];
  pp = idealprimedec(nf,nextprime(1234))[1];
  ppp = idealprimedec(nf,nextprime(4321))[1];

  do("A quadratic over Q, 2 large inert, imaginary", testgwa(nf,[pp,ppp],Vecsmall([2,2]),Vecsmall([-1])));
  do("A quartic over Q, 2 large inert, imaginary", testgwa(bnfinit(nf),[pp,ppp],Vecsmall([4,4]),Vecsmall([-1])));

  nf = nfinit(y^2+1);
  p2 = idealprimedec(nf,2)[1];
  p3 = idealprimedec(nf,3)[1];
  p5 = idealprimedec(nf,5)[1];
  do("A : degree 4 over Q(i), local degrees [4,1,1]", testgwa(nf,[p2,p3,p5],Vecsmall([4,1,1]),Vecsmall([])));

  nf = nfinit(y^2+y+1);
  p2 = idealprimedec(nf,2)[1];
  p3 = idealprimedec(nf,3)[1];
  p5 = idealprimedec(nf,5)[1];
  p7 = idealprimedec(nf,7)[1];
  pp = idealprimedec(nf,nextprime(1248))[1];
  ppp = idealprimedec(nf,nextprime(7531))[1];

  do("A degree 3 over Q(j), local degrees [3,3] larger primes", testgwa(nf,[pp,ppp],[3,3],[]));

  nf = nfinit(y^2-5);
  p2 = idealprimedec(nf,2)[1];
  p3 = idealprimedec(nf,3)[1];
  p5 = idealprimedec(nf,5)[1];
  p7 = idealprimedec(nf,7)[1];
  p11 = idealprimedec(nf,11)[1];
  p13 = idealprimedec(nf,13)[1];
  p17 = idealprimedec(nf,17)[1];
  pp = idealprimedec(nf,nextprime(1248))[1];
  ppp = idealprimedec(nf,nextprime(4897))[1];

  do("A : degree 3 over Q(sqrt(5)), local degrees [3,3] [0,0], larger primes",
testgwa(nf,[pp,ppp],[3,3],[0,0]));
  /* TODO check what happens with [-1,-1] */

  nf = nfinit(y^2-7);
  p2 = idealprimedec(nf,2)[1];
  p3 = idealprimedec(nf,3)[1];
  p5 = idealprimedec(nf,5)[1];
  p7 = idealprimedec(nf,7)[1];
  p11 = idealprimedec(nf,11)[1];
  p13 = idealprimedec(nf,13)[1];
  p17 = idealprimedec(nf,17)[1];

  do("A : degree 5 over Q(sqrt(7)), local degrees [5,5,5,5,5,5,5] [0,0]",
testgwa(nf,[p2,p3,p5,p7,p11,p13,p17],Vecsmall([5,5,5,5,5,5,5]),Vecsmall([0,0])));
  /* TODO check what happens with [-1,-1] */

  nf = nfinit(polcyclo(9,y));
  p2 = idealprimedec(nf,2)[1];
  p3 = idealprimedec(nf,3)[1];
  p5 = idealprimedec(nf,5)[1];
  p7 = idealprimedec(nf,7)[1];
  do("A : degree 9 over Q(zeta_9), local degrees [9,9,9,9]", testgwa(nf,[p2,p3,p5,p7],Vecsmall([9,9,9,9]),Vecsmall([])));

  nf = nfinit(y^6 -y^5 -7*y^4 +2*y^3 +7*y^2 -2*y -1);
  p2 = idealprimedec(nf,2)[1];
  p3 = idealprimedec(nf,3)[1];
  p5 = idealprimedec(nf,5)[1];
  p7 = idealprimedec(nf,7)[1];
  p11 = idealprimedec(nf,11)[1];
  p13 = idealprimedec(nf,13)[1];
  p17 = idealprimedec(nf,17)[1];
  pp = idealprimedec(nf,nextprime(1357))[1];
  ppp = idealprimedec(nf,nextprime(853))[1];

  do("A degree 2 over totally real sextic, local degrees [2,2] [2,2,2,2,2,2], larger primes", testgwa(nf,[pp,ppp],Vecsmall([2,2]),Vecsmall([-1,-1,-1,-1,-1,-1])));

  do("A degree 2 over totally real sextic, local degrees [] [2,2,2,2,2,2]", testgwa(nf,[],Vecsmall([]),Vecsmall([-1,-1,-1,-1,-1,-1])));
});

moreoperations() = gusuite("more operations", ()->{
  my(x='x, y='y, nf, p1, p2, iinv, finv, al, u, t, b, w, un, pol1, pol2, cp,
    mul, rnf, aut, ww, tt, ord, invord, Y = varhigher("Y",y));

  pol1 = y;
  nf = nfinit(pol1);
  p1 = idealprimedec(nf,2)[1];
  p2 = idealprimedec(nf,3)[1];
  iinv = [0];
  finv = [[p1,p2],[-2/3,-1/3]];
  setrand(3);
  al = alginit(nf,[3,finv,iinv],x);

  do("construct algebra", ()->al);

  pol2 = algsplittingfield(al).pol;
  mul = Mod(1,pol1)*Mod(1,pol2);
  u = [0,1,0]~*mul;
  t = [x,0,0]~*mul;
  b = [algb(al),0,0]~*mul;
  w = [x+x^2-7,1/2+x-3/7*x^2,12*x-1]~*mul;
  un = [1,0,0]~*mul;

  do("norm(u)", ()->lift(algnorm(al,u))==lift(algb(al)));
  do("norm(t)", ()->algnorm(al,t)==rnfeltnorm(algsplittingfield(al),x));
  do("trace(u)", ()->algtrace(al,u)==0);
  do("trace(t)", ()->algtrace(al,t)==rnfelttrace(algsplittingfield(al),x));
  do("u+t", ()->algadd(al,u,t)==algadd(al,t,u));
  do("u*t", ()->algmul(al,u,t)!=algmul(al,t,u));
  do("u^3", ()->algpow(al,u,3)==b);
  do("w^-1 L", ()->algmul(al,w,alginv(al,w))==un);
  do("w^-1 R", ()->algmul(al,alginv(al,w),w)==un);
  do("w^-1*u", ()->algmul(al,w,algdivl(al,w,u)));
  do("u*w^-1", ()->algmul(al,algdivr(al,u,w),w));
  cp = algcharpoly(al,w,Y);
  do("charpol(w)", ()->cp);
  do("eval charpol", ()->algadd(al,algadd(al,algpow(al,w,3),algmul(al,[polcoeff(cp,2),0,0]~*mul,algsqr(al,w))),algadd(al,algmul(al,[polcoeff(cp,1),0,0]~*mul,w),[polcoeff(cp,0),0,0]~*mul))==0);
  do("trace(w)", ()->algtrace(al,w)==-polcoeff(cp,2));
  do("norm(w)", ()->algnorm(al,w)==-polcoeff(cp,0));
  do("dim", ()->algdim(al)==9);
  do("absdim", ()->algdim(al,1)==9);
  do("iscommutative", ()->algiscommutative(al)==0);
  do("issemisimple", ()->algissemisimple(al)==1);
  do("issimple", ()->algissimple(al)==1);

  pol1 = y^2+1;
  nf = nfinit(pol1);
  pol2 = x^3 + x^2 - 2*x - 1;
  rnf = rnfinit(nf,pol2);
  aut = x^2-2;
  al = alginit(rnf,[aut,Mod(2,pol1)]);
  mul = Mod(1,pol1)*Mod(1,pol2);
  u = [0,1,0]~*mul;
  t = [x,0,0]~*mul;
  tt = [y*x,0,0]~*mul;
  b = [2,0,0]~*mul;
  un = [1,0,0]~*mul;
  w = [y*x-1/3*x^2, 2+y/7-x, -12*x-3*y*x^2]~*mul;
  ww = [-x^2*y, 1/13+y+x+4*x^2, (-2+y)*x^2+(y/3+1/5)*x]~*mul;
  ord = algbasis(al);
  invord = alginvbasis(al);
  do("algleftmultable w+ww", ()->algtomatrix(al,algadd(al,w,ww),1)==(algtomatrix(al,w,1)+algtomatrix(al,ww,1)));
  do("algleftmultable w*ww", ()->algtomatrix(al,algmul(al,w,ww),1)==(algtomatrix(al,w,1)*algtomatrix(al,ww,1)));
  do("alg(basis(w))", ()->algbasistoalg(al,algalgtobasis(al,w))==w);
  do("alg(basis(ww))", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww);
  do("basis(w)+ww", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww)));
  do("basis(w)-ww", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww)));
  do("w+basis(ww)", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww)));
  do("w-basis(ww)", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww)));
  do("basis(w)*ww", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww)));
  do("w*basis(ww)", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww)));
  do("basis(w)^2", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w)));
  do("basis(ww)^2", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww)));
  do("basis(w)\\ww", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww)));
  do("w\\basis(ww)", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww)));
  do("basis(ww)\\w", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w)));
  do("ww\basis(w)", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w)));
  do("basis(w)^-1", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w)));
  do("basis(ww)^-1", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww)));
  do("basis(w)/ww", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww)));
  do("w/basis(ww)", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww)));
  do("basis(ww)/w", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w)));
  do("ww/basis(w)", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w)));
  do("trace(basis(w))", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w)));
  do("trace(basis(ww))", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww)));
  w = [0,0,x*y]~*mul;
  ww = [1+y,1+x,1+x^2]~*mul;
  do("alg(basis(w)) 2", ()->algbasistoalg(al,algalgtobasis(al,w))==w);
  do("alg(basis(ww)) 2", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww);
  do("basis(w)+ww 2", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww)));
  do("basis(w)-ww 2", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww)));
  do("w+basis(ww) 2", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww)));
  do("w-basis(ww) 2", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww)));
  do("basis(w)*ww 2", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww)));
  do("w*basis(ww) 2", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww)));
  do("basis(w)^2 2", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w)));
  do("basis(ww)^2 2", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww)));
  do("basis(w)\ww 2", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww)));
  do("w\basis(ww) 2", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww)));
  do("basis(ww)\w 2", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w)));
  do("ww\basis(w) 2", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w)));
  do("basis(w)^-1 2", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w)));
  do("basis(ww)^-1 2", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww)));
  do("basis(w)/ww 2", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww)));
  do("w/basis(ww) 2", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww)));
  do("basis(ww)/w 2", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w)));
  do("ww/basis(w) 2", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w)));
  do("trace(basis(w)) 2", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w)));
  do("trace(basis(ww)) 2", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww)));
  w = [1/2,1/3*x,1/5]~*mul;
  ww = [1+y,1+x,1+x^2]~*mul;
  do("alg(basis(w)) 3", ()->algbasistoalg(al,algalgtobasis(al,w))==w);
  do("alg(basis(ww)) 3", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww);
  do("basis(w)+ww 3", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww)));
  do("basis(w)-ww 3", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww)));
  do("w+basis(ww) 3", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww)));
  do("w-basis(ww) 3", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww)));
  do("basis(w)*ww 3", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww)));
  do("w*basis(ww) 3", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww)));
  do("basis(w)^2 3", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w)));
  do("basis(ww)^2 3", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww)));
  do("basis(w)\ww 3", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww)));
  do("w\basis(ww) 3", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww)));
  do("basis(ww)\w 3", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w)));
  do("ww\basis(w) 3", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w)));
  do("basis(w)^-1 3", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w)));
  do("basis(ww)^-1 3", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww)));
  do("basis(w)/ww 3", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww)));
  do("w/basis(ww) 3", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww)));
  do("basis(ww)/w 3", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w)));
  do("ww/basis(w) 3", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w)));
  do("trace(basis(w)) 3", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w)));
  do("trace(basis(ww)) 3", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww)));
  do("radical", ()->algradical(al)==0); \\cyclic => simple
  do("iscommutative cyc 3", ()->algiscommutative(al)==0);
  do("issemisimple cyc 3", ()->algissemisimple(al)==1);
  do("issimple cyc 3", ()->algissimple(al)==1);

  pol1 = y;
  nf = nfinit(pol1);
  pol2 = x^2-2;
  rnf = rnfinit(nf,pol2);
  aut = -x;
  al = alginit(rnf,[aut,Mod(5,pol1)]);
  mul = Mod(1,pol1)*Mod(1,pol2);
  u = [0,1]~*mul;
  t = [x,0]~*mul;
  b = [5,0]~*mul;
  un = [1,0]~*mul;
  w = [-1/3*x^2, 2/7-x]~*mul;
  ww = [-x^2*4, 1/13+x+4*x^2]~*mul;
  ord = algbasis(al);
  invord = alginvbasis(al);
  do("algleftmultable/Q w+ww", ()->algtomatrix(al,algadd(al,w,ww),1)==(algtomatrix(al,w,1)+algtomatrix(al,ww,1)));
  do("algleftmultable/Q w*ww", ()->algtomatrix(al,algmul(al,w,ww),1)==(algtomatrix(al,w,1)*algtomatrix(al,ww,1)));
  do("alg(basis(w))/Q", ()->algbasistoalg(al,algalgtobasis(al,w))==w);
  do("alg(basis(ww))/Q", ()->algbasistoalg(al,algalgtobasis(al,ww))==ww);
  do("basis(w)+ww/Q", ()->algadd(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algadd(al,w,ww)));
  do("basis(w)-ww/Q", ()->algsub(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algsub(al,w,ww)));
  do("w+basis(ww)/Q", ()->algadd(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algadd(al,w,ww)));
  do("w-basis(ww)/Q", ()->algsub(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algsub(al,w,ww)));
  do("basis(w)*ww/Q", ()->algmul(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algmul(al,w,ww)));
  do("w*basis(ww)/Q", ()->algmul(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algmul(al,w,ww)));
  do("basis(w)^2/Q", ()->algsqr(al,algalgtobasis(al,w))==algalgtobasis(al,algsqr(al,w)));
  do("basis(ww)^2/Q", ()->algsqr(al,algalgtobasis(al,ww))==algalgtobasis(al,algsqr(al,ww)));
  do("basis(w)\ww/Q", ()->algdivl(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivl(al,w,ww)));
  do("w\basis(ww)/Q", ()->algdivl(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivl(al,w,ww)));
  do("basis(ww)\w/Q", ()->algdivl(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivl(al,ww,w)));
  do("ww\basis(w)/Q", ()->algdivl(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivl(al,ww,w)));
  do("basis(w)^-1/Q", ()->alginv(al,algalgtobasis(al,w))==algalgtobasis(al,alginv(al,w)));
  do("basis(ww)^-1/Q", ()->alginv(al,algalgtobasis(al,ww))==algalgtobasis(al,alginv(al,ww)));
  do("basis(w)/ww/Q", ()->algdivr(al,algalgtobasis(al,w),ww)==algalgtobasis(al,algdivr(al,w,ww)));
  do("w/basis(ww)/Q", ()->algdivr(al,w,algalgtobasis(al,ww))==algalgtobasis(al,algdivr(al,w,ww)));
  do("basis(ww)/w/Q", ()->algdivr(al,algalgtobasis(al,ww),w)==algalgtobasis(al,algdivr(al,ww,w)));
  do("ww/basis(w)/Q", ()->algdivr(al,ww,algalgtobasis(al,w))==algalgtobasis(al,algdivr(al,ww,w)));
  do("trace(basis(w))/Q", ()->algtrace(al,w)==algtrace(al,algalgtobasis(al,w)));
  do("trace(basis(ww))/Q", ()->algtrace(al,ww)==algtrace(al,algalgtobasis(al,ww)));
  do("radical/Q", ()->algradical(al)==0); \\cyclic => simple
  do("iscommutative /Q", ()->algiscommutative(al)==0);
  do("issemisimple /Q", ()->algissemisimple(al)==1);
  do("issimple /Q", ()->algissimple(al)==1);
});

tablealg() = gusuite("table algebra", ()->{
  my(x='x, al, mt, p, un, a, b, c, d, e, ss, projm, liftm, pa, sc);
  mt = [[1,0,0;0,1,0;0,0,1],[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]]; \\Matrices [*,*;0,*]
  un = [1,0,0]~;
  a = [1,0,-1]~;
  b = [0,-1,1]~;
  do("algisassociative 0.0", ()->algisassociative(mt));
  do("algisassociative 0.1", ()->algisassociative(mt[2..3]));
  my (mt0 = mt);
  mt0[3][3,1] = 1;
  do("algisassociative 0.2", ()->algisassociative(mt0));
  do("algisassociative 0.3", ()->algisassociative('x));
  al = algtableinit(mt,0);
  do("construction 0", ()->al);
  do("iscyclic 0", ()->algtype(al)==1);
  do("dim 0", ()->algdim(al,1)==3);
  do("dim 0b", ()->algdim(al)==3);
  do("char 0", ()->algchar(al)==0);
  do("a+b 0", ()->algadd(al,a,b)==[1,-1,0]~);
  do("a-b 0", ()->algsub(al,a,b)==[1,1,-2]~);
  do("a*b 0", ()->algmul(al,a,b)==[0,-1,0]~);
  do("b*a 0", ()->algmul(al,b,a)==[0,0,0]~);
  do("a^2 0", ()->algsqr(al,a)==a);
  do("b^2 0", ()->algsqr(al,b)==b);
  e = [1,1,0]~;
  do("e^691691 0", ()->algpow(al,e,691691)==[1,691691,0]~);
  d = [1,0,1]~;
  do("d^101 0", ()->algpow(al,d,101)==[1,0,2^101-1]~);
  do("multable(a) 0", ()->algtomatrix(al,a,1)==[1,0,0;0,1,0;-1,0,0]);
  do("multable(b) 0", ()->algtomatrix(al,b,1)==[0,0,0;-1,0,-1;1,0,1]);
  do("divl(d,a) 0", ()->algdivl(al,d,a)==a);
  do("divl(d,b) 0", ()->algdivl(al,d,b)==[0,-1,1/2]~);
  do("d^-1 0", ()->alginv(al,d)==[1,0,-1/2]~);
  do("divr(a,d) 0", ()->algdivr(al,a,d)==a);
  do("divr(b,d) 0", ()->algdivr(al,b,d)==[0,-1/2,1/2]~);
  c = [0,7,0]~;
  do("rad(al) 0", ()->#algradical(al)==1); \\matrices [0,*;0,0]
  do("ss(al) 0", ()->#algradical(algquotient(al,algradical(al)))==0);
  [ss,projm,liftm] = algquotient(al,algradical(al),1);
  pa = projm*a;
  do("proj(a) idem 0", ()->algsqr(ss,pa)==pa);
  do("idemproj 0", ()->algcentralproj(ss,[pa,algsub(ss,projm*un,pa)]));
  sc = algcentralproj(ss,[pa,algsub(ss,projm*un,pa)]);
  do("simple components 0", ()->algmultable(sc[1])==[Mat(1)] && algmultable(sc[2])==[Mat(1)]);
  do("center al 0", ()->#algcenter(al)==1);
  do("center ss 0", ()->#algcenter(ss)==2);
  do("primesubalg ss 0", ()->#algprimesubalg(ss)==-1);
  do("charpol annihil(a) 0", ()->testcharpol(al,a));
  do("charpol annihil(b) 0", ()->testcharpol(al,b));
  do("charpol annihil(c) 0", ()->testcharpol(al,c));
  do("charpol annihil(d) 0", ()->testcharpol(al,d));
  do("charpol annihil(e) 0", ()->testcharpol(al,e));
  do("random 0", ()->algrandom(al,1));
  do("algsimpledec 0", ()->#algsimpledec(ss)[2]==2);
  do("alg_decomposition 0", ()->dec=algsimpledec(al); #dec[1]==1 && #dec[2]==2);
  do("iscommutative 0", ()->algiscommutative(al)==0);
  do("issemisimple 0", ()->algissemisimple(al)==0);
  do("issimple 0", ()->algissimple(al)==0);
  do("issimple ss 0", ()->algissimple(ss)==0);
  do("isdivision 0", ()->algisdivision(al)==0);

  p = 2;
  al = algtableinit(mt,p);
  do("algisassociative 2", ()->algisassociative(mt,p));
  do("construction 2", ()->al);
  do("iscyclic 2", ()->algtype(al)==1);
  do("dim 2", ()->algdim(al,1)==3);
  do("char 2", ()->algchar(al)==p);
  do("a+b 2", ()->algadd(al,a,b)==[1,1,0]~);
  do("a-b 2", ()->algsub(al,a,b)==algadd(al,a,b));
  do("a*b 2", ()->algmul(al,a,b)==[0,p-1,0]~);
  do("b*a 2", ()->algmul(al,b,a)==[0,0,0]~);
  do("a^2 2", ()->algsqr(al,a)==a*Mod(1,p));
  do("b^2 2", ()->algsqr(al,b)==b*Mod(1,p));
  do("multable(a) 2", ()->algtomatrix(al,a,1)==[1,0,0;0,1,0;-1,0,0]*Mod(1,p));
  do("multable(b) 2", ()->algtomatrix(al,b,1)==[0,0,0;-1,0,-1;1,0,1]*Mod(1,p));
  do("divl(un,a) 2", ()->algdivl(al,un,a)==a*Mod(1,p));
  do("divl(un,b) 2", ()->algdivl(al,un,b)==b*Mod(1,p));
  do("un^-1 2", ()->alginv(al,un)==un);
  do("divr(a,un) 2", ()->algdivr(al,a,un)==a*Mod(1,p));
  do("divr(b,un) 2", ()->algdivr(al,b,un)==b*Mod(1,p));
  do("rad(al) 2", ()->#algradical(al)==1); \\matrices [0,*;0,0]
  do("ss(al) 2", ()->#algradical(algquotient(al,algradical(al)))==0);
  [ss,projm,liftm] = algquotient(al,algradical(al),1);
  pa = projm*a;
  do("proj(a) idem 2", ()->algsqr(ss,pa)==pa*Mod(1,p));
  do("idemproj 2", ()->algcentralproj(ss,[pa,algsub(ss,projm*un,pa)]));
  sc = algcentralproj(ss,[pa,algsub(ss,projm*un,pa)]);
  do("simple components 2", ()->algmultable(sc[1])==[Mat(Mod(1,p))] && algmultable(sc[2])==[Mat(Mod(1,p))]);
  do("center al 2", ()->#algcenter(al)==1);
  do("center ss 2", ()->#algcenter(ss)==2);
  do("primesubalg ss 2", ()->#algprimesubalg(ss)==2);
  do("charpol annihil(a) 2", ()->testcharpol(al,a));
  do("charpol annihil(b) 2", ()->testcharpol(al,b));
  do("charpol annihil(c) 2", ()->testcharpol(al,c));
  do("random 2", ()->algrandom(al,1));
  do("algsimpledec 2", ()->#algsimpledec(ss)[2]==2);
  do("alg_decomposition 2", ()->dec=algsimpledec(al); #dec[1]==1 && #dec[2]==2);
  do("iscommutative 2", ()->algiscommutative(al)==0);
  do("issemisimple 2", ()->algissemisimple(al)==0);
  do("issimple 2", ()->algissimple(al)==0);
  do("issimple ss 2", ()->algissimple(ss)==0);
  do("matrix trace 2", ()->algtrace(al,[un,vector(3)~;vector(3)~,un])==0);
  do("matrix norm 2", ()->algnorm(al,[un,vector(3)~;vector(3)~,un])==1);
  do("norm 2", ()->algnorm(al,un)==1);

  p = 3;
  mt = [[1,0;0,1],[0,0;1,0]];\\F3[x]/(x^2)
  un = [1,0]~;
  a = [1,-1]~;
  b = [0,1]~;
  al = algtableinit(mt,p);
  do("construction 3", ()->al);
  do("iscyclic 3", ()->algtype(al)==1);
  do("dim 3", ()->algdim(al,1)==2);
  do("char 3", ()->algchar(al)==p);
  do("a+b 3", ()->algadd(al,a,b)==un);
  do("a-b 3", ()->algsub(al,a,b)==[1,1]~);
  do("a*b 3", ()->algmul(al,a,b)==[0,1]~);
  do("b*a 3", ()->algmul(al,b,a)==[0,1]~);
  do("a^2 3", ()->algsqr(al,a)==[1,1]~);
  do("b^2 3", ()->algsqr(al,b)==[0,0]~);
  do("a^691691 3", ()->algpow(al,a,691691)==[1,-691691]~*Mod(1,p));
  do("multable(a) 3", ()->algtomatrix(al,a,1)==[1,0;-1,1]*Mod(1,p));
  do("multable(b) 3", ()->algtomatrix(al,b,1)==[0,0;1,0]);
  do("algdivl(a,b) 3", ()->algdivl(al,a,b)==b);
  do("a^-1 3", ()->alginv(al,a)==[1,1]~);
  do("algdivr(b,a) 3", ()->algdivr(al,b,a)==b);
  do("rad(al) 3", ()->#algradical(al)==1); \\ideal (x)
  do("ss(al) 3", ()->#algradical(algquotient(al,algradical(al)))==0);
  [ss,projm,liftm] = algquotient(al,algradical(al),1);
  do("center al 3", ()->#algcenter(al)==2);
  do("center ss 3", ()->#algcenter(ss)==1);
  do("primesubalg ss 3", ()->#algprimesubalg(ss)==1);
  do("charpol annihil(a) 3", ()->testcharpol(al,a));
  do("charpol annihil(b) 3", ()->testcharpol(al,b));
  do("random 3", ()->algrandom(al,1));
  do("algsimpledec 3", ()->#algsimpledec(ss)[2]==1);
  do("alg_decomposition 3", ()->dec=algsimpledec(al); #dec[1]==1 && #dec[2]==1);
  do("iscommutative 3", ()->algiscommutative(al)==1);
  do("issemisimple 3", ()->algissemisimple(al)==0);
  do("issemisimple ss 3", ()->algissemisimple(ss)==1);
  do("issimple 3", ()->algissimple(al)==0);
  do("issimple ss 3", ()->algissimple(ss)==1);

  p = 3;
  mt = [[1,0,0;0,1,0;0,0,1],[0,0,0;1,0,0;0,1,0],[0,0,0;0,0,0;1,0,0]];\\F3[x]/(x^3)
  un = [1,0,0]~;
  a = [1,-1,0]~;
  b = [0,1,0]~;
  al = algtableinit(mt,p);
  do("construction 3c", ()->al);
  do("iscyclic 3c", ()->algtype(al)==1);
  do("dim 3c", ()->algdim(al,1)==3);
  do("char 3c", ()->algchar(al)==p);
  do("a+b 3c", ()->algadd(al,a,b)==un);
  do("a-b 3c", ()->algsub(al,a,b)==[1,1,0]~);
  do("a*b 3c", ()->algmul(al,a,b)==[0,1,p-1]~);
  do("b*a 3c", ()->algmul(al,b,a)==[0,1,p-1]~);
  do("a^2 3c", ()->algsqr(al,a)==[1,1,1]~);
  do("b^2 3c", ()->algsqr(al,b)==[0,0,1]~);
  do("a^691691 3c", ()->algpow(al,a,691691)==[1,-691691,(691691*691690)\2]~*Mod(1,p));
  do("multable(a) 3c", ()->algtomatrix(al,a,1)==[1,0,0;-1,1,0;0,-1,1]*Mod(1,p));
  do("multable(b) 3c", ()->algtomatrix(al,b,1)==[0,0,0;1,0,0;0,1,0]);
  do("algdivl(a,b) 3c", ()->algdivl(al,a,b)==[0,1,1]~);
  do("a^-1 3c", ()->alginv(al,a)==[1,1,1]~);
  do("algdivr(b,a) 3c", ()->algdivr(al,b,a)==[0,1,1]~);
  do("rad(al) 3c", ()->#algradical(al)==2); \\ideal (x), basis (x,x^2)
  do("ss(al) 3c", ()->#algradical(algquotient(al,algradical(al)))==0);
  [ss,projm,liftm] = algquotient(al,algradical(al),1);
  do("center al 3c", ()->#algcenter(al)==3);
  do("center ss 3c", ()->#algcenter(ss)==1);
  do("primesubalg ss 3c", ()->#algprimesubalg(ss)==1);
  do("charpol annihil(a) 3c", ()->testcharpol(al,a));
  do("charpol annihil(b) 3c", ()->testcharpol(al,b));
  do("random 3c", ()->algrandom(al,1));
  do("algsimpledec 3c", ()->#algsimpledec(ss)[2]==1);
  do("alg_decomposition 3c", ()->dec=algsimpledec(al); #dec[1]==2 && #dec[2]==1);
  do("iscommutative 3c", ()->algiscommutative(al)==1);
  do("issemisimple 3c", ()->algissemisimple(al)==0);
  do("issemisimple ss 3c", ()->algissemisimple(ss)==1);
  do("issimple 3c", ()->algissimple(al)==0);
  do("issimple ss 3c", ()->algissimple(ss)==1);

  p = 2;
  mt = [[1,0;0,1],[0,1;1,1]]; \\F2[x]/(x^2+x+1)
  un = [1,0]~;
  a = [0,1]~;
  b = [1,1]~;
  al = algtableinit(mt,p);
  do("construction 2b", ()->al);
  do("iscyclic 2b", ()->algtype(al)==1);
  do("dim 2b", ()->algdim(al,1)==2);
  do("char 2b", ()->algchar(al)==p);
  do("a+b 2b", ()->algadd(al,a,b)==un);
  do("a-b 2b", ()->algsub(al,a,b)==un);
  do("a*b 2b", ()->algmul(al,a,b)==un);
  do("b*a 2b", ()->algmul(al,b,a)==un);
  do("a^2 2b", ()->algsqr(al,a)==b);
  do("b^2 2b", ()->algsqr(al,b)==a);
  do("a^691691 2b", ()->algpow(al,a,691691)==b);
  do("multable(a) 2b", ()->algtomatrix(al,a,1)==[0,1;1,1]);
  do("multable(b) 2b", ()->algtomatrix(al,b,1)==[1,1;1,0]);
  do("divl(a,b) 2b", ()->algdivl(al,a,b)==a);
  do("a^-1 2b", ()->alginv(al,a)==b);
  do("divr(b,a) 2b", ()->algdivr(al,b,a)==a);
  do("rad(al) 2b", ()->#algradical(al)==0); \\separable extension of F2
  do("center al 2b", ()->#algcenter(al)==2);
  do("primesubalg al 2b", ()->#algprimesubalg(al)==1);
  do("charpol annihil(a) 2b", ()->testcharpol(al,a));
  do("charpol annihil(b) 2b", ()->testcharpol(al,b));
  do("random 2b", ()->algrandom(al,1));
  do("algsimpledec 2b", ()->#algsimpledec(al)[2]==1);
  do("alg_decomposition 2b", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==1 && algdim(dec[2][1],1)==2);
  do("iscommutative 2b", ()->algiscommutative(al)==1);
  do("issemisimple 2b", ()->algissemisimple(al)==1);
  do("issimple 2b", ()->algissimple(al)==1);
  do("issimple,1 2b", ()->algissimple(al,1)==1);


  p = 3;
  mt = [matid(4),

         [0,1,0,0;
          1,0,0,0;
          0,0,1,0;
          0,0,0,-1],

         [0,0,0,1/2;
          0,0,0,1/2;
          1,-1,0,0;
          0,0,0,0],

         [0,0,1/2,0;
          0,0,-1/2,0;
          0,0,0,0;
          1,1,0,0]]*Mod(1,p); \\M_2(F3)
  un = [1,0,0,0]~;
  a = [0,1,-1,0]~;
  b = [1,1,0,1]~;
  al = algtableinit(mt,p);
  do("construction 3b", ()->al);
  do("iscyclic 3b", ()->algtype(al)==1);
  do("dim 3b", ()->algdim(al,1)==4);
  do("char 3b", ()->algchar(al)==p);
  do("a+b 3b", ()->algadd(al,a,b)==[1,-1,2,1]~*Mod(1,p));
  do("a-b 3b", ()->algsub(al,a,b)==[2,0,2,2]~);
  do("a*b 3b", ()->algmul(al,a,b)==[2,2,0,2]~);
  do("b*a 3b", ()->algmul(al,b,a)==[2,0,1,1]~);
  do("a^2 3b", ()->algsqr(al,a)==un);
  do("b^2 3b", ()->algsqr(al,b)==-b*Mod(1,p));
  do("a^691691 3b", ()->algpow(al,a,691691)==a*Mod(1,p));
  do("b^691691 3b", ()->algpow(al,b,691691)==b);
  do("multable(a) 3b", ()->algtomatrix(al,a,1)==[0,1,0,1;1,0,0,1;2,1,1,0;0,0,0,2]);
  do("multable(b) 3b", ()->algtomatrix(al,b,1)==[1,1,2,0;1,1,1,0;0,0,2,0;1,1,0,0]);
  do("divl(a,b) 3b", ()->algdivl(al,a,b)==[2,2,0,2]~);
  do("a^-1 3b", ()->alginv(al,a)==[0,1,2,0]~);
  do("divr(b,a) 3b", ()->algdivr(al,b,a)==[2,0,1,1]~);
  c = [0,0,1,0]~;
  do("rad(al) 3b", ()->#algradical(al)==0); \\matrix ring is semisimple
  do("center al 3b", ()->#algcenter(al)==1);
  do("primesubalg al 3b", ()->#algprimesubalg(al)==1);
  do("charpol annihil(a) 3b", ()->testcharpol(al,a));
  do("charpol annihil(b) 3b", ()->testcharpol(al,b));
  do("charpol annihil(c) 3b", ()->testcharpol(al,c));
  do("random 3b", ()->algrandom(al,1));
  do("algsimpledec 3b", ()->#algsimpledec(al)[2]==1);
  do("alg_decomposition 3b", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==1 && #algcenter(dec[2][1])==1);
  do("iscommutative 3b", ()->algiscommutative(al)==0);
  do("issemisimple 3b", ()->algissemisimple(al)==1);
  do("issimple 3b", ()->algissimple(al)==1);

  p = 2;
  mt = [matid(4),

     [0,0,1,0;
      1,0,0,1;
      0,0,0,0;
      0,0,-1,0],

     [0,0,0,0;
      0,0,0,0;
      1,0,0,0;
      0,1,0,0],

     [0,0,0,0;
      0,0,0,0;
      0,0,1,0;
      1,0,0,1]]*Mod(1,p); \\M_2(F2)
  un = [1,0,0,0]~;
  a = [0,1,0,0]~;
  b = [1,0,0,1]~;
  al = algtableinit(mt,p);
  do("construction 2c", ()->al);
  do("iscyclic 2c", ()->algtype(al)==1);
  do("dim 2c", ()->algdim(al,1)==4);
  do("char 2c", ()->algchar(al)==p);
  do("a+b 2c", ()->algadd(al,a,b)==[1,1,0,1]~);
  do("a-b 2c", ()->algsub(al,a,b)==[1,1,0,1]~);
  do("a*b 2c", ()->algmul(al,a,b)==[0,0,0,0]~);
  do("b*a 2c", ()->algmul(al,b,a)==a);
  do("a^2 2c", ()->algsqr(al,a)==[0,0,0,0]~);
  do("b^2 2c", ()->algsqr(al,b)==b);
  c = [1,1,1,1]~;
  do("a^691691 2c", ()->algpow(al,a,691691)==[0,0,0,0]~);
  do("b^691691 2c", ()->algpow(al,b,691691)==b);
  do("c^691691 2c", ()->algpow(al,c,691691)==[0,1,1,1]~);
  do("multable(a) 2c", ()->algtomatrix(al,a,1)==[0,0,1,0;1,0,0,1;0,0,0,0;0,0,1,0]);
  do("multable(b) 2c", ()->algtomatrix(al,b,1)==[1,0,0,0;0,1,0,0;0,0,0,0;1,0,0,0]);
  do("divl(c,a) 2c", ()->algdivl(al,c,a)==[0,0,0,1]~);
  do("divl(c,b) 2c", ()->algdivl(al,c,b)==[0,0,1,0]~);
  do("c^-1 2c", ()->alginv(al,c)==[0,1,1,1]~);
  do("divr(a,c) 2c", ()->algdivr(al,a,c)==[1,1,0,1]~);
  do("divr(b,c) 2c", ()->algdivr(al,b,c)==[0,1,0,0]~);
  do("rad(al) 2c", ()->#algradical(al)==0); \\matrix ring is semisimple
  do("center al 2c", ()->#algcenter(al)==1);
  do("primesubalg al 2c", ()->#algprimesubalg(al)==1);
  do("charpol annihil(a) 2c", ()->testcharpol(al,a));
  do("charpol annihil(b) 2c", ()->testcharpol(al,b));
  do("charpol annihil(c) 2c", ()->testcharpol(al,c));
  do("random 2c", ()->algrandom(al,1));
  do("algsimpledec 2c", ()->#algsimpledec(al)[2]==1);
  do("alg_decomposition 2c", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==1 && #algcenter(dec[2][1])==1);
  do("iscommutative 2c", ()->algiscommutative(al)==0);
  do("issemisimple 2c", ()->algissemisimple(al)==1);
  do("issimple 2c", ()->algissimple(al)==1);

  p = 5;
  mt = [Mat(Mod(1,p))];
  un = [1]~;
  a = [2]~;
  b = [3]~;
  al = algtableinit(mt,p);
  do("construction 5", ()->al);
  do("iscyclic 5", ()->algtype(al)==1);
  do("dim 5", ()->algdim(al,1)==1);
  do("char 5", ()->algchar(al)==p);
  do("a+b 5", ()->algadd(al,a,b)==[Mod(0,p)]~);
  do("a-b 5", ()->algsub(al,a,b)==[Mod(4,p)]~);
  do("a*b 5", ()->algmul(al,a,b)==[Mod(1,p)]~);
  do("b*a 5", ()->algmul(al,b,a)==[Mod(1,p)]~);
  do("a^2 5", ()->algsqr(al,a)==[Mod(4,p)]~);
  do("b^2 5", ()->algsqr(al,b)==[Mod(-1,p)]~);
  do("a^691691 5", ()->algpow(al,a,691691)==b);
  do("multable(a) 5", ()->algtomatrix(al,a,1)==Mat(Mod(2,p)));
  do("multable(b) 5", ()->algtomatrix(al,b,1)==Mat(Mod(3,p)));
  do("divl(a,b) 5", ()->algdivl(al,a,b)==[Mod(4,p)]~);
  do("a^-1 5", ()->alginv(al,a)==[Mod(3,p)]~);
  do("divr(a,b) 5", ()->algdivr(al,a,b)==[Mod(4,p)]~);
  do("rad(al) 5", ()->#algradical(al)==0); \\F5, dim 1
  do("center al 5", ()->#algcenter(al)==1);
  do("primesubalg al 5", ()->#algprimesubalg(al)==1);
  do("charpol annihil(a) 5", ()->testcharpol(al,a));
  do("charpol annihil(b) 5", ()->testcharpol(al,b));
  do("random 5", ()->algrandom(al,1));
  do("algsimpledec 5", ()->#algsimpledec(al)[2]==1);
  do("alg_decomposition 5", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==1 && algdim(dec[2][1],1)==1);
  do("iscommutative 5", ()->algiscommutative(al)==1);
  do("issemisimple 5", ()->algissemisimple(al)==1);
  do("issimple 5", ()->algissimple(al)==1);

  p = 0; \\M_2(Q)+Q
  mt = [matid(5),

     [0,0,1,0,0;
      1,0,0,1,0;
      0,0,0,0,0;
      0,0,-1,0,0;
      0,1,-1,-1,1],

     [0,0,0,0,0;
      0,0,0,0,0;
      1,0,0,0,0;
      0,1,0,0,0;
      0,0,0,0,0],

     [0,0,0,0,0;
      0,0,0,0,0;
      0,0,1,0,0;
      1,0,0,1,0;
      0,0,0,0,0],

     [0,0,0,0,0;
      0,0,0,0,0;
      0,0,0,0,0;
      0,0,0,0,0;
      1,1,0,0,1]
  ];
  un = [1,0,0,0,0]~;
  a = [1,0,0,0,-1]~;
  b = [1,1,0,0,0]~;
  al = algtableinit(mt,p);
  do("construction 0b", ()->al);
  do("iscyclic 0b", ()->algtype(al)==1);
  do("dim 0b", ()->algdim(al,1)==5);
  do("char 0b", ()->algchar(al)==p);
  do("a+b 0b", ()->algadd(al,a,b)==[2,1,0,0,-1]~);
  do("a-b 0b", ()->algsub(al,a,b)==[0,-1,0,0,-1]~);
  do("a*b 0b", ()->algmul(al,a,b)==[1,1,0,0,-2]~);
  do("b*a 0b", ()->algmul(al,b,a)==algmul(al,a,b));\\a central
  do("a^2 0b", ()->algsqr(al,a)==a);
  do("b^2 0b", ()->algsqr(al,b)==[1,2,0,0,1]~);
  do("a^691691 0b", ()->algpow(al,a,691691)==a);
  do("b^691 0b", ()->algpow(al,b,691)==[1,691,0,0,2^691-1-691]~);
  do("multable(a) 0b", ()->algtomatrix(al,a,1)==
      [1,0,0,0,0;
       0,1,0,0,0;
       0,0,1,0,0;
       0,0,0,1,0;
       -1,-1,0,0,0]);
  do("multable(b) 0b", ()->algtomatrix(al,b,1)==
      [1,0,1,0,0;
       1,1,0,1,0;
       0,0,1,0,0;
       0,0,-1,1,0;
       0,1,-1,-1,2]);
  do("divl(b,a) 0b", ()->algdivl(al,b,a)==[1,-1,0,0,0]~);
  do("b^-1 0b", ()->alginv(al,b)==[1,-1,0,0,1/2]~);
  do("divr(a,b) 0b", ()->algdivr(al,a,b)==algdivl(al,b,a));
  do("rad(al) 0b", ()->#algradical(al)==0);
  do("idemproj 0b", ()->algcentralproj(al,[a,algsub(al,un,a)]));
  sc = algcentralproj(al,[a,algsub(al,un,a)]);
  do("simple components 0b", ()->algdim(sc[1],1)==4 && algdim(sc[2],1)==1);
  do("mt M2 component 0b", ()->algmultable(sc[1])[1]==matid(4));
  do("center al 0b", ()->#algcenter(al)==2);
  do("primesubalg al 0b", ()->#algprimesubalg(al)==-1);
  do("charpol annihil(a) 0b", ()->testcharpol(al,a));
  do("charpol annihil(b) 0b", ()->testcharpol(al,b));
  do("random 0b", ()->algrandom(al,1));
  do("algsimpledec 0b", ()->#algsimpledec(al)[2]==2);
  do("alg_decomposition 0b", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==2
    && #algcenter(dec[2][1])==1 && #algcenter(dec[2][2])==1 &&
    (algdim(dec[2][1],1)==4 || algdim(dec[2][2],1)==4));
  do("subalg M2(Q)", ()->sal=algsubalg(al,[1,0,0,0; 0,1,0,0; 0,0,1,0; 0,0,0,1;\
    0,0,0,0])[1]; algisassociative(sal) && algradical(sal)==0 &&\
    #algsimpledec(sal)[2]==1);
  do("iscommutative 0b", ()->algiscommutative(al)==0);
  do("issemisimple 0b", ()->algissemisimple(al)==1);
  do("issimple 0b", ()->algissimple(al)==0);

  p = 3;
  al = algtableinit(mt,p);
  do("construction 3d", ()->al);
  do("iscyclic 3d", ()->algtype(al)==1);
  do("dim 3d", ()->algdim(al,1)==5);
  do("char 3d", ()->algchar(al)==p);
  do("a+b 3d", ()->algadd(al,a,b)==[2,1,0,0,-1]~*Mod(1,p));
  do("a-b 3d", ()->algsub(al,a,b)==[0,-1,0,0,-1]~*Mod(1,p));
  do("a*b 3d", ()->algmul(al,a,b)==[1,1,0,0,-2]~*Mod(1,p));
  do("b*a 3d", ()->algmul(al,b,a)==algmul(al,a,b));\\a central
  do("a^2 3d", ()->algsqr(al,a)==a*Mod(1,p));
  do("b^2 3d", ()->algsqr(al,b)==[1,2,0,0,1]~);
  do("a^691691 3d", ()->algpow(al,a,691691)==a*Mod(1,p));
  do("b^691 3d", ()->algpow(al,b,691)==[1,691,0,0,2^691-1-691]~*Mod(1,p));
  do("multable(a) 3d", ()->algtomatrix(al,a,1)==
      [1,0,0,0,0;
       0,1,0,0,0;
       0,0,1,0,0;
       0,0,0,1,0;
       -1,-1,0,0,0]*Mod(1,p));
  do("multable(b) 3d", ()->algtomatrix(al,b,1)==
      [1,0,1,0,0;
       1,1,0,1,0;
       0,0,1,0,0;
       0,0,-1,1,0;
       0,1,-1,-1,2]*Mod(1,p));
  do("divl(b,a) 3d", ()->algdivl(al,b,a)==[1,-1,0,0,0]~*Mod(1,p));
  do("b^-1 3d", ()->alginv(al,b)==[1,-1,0,0,1/2]~*Mod(1,p));
  do("divr(a,b) 3d", ()->algdivr(al,a,b)==algdivl(al,b,a));
  do("rad(al) 3d", ()->#algradical(al)==0);
  do("idemproj 3d", ()->algcentralproj(al,[a,algsub(al,un,a)]));
  sc = algcentralproj(al,[a,algsub(al,un,a)]);
  do("simple components 3d", ()->algdim(sc[1],1)==4 && algdim(sc[2],1)==1);
  do("mt M2 component 3d", ()->algmultable(sc[1])[1]==matid(4));
  do("center al 3d", ()->#algcenter(al)==2);
  do("primesubalg al 3d", ()->#algprimesubalg(al)==2);
  do("charpol annihil(a) 3d", ()->testcharpol(al,a));
  do("charpol annihil(b) 3d", ()->testcharpol(al,b));
  do("random 3d", ()->algrandom(al,1));
  do("algsimpledec 3d", ()->#algsimpledec(al)[2]==2);
  do("alg_decomposition 3d", ()->dec=algsimpledec(al); dec[1]==0 && #dec[2]==2
    && #algcenter(dec[2][1])==1 && #algcenter(dec[2][2])==1 &&
    (algdim(dec[2][1],1)==4 || algdim(dec[2][2],1)==4));
  do("subalg M2(F3)", ()->sal=algsubalg(al,[1,0,0,0; 0,1,0,0; 0,0,1,0; 0,0,0,1;\
    0,0,0,0]); algisassociative(sal[1]) && algradical(sal[1])==0 &&\
    #algsimpledec(sal[1])[2]==1);
  do("iscommutative 3d", ()->algiscommutative(al)==0);
  do("issemisimple 3d", ()->algissemisimple(al)==1);
  do("issimple 3d", ()->algissimple(al)==0);
  do("issimple,1 3d", ()->algissimple(al,1)==0);
});

all() = gusuite("all", ()->{
  get();
  operations();
  tensor();
  gw();
  moreoperations();
  tablealg();
});

all();

nf = nfinit(y^2-2);
al = alginit(nf, [-3,-5], x,3);
print("maxorder assoc: ", algisassociative(al[9]));
al0 = alginit(nf, [-3,-5], x,0);
print("natorder assoc: ", algisassociative(al0[9]));
un = [1,0]~;
ii = [x,0]~;
jj = [0,1]~;
kk = algmul(al,ii,jj);
print("spl(1): ", algtomatrix(al,un)==matid(2));
print("spl(i): ", algtomatrix(al,ii)==[x,0;0,-x]);
print("spl(j): ", algtomatrix(al,jj)==[0,-5;1,0]);
print("spl(k): ", algtomatrix(al,kk)==[0,-5*x;-x,0]);
print("spl(basis(1)): ", algtomatrix(al,algalgtobasis(al,un))==matid(2));
print("spl(basis(i)): ", algtomatrix(al,algalgtobasis(al,ii))==[x,0;0,-x]);
print("spl(basis(j)): ", algtomatrix(al,algalgtobasis(al,jj))==[0,-5;1,0]);
print("spl(basis(k)): ", algtomatrix(al,algalgtobasis(al,kk))==[0,-5*x;-x,0]);
a = y+1;
b = 1/3;
c = -y/5+1/2;
print("spl(a*1): ", algtomatrix(al,a*un)==a*matid(2));
print("spl(a*i): ", algtomatrix(al,a*ii)==a*[x,0;0,-x]);
print("spl(a*j): ", algtomatrix(al,a*jj)==a*[0,-5;1,0]);
print("spl(a*k): ", algtomatrix(al,a*kk)==a*[0,-5*x;-x,0]);
print("spl(b*1): ", algtomatrix(al,b*un)==b*matid(2));
print("spl(b*i): ", algtomatrix(al,b*ii)==b*[x,0;0,-x]);
print("spl(b*j): ", algtomatrix(al,b*jj)==b*[0,-5;1,0]);
print("spl(b*k): ", algtomatrix(al,b*kk)==b*[0,-5*x;-x,0]);


ord = algbasis(al);
invord = alginvbasis(al);
setrand(1);
x1 = algrandom(al,1);
ax1 = algbasistoalg(al,x1);
nx1 = algalgtobasis(al0,ax1);
print("nattomax 1: ", nx1==ord*x1);
setrand(2);
x2 = algrandom(al,1);
ax2 = algbasistoalg(al,x2);
nx2 = algalgtobasis(al0,ax2);
print("nattomax 2: ", nx2==ord*x2);
print("ord*invord=id: ", ord*invord == matid(8));
print("spl additive: ", algtomatrix(al,x1) + algtomatrix(al,x2) == algtomatrix(al, algadd(al,x1,x2)));
print("spl multiplicative: ", algtomatrix(al,x1) * algtomatrix(al,x2) == algtomatrix(al, algmul(al,x1,x2)));
print("changebasis bug 1: ", algalgtobasis(al,algbasistoalg(al,algmul(al,x1,x2)))==algmul(al,x1,x2));
print("changebasis bug 2: ", algalgtobasis(al0,algmul(al0,ax1,ax2)) == algmul(al0,nx1,nx2));
print("changebasis bug 3: ", invord*algmul(al0,nx1,nx2) == algmul(al,x1,x2));
print("changebasis bug 4: ", algtomatrix(al,x1,1) == invord*algtomatrix(al0,nx1,1)*ord);

print("algtableinit segfault bug: ");
alt = algtableinit(al[9]);
print(alt != 'alt);
print("center of CSA: ", #algcenter(alt)==2);
print("radical of CSA: ", algradical(alt)==0);
print("decomposition of CSA: ", #algsimpledec(alt)[2]==1);
dec = algsimpledec(alt);
{print("alg_decomposition of CSA: ", #dec==2 && dec[1]==0 && #dec[2]==1 &&
  #algcenter(dec[2][1])==2 && algdim(dec[2][1],1)==8);}

print("alsimple bug");
mt = [matid(3), [0,0,0;1,1,0;0,0,0], [0,0,0;0,0,0;1,0,1]];
A = algtableinit(mt);
algissimple(A)

print("tests for al_CSA: ");
T = y^3-y+1;
nf = nfinit(T);
   m_i = [0,-1,0, 0;\
          1, 0,0, 0;\
          0, 0,0,-1;\
          0, 0,1, 0];
   m_j = [0, 0,-1,0;\
          0, 0, 0,1;\
          1, 0, 0,0;\
          0,-1, 0,0];
   m_k = [0, 0, 0, -1;\
          0, 0,-1, 0;\
          0, 1, 0, 0;\
          1, 0, 0, 0];
mt = [matid(4), m_i, m_j, m_k];
print(algisassociative(mt));
al = alginit(nf, mt, 'x);
print(al != 0);
print("algebra:");
print("csa getcenter: ", algcenter(al) == nf);
print("csa getsplitting: ", algsplittingfield(al) != 0);
print("getrelmultable: ", algrelmultable(al) == mt);
print("getsplittingdata:");
print(#algsplittingdata(al) == 3);
print(#algsplittingdata(al)[1] == 12);
print(#algsplittingdata(al)[2] == 2);
print(#algsplittingdata(al)[3][1,] == 12);
print(#algsplittingdata(al)[3][,1] == 2);
print(al[3][3]*al[3][2][,1] == [1,0]~);
print(al[3][3]*al[3][2][,2] == [0,1]~);
polabs = al[1][12][1].pol;
for(i=1,10,\
print(al[3][3]*algmul(al, al[3][2][,1], algpow(al,al[3][1],i)) == [Mod(x^i,polabs),0]~);\
print(al[3][3]*algmul(al, al[3][2][,2], algpow(al,al[3][1],i)) == [0,Mod(x,polabs)^i]~)\
);
print("hasse invariants:");
do("hassei csa", () -> alghassei(al) == 0);
do("hassef cas", () -> alghassef(al) == 0);
do("hasse csa", () -> alghasse(al,1) == 0);
print("csa splitting pol: ", poldegree(al[1][12][1].pol) == 6);
print("csa basis: ", matsize(algbasis(al)) == [12,12]);
print("csa invbasis: ", matsize(alginvbasis(al)) == [12,12]);
print("csa absdim: ", #algmultable(al) == algdim(al,1));
print("csa char: ", algchar(al) == 0);
print("csa deg: ", algdegree(al) == 2);
print("csa dim: ", algdim(al) == 4);
print("csa absdim: ", algdim(al,1) == 12);
print("csa type: ", algtype(al) == 2); \\2==al_CSA
print("csa iscommutative: ", algiscommutative(al)==0);
print("csa issemisimple: ", algissemisimple(al)==1);

print("elements:");
a = [0, Mod(y,T), 0, 0]~;
b = [0, -1, Mod(2*y^2,T), 0]~;
c = [Mod(1-y+2*y^2,T), 3, 0, Mod(-3*y,T)]~;
mynorm(aa) = sum(i=1,4,aa[i]^2);
algbasistoalg(al,a)
algalgtobasis(al,[1,2,3,4,5,6,7,8,9,10,11,12]~)

print("csa add: ", algadd(al,a,b) == a+b);
print("csa neg: ", algneg(al,a) == -a);
print("csa neg 2: ", algneg(al,b) == -b);
print("csa sub: ", algsub(al,a,b) == a-b);
print("csa mul: ", algmul(al,a,b) == [Mod(y,T), 0, 0, Mod(2*y-2,T)]~);
print("csa mul 2: ", algmul(al,b,a) == [Mod(y,T), 0, 0, Mod(2-2*y,T)]~);
print("csa sqr: ", algsqr(al,a) == [Mod(-y^2,T),0,0,0]~);
print("csa sqr 2: ", algsqr(al,b) == [Mod(-1-4*y^4,T),0,0,0]~);
print("csa mt: ", algrelmultable(al)*b == -m_i + Mod(2*y^2,T)*m_j);
print("csa inv: ", alginv(al,a) == -1/y^2*a);
print("csa inv 2: ", alginv(al,b) == -1/Mod(1+4*y^4,T)*b);
print("csa divl: ", algdivl(al,1+a+b,b) == algmul(al, alginv(al, 1+a+b), b));
print("csa pow: ", algpow(al, a, 5) == Mod(y^4,T)*a);
aa = algalgtobasis(al, a);
bb = algalgtobasis(al, b);
cc = algalgtobasis(al, c);
print("csa mul 3: ", algmul(al,aa,b) == algalgtobasis(al,algmul(al,a,b)));
print("csa mul 4: ", algmul(al,a,bb) == algalgtobasis(al,algmul(al,a,b)));
print("csa pow 2: ", algpow(al,aa,13) == algalgtobasis(al,algpow(al,a,13)));
print("csa sub 2: ", algsub(al,aa,b) == algalgtobasis(al,algsub(al,a,b)));
print("csa sub 3: ", algsub(al,bb,a) == algalgtobasis(al,algsub(al,b,a)));
print("csa inv 3: ", alginv(al,aa) == algalgtobasis(al,alginv(al,a)));
print("csa inv 4: ", alginv(al,bb) == algalgtobasis(al,alginv(al,b)));
print("csa inv 5: ", alginv(al,algadd(al,a,bb)) == algalgtobasis(al,alginv(al,algadd(al,a,b))));
print("csa trace: ", algtrace(al,cc) == 2*c[1]);
print("csa trace 2: ", algtrace(al,c) == 2*c[1]);
print("csa abs trace: ", algtrace(al,cc,1) == 4*trace(Mod(c[1],T)));
print("csa abs trace 2: ", algtrace(al,c,1) == 4*trace(Mod(c[1],T)));

D = 12;
flag = 1;
for(i=1, D,\
  for(j=i, D,\
    ei = matid(D)[,i];\
    ej = matid(D)[,j];\
    flag = flag && (algtomatrix(al,ei)*algtomatrix(al,ej) == algtomatrix(al, algmul(al, ei, ej)));\
    flag = flag && (algtomatrix(al,ei)+algtomatrix(al,ej) == algtomatrix(al, algadd(al, ei, ej)))\
    ));
print(flag);

print("testcharpol");
testcharpol(al,elt) = print(algcharpoly(al,elt)==x^2-algtrace(al,elt)*x+mynorm(elt));
testcharpol(al,a);
testcharpol(al,b);
testcharpol(al,c);

print("testcharpol2");
testcharpol2(al,elt) = print(algcharpoly(al,elt)==x^2-algtrace(al,elt)*x+mynorm(algbasistoalg(al,elt)));
testcharpol2(al,aa);
testcharpol2(al,bb);
testcharpol2(al,cc);

print("testnorm");
testnorm(al,elt) = print(algnorm(al,elt) == mynorm(elt));
testnorm(al,a);
testnorm(al,b);
testnorm(al,c);

print("testnorm2");
testnorm2(al,elt) = print(algnorm(al,elt) == mynorm(algbasistoalg(al,elt)));
testnorm2(al,aa);
testnorm2(al,bb);
testnorm2(al,cc);

doubleindex(N,i,j) = (i-1)*N+j;
matrixringmt(N) =
{
  my(mt = [Mat([Col(0,N^2) | i<-[1..N^2]]) | j<-[1..N^2]], B, Bi, mt2=Vec(0,N^2));
  for(i=1,N,
    for(j=1,N,
      for(k=1,N,
        mt[doubleindex(N,i,j)][doubleindex(N,i,k),doubleindex(N,j,k)] = 1
      )
    )
  );
  B = matid(N^2);
  for(i=1, N, B[doubleindex(N,i,i),1]=1);
  Bi = B^(-1);
  mt2[1] = matid(N^2);
  for(i=2,N^2, mt2[i] = Bi*mt[i]*B);
  mt2;
}

print("examples from docu");
setrand(1);
algtype([])
A = alginit(nfinit(y),[-1,1]);
algadd(A,[1,0]~,[1,2]~)
algisinv(A,[-1,1]~)
algisinv(A,[1,2]~,&ix)
ix
algisdivl(A,[x+2,-x-2]~,[x,1]~)
algisdivl(A,[x+2,-x-2]~,[-x,x]~)
algisdivl(A,[x+2,-x-2]~,[-x,x]~,&z)
z

A = alginit(nfinit(y^2-5),[2,y]);
algalgtobasis(A,[y,1]~)
algbasistoalg(A,algalgtobasis(A,[y,1]~))

algbasistoalg(A,[0,1,0,0,2,-3,0,0]~)
algalgtobasis(A,algbasistoalg(A,[0,1,0,0,2,-3,0,0]~))

mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
A = algtableinit(mt,2);
e = [0,1,0]~;
one = [1,0,0]~;
e2 = algsub(A,one,e);
algcentralproj(A,[e,e2])
algprimesubalg(A)
algquotient(A,[0;1;0])
algsubalg(A,[1,0; 0,0; 0,1])
algiscommutative(A)
algissimple(A)

mt = [matid(3),[0,0,0;1,0,1;0,0,0],[0,0,0;0,0,0;1,0,1]];
A = algtableinit(mt);
algiscommutative(A)
algissemisimple(A)
algissimple(A)
algissimple(A,1)

nf = nfinit(y^2-5);
A = alginit(nf, [-3,1-y]);
alghassef(A)
algdegree(A)^algdim(A,1)*nf.disc^algdim(A)*idealnorm(nf,alghassef(A)[1][2])^algdegree(A)
algdisc(A)

nf = nfinit(y^3-y+1);
A = alginit(nf, [-1,-1]);
algdim(A,1)
algcenter(A).pol
algdegree(A)
algdim(A)

nf = nfinit(y);
p = idealprimedec(nf,7)[1];
p2 = idealprimedec(nf,11)[1];
A = alginit(nf,[3,[[p,p2],[1/3,2/3]],[0]]);
algaut(A)
algb(A)

mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
A = algtableinit(mt,13);
algchar(A)
algtype(A)

nf = nfinit(y^2-5);
A = alginit(nf, [-1,2*y-1]);
alghassef(A)
A = alginit(nf, [-1,y]);
alghassei(A)
alghasse(A, 1)
alghasse(A, 2)
alghasse(A, idealprimedec(nf,2)[1])
alghasse(A, idealprimedec(nf,5)[1])
algindex(A, 1)
algindex(A, 2)
algindex(A, idealprimedec(nf,2)[1])
algindex(A, idealprimedec(nf,5)[1])
algindex(A)
algisdivision(A, 1)
algisdivision(A, 2)
algisdivision(A, idealprimedec(nf,2)[1])
algisdivision(A, idealprimedec(nf,5)[1])
algisdivision(A)
algissplit(A, 1)
algissplit(A, 2)
algissplit(A, idealprimedec(nf,2)[1])
algissplit(A, idealprimedec(nf,5)[1])
algissplit(A)
algisramified(A, 1)
algisramified(A, 2)
algisramified(A, idealprimedec(nf,2)[1])
algisramified(A, idealprimedec(nf,5)[1])
algisramified(A)
algramifiedplaces(A)

nf = nfinit(y^2-5);
pr = idealprimedec(nf,13)[1];
pol = nfgrunwaldwang(nf, [pr], [2], [0,-1], 'x)


A = alginit(nfinit(y), [-1,-1]);
alginvbasis(A)
algbasis(A)
algmultable(A)
alginv(A,[1,1,0,0]~)
algmul(A,[1,1,0,0]~,[0,0,2,1]~)
algtomatrix(A,[0,1,0,0]~,1)
algtomatrix(A,[0,x]~,1)
algneg(A,[1,1,0,0]~)
algtomatrix(A,[0,0,0,2]~)
algpow(A,[1,1,0,0]~,7)
algsub(A,[1,1,0,0]~,[1,0,1,0]~)
algtrace(A,[5,0,0,1]~)
algtrace(A,[5,0,0,1]~,1)
algtype(A)

nf = nfinit(y^3-5);
a = y; b = y^2;
mt = qamt(a,b);
A = alginit(nf,mt,'x);
algrelmultable(A)
algsplittingfield(A).pol
algsplittingdata(A)
algtype(A)

mt = [matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
A = algtableinit(mt,19);
algnorm(A,[0,-2,3]~)
A = algtableinit(mt);
algnorm(A,[0,-2,3]~)

m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0];
m_k=[0,0,0,-1;0,0,-1,0;0,1,0,0;1,0,0,0];
mt = [matid(4), m_i, m_j, m_k];
A = algtableinit(mt);
algissemisimple(A)
algissimple(A)
algissimple(A,1)
\\end examples






print("matrices over algebras");
scal8(a) = vector(8,i,if(i==1,a,0))~;
setrand(1);
nf = nfinit(y^2-5);
al = alginit(nf, [-1,-7]);
setrand(1);
M1 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)]
M2 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)]
print("mul alM: ", algmul(al,M1,M2));
a = [1,2,3,4,5,6,7,8]~; M = Mat([0,0]); M[1,1] = a; M[1,2] = a;
algmul(al, M, [a,a,a;a,a,a]);
print("sqr alM: ", algsqr(al,M1) == algmul(al,M1,M1));
print("divl alM: ", algmul(al,M1,algdivl(al,M1,M2)) == M2);
print("divr alM: ", algmul(al,algdivr(al,M1,M2),M2) == M1);
print("isinv alM: ", algisinv(al, M1));
print("isinv alM 2: ", algisinv(al, M2));
un = [1,0,0,0,0,0,0,0]~; zero = [0,0,0,0,0,0,0,0]~; id = [un,zero;zero,un];
{print("inv alM: ", algmul(al,M1,alginv(al,M1)) == id &&
 algmul(al,alginv(al,M1),M1) == id);}
{print("inv alM 2: ", algmul(al,M2,alginv(al,M2)) == id &&
 algmul(al,alginv(al,M2),M2) == id);}
print("neg alM: ", algneg(al,M1) == -M1);
print("sub alM: ", algsub(al,M1,M2) == M1-M2);
print("add alM: ", algadd(al,M1,M2) == M1+M2);
print("algtobasis basistoalg alM 1: ", algalgtobasis(al, algbasistoalg(al, M1)) ==
 M1);
print("algtobasis basistoalg alM 2: ", algalgtobasis(al, algbasistoalg(al, M2)) ==
 M2);
print("algleftmultable add alM: ", algtomatrix(al, M1,1)+algtomatrix(al,M2,1) == algtomatrix(al, algadd(al, M1, M2),1));
print("algleftmultable mul alM: ", algtomatrix(al, M1,1)*algtomatrix(al,M2,1) == algtomatrix(al, algmul(al, M1, M2),1));
{print("algleftmultable sqr alM: ", algtomatrix(al, M1,1)^2 == algtomatrix(al, algsqr(al, M1),1));}
print("algsplitm add alM: ", algtomatrix(al, M1)+algtomatrix(al,M2) ==
 algtomatrix(al, algadd(al, M1, M2)));
print("algsplitm mul alM: ", algtomatrix(al, M1)*algtomatrix(al,M2) ==
 algtomatrix(al, algmul(al, M1, M2)));
print("algsplitm sqr alM: ", algtomatrix(al, M1)^2 ==
 algtomatrix(al, algsqr(al, M1)));
print("algsplitm sqr alM 2: ", algtomatrix(al, M2)^2 ==
 algtomatrix(al, algsqr(al, M2)));
{print("algtrace alM: ", algtrace(al,M1) == algtrace(al,M1[1,1]) +
 algtrace(al,M1[2,2]));}
{print("algtrace alM 2: ", algtrace(al,M2) == algtrace(al,M2[1,1]) +
 algtrace(al,M2[2,2]));}
{print("algtrace abs alM: ", algtrace(al,M1,1) == 2*(algtrace(al,M1[1,1],1) +
 algtrace(al,M1[2,2],1)));}
{print("algtrace abs alM 2: ", algtrace(al,M2,1) == 2*(algtrace(al,M2[1,1],1) +
 algtrace(al,M2[2,2],1)));}
{print("algtrace prod alM: ", algtrace(al, algmul(al,M1,M2)) == algtrace(al,
algmul(al,M2,M1)));}
{print("algnorm alM: ", algnorm(al,algmul(al,M1,M2)) == algnorm(al,M1) *
 algnorm(al,M2));}
{print("algnorm alM 2: ", algnorm(al,algmul(al,M2,M1)) == algnorm(al,M1) *
 algnorm(al,M2));}
{print("algcharpoly alM: ", poldegree(algcharpoly(al,M1))==4 &&
 polcoeff(algcharpoly(al,M1),3) == -algtrace(al,M1) &&
 polcoeff(algcharpoly(al,M1),0) == algnorm(al,M1));}
{print("algcharpoly alM 2: ", poldegree(algcharpoly(al,M2))==4 &&
 polcoeff(algcharpoly(al,M2),3) == -algtrace(al,M2) &&
 polcoeff(algcharpoly(al,M2),0) == algnorm(al,M2));}
m = 15; n = -8;
{print("pow alM: ", algmul(al, algpow(al,M1,m), algpow(al,M1,n)) ==
 algpow(al,M1,m+n));}
{print("pow alM 2: ", algmul(al, algpow(al,M2,m), algpow(al,M2,n)) ==
 algpow(al,M2,m+n));}
print("pow 0 alM: ", algpow(al,M1,0) == id);
algbasistoalg(al,M1)
algbasistoalg(al,M2)
m1 = [1,2;3,4];
m2 = [5,6;7,8];
M1 = apply(scal8,m1);
M2 = apply(scal8,m2);
print("mul scalar alM: ", algmul(al,M1,M2) == apply(scal8,m1*m2));

m_i=[0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
m_j=[0,0,-1,0;0,0,0,1;1,0,0,0;0,-1,0,0];
m_k=[0,0,0,-1;0,0,-1,0;0,1,0,0;1,0,0,0];
mt = [matid(4), m_i, m_j, m_k];
al = algtableinit(mt);
setrand(10);
M1 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)]
M2 = [algrandom(al,2),algrandom(al,2);algrandom(al,2),algrandom(al,2)]
print("mul alM t: ", algmul(al,M1,M2));
print("sqr alM t: ", algsqr(al,M1) == algmul(al,M1,M1));
print("divl alM t: ", algmul(al,M1,algdivl(al,M1,M2)) == M2);
print("divr alM t: ", algmul(al,algdivr(al,M1,M2),M2) == M1);
print("isinv alM t: ", algisinv(al, M1));
print("isinv alM t 2: ", algisinv(al, M2));
un = [1,0,0,0]~; zero = [0,0,0,0]~; id = [un,zero;zero,un];
{print("inv alM t: ", algmul(al,M1,alginv(al,M1)) == id &&
 algmul(al,alginv(al,M1),M1) == id);}
{print("inv alM t 2: ", algmul(al,M2,alginv(al,M2)) == id &&
 algmul(al,alginv(al,M2),M2) == id);}
print("neg alM t: ", algneg(al,M1) == -M1);
print("sub alM t: ", algsub(al,M1,M2) == M1-M2);
print("add alM t: ", algadd(al,M1,M2) == M1+M2);
print("algleftmultable add alM t: ", algtomatrix(al,M1,1) + algtomatrix(al,M2,1) == algtomatrix(al, algadd(al,M1,M2),1));
print("algleftmultable mul alM t: ", algtomatrix(al,M1,1) * algtomatrix(al,M2,1) == algtomatrix(al, algmul(al,M1,M2),1));
print("algleftmultable sqr alM t: ", algtomatrix(al,M1,1)^2 == algtomatrix(al,algsqr(al,M1),1));
{print("algtrace alM t: ", algtrace(al,M1) == 2*(algtrace(al,M1[1,1]) +
 algtrace(al,M1[2,2])));}
{print("algtrace alM t 2: ", algtrace(al,M2) == 2*(algtrace(al,M2[1,1]) +
 algtrace(al,M2[2,2])));}
{print("algtrace prod alM t: ", algtrace(al, algmul(al,M1,M2)) == algtrace(al,
algmul(al,M2,M1)));}
{print("algnorm alM t: ", algnorm(al,algmul(al,M1,M2)) == algnorm(al,M1) *
 algnorm(al,M2));}
{print("algnorm alM t 2: ", algnorm(al,algmul(al,M2,M1)) == algnorm(al,M1) *
 algnorm(al,M2));}
{print("algcharpoly alM t: ", poldegree(algcharpoly(al,M1))==16 &&
 polcoeff(algcharpoly(al,M1),15) == -algtrace(al,M1) &&
 polcoeff(algcharpoly(al,M1),0) == algnorm(al,M1));}
{print("algcharpoly alM t 2: ", poldegree(algcharpoly(al,M2))==16 &&
 polcoeff(algcharpoly(al,M2),15) == -algtrace(al,M2) &&
 polcoeff(algcharpoly(al,M2),0) == algnorm(al,M2));}
m = 32; n = -63;
{print("pow alM t: ", algmul(al, algpow(al,M1,m), algpow(al,M1,n)) ==
 algpow(al,M1,m+n));}
{print("pow alM 2 t: ", algmul(al, algpow(al,M2,m), algpow(al,M2,n)) ==
 algpow(al,M2,m+n));}
print("pow 0 alM t: ", algpow(al,M2,0) == id);



T = y^3-y+1;
nf = nfinit(T);
print("csa al2");
setrand(1);
al2 = alginit(nf, matrixringmt(2), 'x);
print("al2 contains nfabs: ", algsplittingfield(al2)[12][1] != 0);
al2b = al2; al2b[1][12][1] = 0; \\ depends on 32/64bit
print(al2b);
print("csa al3");
al3 = alginit(nf, matrixringmt(3), 'x);
print("al3 contains nfabs: ", algsplittingfield(al3)[12][1] != 0);

\\limit cases
print("trivial algebra over a quadratic field");
al = alginit(rnfinit(nfinit(y^2+1),x),[y,1])
a = [y]~
b = [1-2*y]~
c = [-3,1]~
algadd(al,a,b)
algsub(al,c,a)
algmul(al,a,b)
algdivl(al,b,c)
algdivr(al,c,b)
alginv(al,a)
algalgtobasis(al,b)
algtomatrix(al,a)
algtomatrix(al,a,1)
algcharpoly(al,b)
algtrace(al,c)
algtrace(al,c,1) == trace(trace(algbasistoalg(al,c)[1]))
algnorm(al,c)
algiscommutative(al)
algissemisimple(al)
algissimple(al)
alghasse(al,1)
alghasse(al,idealprimedec(nfinit(y^2+1),2)[1])
algindex(al)
algisdivision(al)
algissplit(al)
algisramified(al)
algramifiedplaces(al)


print("trivial algebra over Q");
al = alginit(rnfinit(nfinit(y),x),[y,1])
a = [-2]~
b = [1/3]~
c = [4/5]~
algadd(al,a,b)
algsub(al,c,a)
algmul(al,a,b)
algdivl(al,b,c)
algdivr(al,c,b)
alginv(al,a)
algalgtobasis(al,b)
algtomatrix(al,a,1)
algtomatrix(al,b)
algcharpoly(al,b)
algtrace(al,c)
algtrace(al,c,1)
algnorm(al,c)
algiscommutative(al)
algissemisimple(al)
algissimple(al)
alghasse(al,1)
alghasse(al,idealprimedec(nfinit(y),2)[1])
algindex(al)
algisdivision(al)
algissplit(al)
algisramified(al)
algramifiedplaces(al)

print("trivial CSA over Q");
al = alginit(nfinit(y), [Mat(1)]);
algsqr(al,[Mod(3,y)]~)
algsqr(al,[2]~)
print("nontrivial CSA over Q");
{m_i = [0,-1,0, 0;
       1, 0,0, 0;
       0, 0,0,-1;
       0, 0,1, 0];
m_j = [0, 0,-1,0;
       0, 0, 0,1;
       1, 0, 0,0;
       0,-1, 0,0];
m_k = [0, 0, 0, -1;
       0, 0,-1, 0;
       0, 1, 0, 0;
       1, 0, 0, 0];
mt = [matid(4), m_i, m_j, m_k];}
al = alginit(nfinit(y), mt);
algsqr(al,[Mod(3,y),Mod(2,y),Mod(1,y),Mod(2,y)]~)
algsqr(al,[2,3,4,5]~)

print("empty matrices");
al = alginit(nfinit(y), [-1,-1]);
print("-v: ", algneg(al,[;]) == [;]);
print("v^(-1): ", alginv(al,[;]) == [;]);
print("v^n: ", algpow(al, [;], 13) == [;]);
print("v^0: ", algpow(al, [;], 0) == [;]);
print("mt(v)", algtomatrix(al, [;], 1) == [;]);
print("spl(v)", algtomatrix(al, [;]) == [;]);
print("trace(v): ", algtrace(al, [;]) == 0);
print("trace abs(v): ", algtrace(al, [;], 1) == 0);
print("norm(v): ", algnorm(al, [;]) == 1);
print("charpoly(v): ", algcharpoly(al, [;]) == 1 && type(algcharpoly(al,[;])) == "t_POL");
print("v+v: ", algadd(al,[;],[;]) == [;]);
print("v-v: ", algsub(al,[;],[;]) == [;]);
print("v*v: ", algmul(al,[;],[;]) == [;]);
print("v/v: ", algdivr(al,[;],[;]) == [;]);
print("v\\v: ", algdivl(al,[;],[;]) == [;]);
v1 = matrix(0,1);
print("v*nv: ", algmul(al,v1,matid(1))==v1);
print("v*v 2: ", algmul(al,[;],matrix(0,1))==matrix(0,1));
print("trace(v) char 2: ", algtrace(algtableinit([matid(1)],2), [;]) == 0);

mt0 = [Mat([1])];
almt0 = algtableinit(mt0,0)
a = [12]~
b = [-1/7]~
algadd(almt0,a,b)
algsub(almt0,a,b)
algmul(almt0,a,b)
algneg(almt0,a)
alginv(almt0,a)
algsqr(almt0,b)
algdivl(almt0,a,b)
algtrace(almt0,a)
algtrace(almt0,a,1)
algnorm(almt0,b)
algcharpoly(almt0,a)
algtomatrix(almt0,b,1)
algpow(almt0,a,0)
algiscommutative(almt0)
algissemisimple(almt0)
algissimple(almt0)
algisdivision(almt0)


print("trivial tensor product");
al1 = alginit(nfinit(y),1);
al2 = alginit(nfinit(y),2);
print(algtensor(al1,al2)==al2);
print(algtensor(al2,al1)==al2);

print("splitting a nasty commutative algebra");
{mt = [matid(8),
[0,2,0,0,0,0,0,0;
 1,0,0,0,0,0,0,0;
 0,0,0,2,0,0,0,0;
 0,0,1,0,0,0,0,0;
 0,0,0,0,0,2,0,0;
 0,0,0,0,1,0,0,0;
 0,0,0,0,0,0,0,2;
 0,0,0,0,0,0,1,0],

[0,0,3,0,0,0,0,0;
 0,0,0,3,0,0,0,0;
 1,0,0,0,0,0,0,0;
 0,1,0,0,0,0,0,0;
 0,0,0,0,0,0,3,0;
 0,0,0,0,0,0,0,3;
 0,0,0,0,1,0,0,0;
 0,0,0,0,0,1,0,0],

[0,0,0,6,0,0,0,0;
 0,0,3,0,0,0,0,0;
 0,2,0,0,0,0,0,0;
 1,0,0,0,0,0,0,0;
 0,0,0,0,0,0,0,6;
 0,0,0,0,0,0,3,0;
 0,0,0,0,0,2,0,0;
 0,0,0,0,1,0,0,0],

[0,0,0,0,5,0,0,0;
 0,0,0,0,0,5,0,0;
 0,0,0,0,0,0,5,0;
 0,0,0,0,0,0,0,5;
 1,0,0,0,0,0,0,0;
 0,1,0,0,0,0,0,0;
 0,0,1,0,0,0,0,0;
 0,0,0,1,0,0,0,0],

[0,0,0,0,0,10,0, 0;
 0,0,0,0,5, 0,0, 0;
 0,0,0,0,0, 0,0,10;
 0,0,0,0,0, 0,5, 0;
 0,2,0,0,0, 0,0, 0;
 1,0,0,0,0, 0,0, 0;
 0,0,0,2,0, 0,0, 0;
 0,0,1,0,0, 0,0, 0],

[0,0,0,0,0,0,15, 0;
 0,0,0,0,0,0, 0,15;
 0,0,0,0,5,0, 0, 0;
 0,0,0,0,0,5, 0, 0;
 0,0,3,0,0,0, 0, 0;
 0,0,0,3,0,0, 0, 0;
 1,0,0,0,0,0, 0, 0;
 0,1,0,0,0,0, 0, 0],

[0,0,0,0,0, 0, 0,30;
 0,0,0,0,0, 0,15, 0;
 0,0,0,0,0,10, 0, 0;
 0,0,0,0,5, 0, 0, 0;
 0,0,0,6,0, 0, 0, 0;
 0,0,3,0,0, 0, 0, 0;
 0,2,0,0,0, 0, 0, 0;
 1,0,0,0,0, 0, 0, 0]
];}
{chg =
[1, 0,0,0,0,0, 0, 0;
 0, 1,0,0,0,0, 0, 0;
 0,-2,1,1,0,0, 0, 0;
 0,-1,0,1,0,0, 0, 0;
 0, 0,0,0,1,1,-2, 0;
 0, 0,0,0,0,1, 0,-1;
 0, 0,0,0,0,0, 1, 0;
 0, 0,0,0,0,0, 0, 1];}
chgi = chg^(-1);
mt2 = vector(8,j,chgi*sum(i=1,8,chg[i,j]*mt[i])*chg);
algisassociative(mt2)
al = algtableinit(mt2);
algiscommutative(al)
algissemisimple(al)
setrand(9991);
algissimple(al,1)

print("non associative algebra");
mt = [matid(3), [0,2,3;1,4,5;0,6,7], [0,8,9;0,10,11;1,12,13]];
algisassociative(mt)

print("csa without maximal order");
alginit(nfinit(y), [matid(1)], 'x, 0);

print("simplify bug #1671");
test(str,al)={
 my(sal = simplify(al), x, y);
 setrand(1);
 print("testing simplify: ", str);
 print(algtype(al) == algtype(sal));
 print(algdim(al) == algdim(sal));
 setrand(11);
 x = algrandom(al,3);
 y = algrandom(al,10);
 print(algsqr(al,x) == algsqr(sal,x));
 print(algtomatrix(al,x) == algtomatrix(sal,x));
 print(algcharpoly(al,x) == algcharpoly(sal,x));
 print(algnorm(al,x) == algnorm(sal,x));
 print(algtomatrix(al,x,1) == algtomatrix(sal,x,1));
 print(algtrace(al,x) == algtrace(sal,x));
 print(algtrace(al,x,1) == algtrace(sal,x,1));
 print(alginv(al,x) == alginv(sal,x));
 print(algpow(al,x,42) == algpow(sal,x,42));
 print(algmul(al,x,y) == algmul(sal,x,y));
 print(algdivl(al,x,y) == algdivl(sal,x,y));
 print(algpoleval(al,algcharpoly(al,x),x) == 0);
 print(algpoleval(al,algcharpoly(al,y),y) == 0);

 print(algbasistoalg(al,x) == algbasistoalg(sal,x));
 x = algbasistoalg(al,x);
 print(algbasistoalg(al,y) == algbasistoalg(sal,y));
 y = algbasistoalg(al,y);
 print(algsqr(al,x) == algsqr(sal,x));
 print(algtomatrix(al,x) == algtomatrix(sal,x));
 print(algcharpoly(al,x) == algcharpoly(sal,x));
 print(algnorm(al,x) == algnorm(sal,x));
 print(algtomatrix(al,x,1) == algtomatrix(sal,x,1));
 print(algtrace(al,x) == algtrace(sal,x));
 print(algtrace(al,x,1) == algtrace(sal,x,1));
 print(alginv(al,x) == alginv(sal,x));
 print(algpow(al,x,42) == algpow(sal,x,42));
 print(algmul(al,x,y) == algmul(sal,x,y));
 print(algdivl(al,x,y) == algdivl(sal,x,y));

 print(algadd(al,x,y) == algadd(al,x,simplify(y)));
 print(algmul(al,x,y) == algmul(al,x,simplify(y)));
 print(algmul(al,x,y) == algmul(al,simplify(x),simplify(y)));
};
test("degree 1 cyclic over Q", alginit(nfinit(y),1));
test("degree 1 cyclic over Q(i)", alginit(nfinit(y^2+1),1));
test("degree 1 csa over Q", alginit(nfinit(y), [matid(1)]));
test("degree 1 csa over Q(i)", alginit(nfinit(y^2+1), [matid(1)]));
test("quatalg over Q(s5)", alginit(nfinit(y^2-5), [-2,-3]));
{m_i = [0,-1,0, 0;
       1, 0,0, 0;
       0, 0,0,-1;
       0, 0,1, 0];
m_j = [0, 0,-1,0;
       0, 0, 0,1;
       1, 0, 0,0;
       0,-1, 0,0];
m_k = [0, 0, 0, -1;
       0, 0,-1, 0;
       0, 1, 0, 0;
       1, 0, 0, 0];
mt = [matid(4), m_i, m_j, m_k];}
test("quatalg csa over Q", alginit(nfinit(y), mt));

m = matcompanion(x^4+1);
mt = [m^i | i <- [0..3]];
al = algtableinit(mt);
B = [1,0;0,0;0,1/2;0,0]
al2 = algsubalg(al,B);

print("algpoleval relative poly in basis form");
pol = y^2-2;
nf = nfinit(pol);
a = 1+y;
b = -3-y;
al = alginit(nf, [a,b]);
ii = algalgtobasis(al,[x,0]~);
algpoleval(al, x^2-a, ii) == 0
jj = algalgtobasis(al,[0,1]~);
algpoleval(al, x^2-b, jj) == 0
kk = algalgtobasis(al,[0,-x]~);
algpoleval(al, x^2+Mod(a,pol)*b, kk) == 0
w = algrandom(al,10);
T = x^3 + 7*x^2 - y^5*x + (8-2*y);
{algpoleval(al,T,w) == algpow(al,w,3) + 7*algsqr(al,w) -
 algmul(al,algeltfromnf(al,y^5),w) + algeltfromnf(al,8-2*y)}
al = alginit(nf, qamt(a,b));
ii = algalgtobasis(al,[0,1,0,0]~);
algpoleval(al, x^2-a, ii) == 0
jj = algalgtobasis(al,[0,0,1,0]~);
algpoleval(al, x^2-b, jj) == 0
kk = algalgtobasis(al,[0,0,0,1]~);
algpoleval(al, x^2+Mod(a,pol)*b, kk) == 0
{algpoleval(al,T,w) == algpow(al,w,3) + 7*algsqr(al,w) -
 algmul(al,algeltfromnf(al,y^5),w) + algeltfromnf(al,8-2*y)}

print("doc algpoleval");
nf = nfinit(y^2-5);
al = alginit(nf,[y,-1]);
b = [1..8]~;
pol = algcharpoly(al,b,,1); \\absolute characteristic polynomial
algpoleval(al,pol,b)==0
mb = algtomatrix(al,b,1);
algpoleval(al,pol,[b,mb])==0
pol = algcharpoly(al,b); \\reduced characteristic polynomial
algpoleval(al,pol,b) == 0
exponent(algpoleval(,polcyclo(8),[1,0,0,1]~/sqrt(2))) < -100

print("splitting field bug for CSA");
setrand(1);
pol = y^2-2;
nf = nfinit(pol);
a = (3+y)^2;
b = -y-7;
al = alginit(nf, qamt(a,b));
ii = [0,1,0,0]~;
algnorm(al,ii) == -Mod(a,pol)
algtomatrix(al,algeltfromnf(al,y)) == Mod(y,pol)*matid(2)
rnf = algsplittingfield(al);
spld = algsplittingdata(al);
t = spld[1];
algpoleval(al, minpoly(rnfeltabstorel(rnf,x)), t) == 0




\\ bad inputs
a = [12]~;
b = [-1/7]~;
m_i = [0,-1,0, 0;\
       1, 0,0, 0;\
       0, 0,0,-1;\
       0, 0,1, 0];
m_j = [0, 0,-1,0;\
       0, 0, 0,1;\
       1, 0, 0,0;\
       0,-1, 0,0];
m_k = [0, 0, 0, -1;\
       0, 0,-1, 0;\
       0, 1, 0, 0;\
       1, 0, 0, 0];
mt = [matid(4), m_i, m_j, m_k];
almt = algtableinit(mt,0);
algsplittingfield(almt);
algdegree(almt);
alghassei(almt);
alghassef(almt);
algrandom(1,1)
algrandom(almt,I)
algtype(1)
algdim([1,[1],0,0,0,0,0,0,0,0])
algdim([1,[1],0,0,0,0,0,0,0,0],1)
algtensor(al,al2)
algtensor(al2,al)
algtensor(1,z,1)
algisassociative([1],0)
algisassociative([[1,0;0,2],[0,0;0,0]]) \\valid input
algmul(almt,a,b)
algtomatrix(almt,a,1)
alginv(almt,a)
algalgtobasis(almt,a)
algbasistoalg(almt,[0,0,0,0]~)
algpoleval(almt,1,a)
zero = [0,0,0,0]~; m = Mat([1,1]); m[1,1]=zero; m[1,2]=zero;
algadd(almt, [zero;zero], m)
algadd(almt, [zero;zero;zero], [zero;zero]);
algsub(almt, [zero;zero], m)
algsub(almt, [zero;zero;zero], [zero;zero]);
algmul(almt, m, [zero;zero;zero]);
algsqr(almt, [zero;zero]);
algdivl(almt, m, zero);
algdivl(almt, Mat([[zero]~]), [zero,zero;zero,zero]);
algdivl(almt, m, m);
alginv(almt, m);
algtomatrix(almt,m,1);
algpow(almt, m, 3);
algtrace(almt, m);
algcharpoly(almt, m);
algcharpoly(alginit(nfinit(y),[-1,-1]), m);
algnorm(almt, m);
algnorm(alginit(nfinit(y),[-1,-1]), m);
alginit(nfinit(y),[2,[[],[]],[x]])
alginit(nfinit(y),[2,[],[1,1]])
alginit(nfinit(y),[2,[[],[]],Vecsmall([1])])
alginit(y,[2,[[],[]],[1]])
alginit(nfinit(y), y)
alginit(nfinit(y), [1,2,3,4])
algtableinit(mt,y);
alginit(nfinit(y^2+1),-3);
alginit(nfinit(x^2+1),3);
highvar = varhigher("highvar");
alginit(nfinit(highvar^2+1),3);
al = alginit(nfinit(y^2-2),[-1,-1]); algrandom(al,-10)
al = alginit(nfinit(y^2-2),[-1,-1]);
algrelmultable(al);
algsplittingdata(al);
alghasse(almt, 1);
algindex(almt, 1);
algisdivision(almt);
algissplit(almt);
algisramified(almt);
algramifiedplaces(almt);
alghasse(al);
alghasse(al, -1);
alghasse(al, 3);
alghasse(al, 2^100);
alghasse(al, []);
alghasse(al, 1/3);
algtableinit([matid(2), [0,1/2;1,0]]);
Q = nfinit(y);
alginit(Q, [matid(2), [0,1/2;1,0]]);
alginit(Q, [-1/2, -1]);
alginit(Q, [-1, -1/2]);
alginit(rnfinit(Q, x^2+1), [-x,-1/2]);
algsqr([0,0,0,0,0,0,0,0,0,0,0],[]~);
algsqr([0,0,0,0,0,0,0,0,[],0,0],[]~);
algsqr([0,0,0,0,0,0,0,0,[0],0,0],[]~);
algsqr([0,0,0,0,0,0,0,0,[[;]],0,0],[]~);
algsqr([[],0,0,0,0,0,0,0,[[;]],0,0],[]~);
algsqr([[],[0],0,0,0,0,0,0,[[;]],0,0],[]~);
algdim([[],[0],0,0,0,0,0,0,[[;]],0,0]);
algdegree([[],[0],0,0,0,0,0,0,[[;]],0,0]);
algdegree([rnfinit(nfinit(y),x),[[]],0,0,0,0,0,0,[[;]],0,0]);
algcenter([rnfinit(nfinit(y),x),[[]],0,0,0,0,0,0,[[;]],0,0]);
algcentralproj(almt,0);
algcentralproj(almt,[zero,zero]);
algsubalg(almt,0);
algisassociative([]);
algisassociative([matid(2),Mat([1,1])]);
algisassociative([[1,2;3,4],matid(2)]) \\valid input
algisassociative([matid(1)],[]);
algsqr(algtableinit([matid(1)]),[1,2]~);
algsqr(al,vector(691)~);
algsqr(al,[1,2,3,4,5,6,7,f^2]~);
algsqr(al,[f^3,[]]~);
algmul(al,[;],[1,2]~);
algdivl(al,[;],matid(1));
algdivl(al,matid(1),matrix(1,2));
algdivl(al,matrix(0,3),[;]);
algdivl(al,[;],matrix(0,3));
algdivl(al,matrix(1,1),[;]);
alginv(al,[0,0]~);
al0mt = algtableinit([matid(1)]);
algalgtobasis(al0mt,[1]~);
algbasistoalg(al0mt,[1]~);
nfgrunwaldwang(nfinit(y),0,[],[],'x);
nfgrunwaldwang(nfinit(y),[2],'x-'x,[1]);
alginit(rnfinit(nfinit(y),x),0);
alginit(rnfinit(nfinit(y),x),[1,2,3,4]);
alginit(nfinit(y), [matid(2),matid(2)]);
alginit(nfinit(y), [matid(2),[0,1;1,0]]);

nfgrunwaldwang(nfinit(y), 0, [], [0]);
nfgrunwaldwang(nfinit(y), [2], [], [0]);
nfgrunwaldwang(nfinit(y), [2], [2], []);
nfgrunwaldwang(nfinit(y), [2], [6], [0]);
nfgrunwaldwang(nfinit(y), [2,3], [2,3], [0]);
nfgrunwaldwang(nfinit(y), [2], [3], [-1]);
nfgrunwaldwang(nfinit(y), [[]~], [3], [-1]);
nfgrunwaldwang(nfinit(y), [2], [9], [0]);

mt=[matid(3), [0,0,0; 1,1,0; 0,0,0], [0,0,1; 0,0,0; 1,0,1]];
A=algtableinit(mt,2);
algdegree(A)
algsub(A,1,1)
algadd(A,1,1)
algneg(A,1)
algmul(A,1,1)
algsqr(A,1)
algdivl(A,1,1)
algdivr(A,1,1)
alginv(A,1)
a='a;
K=nfinit(a);PR=idealprimedec(K,2);A=alginit(K,[3,[PR,[1]],[-1]]);
K=nfinit(a);P2=idealprimedec(K,2);P3=idealprimedec(K,3);A=alginit(K,[3,[concat(P2,P3),[1/3,-2/3]],[1/3]]);
algtensor(alginit(nfinit(y),2),alginit(nfinit(y^2+1),3));
algtensor(alginit(nfinit(y),2),alginit(nfinit(y),2));
nf = nfinit(y); p2 = idealprimedec(nf,2)[1]; p3 = idealprimedec(nf,3)[1];
\\alginit(nf, [2, [[p2,p3],[1/2,1/2]], [0]]);
alginit(nf, [2, [[p2,p2],[1/2,1/2]], [0]]);
alginit(nf, [2, [[p2,p3],[1/2,1/2]], [0,0]]);
alginit(nf, [2, [[p2,p3],[1/2,1/2],0], [0]]);
alginit(nf, [2, [0,[1/2,1/2]], [0]]);
alginit(nf, [2, [[p2,p3],0], [0]]);
alginit(nf, [2, [[p2,p3],[1/2,1/2,0]], [0]]);
alginit(nf, [2, [[p2,p3],[1/2,1/2]], [1/3]]);

al = alginit(nfinit(y),[-1,-1]);
setrand(23);
a = algrandom(al,2);
algcharpoly(al,a,'z);

al = alginit(nfinit(y^2+7), [-1,-1]);
algcharpoly(al,[1,2,3]~);

algindex(1, 1)

al = alginit(nfinit(y), [Mat(1)]);
algsqr(al,[Mod(1,y),Mod(2,y)]~)
{m_i = [0,-1,0, 0;
       1, 0,0, 0;
       0, 0,0,-1;
       0, 0,1, 0];
m_j = [0, 0,-1,0;
       0, 0, 0,1;
       1, 0, 0,0;
       0,-1, 0,0];
m_k = [0, 0, 0, -1;
       0, 0,-1, 0;
       0, 1, 0, 0;
       1, 0, 0, 0];
mt = [matid(4), m_i, m_j, m_k];}
al = alginit(nfinit(y), mt);
algsqr(al,[Mod(1,y),Mod(2,y)]~)

alfail = alginit(nf, [0,-12345], 'x);
alfail = alginit(nf, [-12345,0], 'x);
algb(al);
algaut(al);
algtableinit([Mat(1)],1)
algtableinit([Mat(1)],4)
al = alginit(nfinit(y),[-1,-1]);
algpoleval(al,x+1,"toto")
algpoleval(al,x+1,[1,2,3])
algpoleval(al,x+1,[1,2])
a = [1..4]~;
b = [5..8]~;
mb = algtomatrix(al,b,1);
algpoleval(al,x+1,[a,mb]);
algpoleval(al,x+1,[1,mb]);
alginit(nfinit(y),["a",[[],[]],[]]);
alginit(nfinit(y),[1,[[],[]],[]]);
alginit(nfinit(y),[0,[[],[]],[]]);
algrandom(,1);
algrandom(,-1.);
algneg(,[1..4]);
algneg(,Mod(1,2));
algneg(,[1..5]~);
algneg(,[1,2,3,I]~);
algadd(,1,[]~);
algadd(,O(3^3),I);
algadd(,I,[1;2]);
algadd(,Mat([1,2]),[3;4]);
algadd(,Mat(1),Mat(O(3)));
algadd(,I,Mat(2));
algtrace(,O(x^2));
algtrace(,[[1..4]~;[2..5]~]);
algtomatrix(,1+I*'x);
algmul(,[1,2,3,4]~,'x);
algmul(,'y,I);
algmul(,[1,2;3,4],1+I);
algsqr(,O(3^3));
algnorm(,Mod(1,2));
algcharpoly(,sin);
alginv(,'x);
alginv(,0);
algdivl(,'x,1);
algdivl(,[1,2,3,4]~,'y);
algdivl(,0,1);
algdivl(,[;],1);
algdivl(,[1,2,3,4]~,[;]);
algdivl(,[1;2],Pi);
algpoleval(,'x,'x);
algpoleval(,'x,[1,2;3,4]);
algpoleval(,O(3),[1,2,3,4]~)
algdivl(,matrix(0,3),[;]);
algdivl(,[;],matrix(0,3));
algdivl(,matrix(1,1),[;]);
H = alginit(1.,1/2);
R = alginit(1.,0);
C = alginit(I,0);
algramifiedplaces(H);
H0 = H; H0[1] = O(2); algrandom(H0,1.);
algsqr(H,[]~);
algsqr(H,O(x));
algalgtobasis(H,1);
algbasistoalg(H,1);
algcentralproj(H,[1]);
algcharpoly(R,[1,2,3,4]~)
algcharpoly(C,[1,2,3,4]~)
algdisc(R)
algdisc(C)
algdisc(H)
algdivl(C,[;],1)
algdivl(C,[1,2,3,4]~,[1,2,3,4]~)
algdivl(C,matrix(2,1),matrix(1,1))
algdivl(C,matrix(2,2),matrix(3,3))
alginit(1.,1);
alginv(C,[1..4]~);
alginv(C,0);
alglatadd(H,[matid(4),1],[matid(4),1]);
alglatcontains(H,[matid(4),1],[1..4]~);
alglatelement(H,[matid(4),1],[1..4]~);
alglathnf(H,matid(4));
alglatindex(H,[matid(4),1],[matid(4),1]);
alglatinter(H,[matid(4),1],[matid(4),1]);
alglatlefttransporter(H,[matid(4),1],[matid(4),1]);
alglatmul(H,[matid(4),1],[matid(4),1]);
alglatrighttransporter(H,[matid(4),1],[matid(4),1]);
alglatsubset(H,[matid(4),1],[matid(4),1]);
algnorm(R,[1..4]~);
algnorm(C,[1..4]~);
algquotient(H,[;]);
algrelmultable(H);
algsplittingdata(H);
algsubalg(H,[1;0;0;0]);
algtableinit(H);
algtensor(H,H);
algtomatrix(R,[1,2,3,4]~);
algtomatrix(C,[1,2,3,4]~);
algtrace(R,[1,2,3,4]~);
algtrace(C,[1,2,3,4]~);
H0 = H; H0[9] = concat(H0[9],[matid(4)]);
algtrace(H0,1);
algnorm(H0,1);
algcharpoly(H0,1);
algtomatrix(H0,1);
alginv(H0,1);
algdim(H0);
algrandom(H0,1.);
al = alginit(nfinit(y),[-1,-1]);
al[2][1] = O(x);
algdim(al);
algdim(al,1);
al = alginit(nfinit(y^2+1), algmultable(al));
algsqr(al,[1..20]~);
al = alginit(nfinit(y),1);
algsqr(al,[O(x)]~);
\\end bad inputs


print("new algsimpledec");
\\ K^3
mt = [matid(3),[0,0,0;1,1,0;0,0,0],[0,0,0;0,0,0;1,0,1]];
al = algtableinit(mt);
algissimple(al)
setrand(1);
algsimpledec(al,1)
al2 = algtableinit(mt,5);
algissimple(al2)
setrand(2);
algsimpledec(al2,1)
\\ upper-tri in M2(K)
mt = [matid(3),[0,0,0;1,1,0;0,0,1],[0,0,0;0,0,0;1,0,0]];
al = algtableinit(mt);
setrand(1);
algsimpledec(al,1)
al2 = algtableinit(mt,5);
setrand(1);
algsimpledec(al2,1)

print("norm(,1)");
nf = nfinit(y^2-5);
B = alginit(nf,[-1,y]);
b = [x,1]~;
algnorm(B,b,1)
n = algnorm(B,b)
nfeltnorm(nf,n)^2
algnorm(B,b/3,1)
algnorm(B,[3,5,1,6,7,-2,1/7,0]~,1)
m = [[1/3,y]~,[0,0]~;[y+1,y-1]~,[1..8]~];
algnorm(B,m,1)==matdet(algtomatrix(B,m,1))
a = algrandom(B,2);
algnorm(B,a,1)*algnorm(B,b,1)==algnorm(B,algmul(B,a,b),1)

print("trace(,1)");
nf = nfinit(y^2-5);
A = alginit(nf,[-1,y]);
a = [1+x+y,2*y]~*Mod(1,y^2-5)*Mod(1,x^2+1);
t = algtrace(A,a)
algtrace(A,a,1)
algdegree(A)*nfelttrace(nf,t)
b = [1+x/3+y,y-x/7]~*Mod(1,y^2-5)*Mod(1,x^2+1);
algdegree(A)*nfelttrace(nf,algtrace(A,b))==algtrace(A,b,1)
c = [4/3,2,1,6,8,9,-1,3/2]~;
algdegree(A)*nfelttrace(nf,algtrace(A,c))==algtrace(A,c,1)
m = [[y,x]~*Mod(1,y^2-5)*Mod(1,x^2+1),[1,0]~;[1..8]~,[1/7,5,6,7,8,1/4,1/3,1/2]~];
2*algdegree(A)*nfelttrace(nf,algtrace(A,m))==algtrace(A,m,1)
algtrace(A,[[1,0]~,[0,0]~;[0,0]~,[1,0]~],1)==4*algdim(A,1)

print("charpoly(,1)");
nf = nfinit(y^2-5);
al = alginit(nf,[-3-y,y]);
pol = nf.pol;
polrel = algsplittingfield(al).pol;
a = [y,1+x]~*Mod(1,pol)*Mod(1,polrel);
P = lift(algcharpoly(al,a))
algcharpoly(al,a,,1)
lift(P*subst(P,y,-y)*Mod(1,pol))^2
b = [1+x/3+y/2,3*y-x/7]~*Mod(1,pol)*Mod(1,polrel);
P = lift(algcharpoly(al,b));
Q = algcharpoly(al,b,,1);
Q == lift(P*subst(P,y,-y)*Mod(1,pol))^2
c = [4/3,2,1/7,6,4,9,-1,3/2]~;
P = lift(algcharpoly(al,c));
Q = algcharpoly(al,c,,1);
Q == lift(P*subst(P,y,-y)*Mod(1,pol))^2
{m = [[y/3,x+1]~*Mod(1,pol)*Mod(1,polrel),[1,7/11]~;
    [1..8]~,[1/7,5,6,7/2,8,1/4,1,-1/2]~];}
P = lift(algcharpoly(al,m));
Q = algcharpoly(al,m,,1);
Q==lift(P*subst(P,y,-y)*Mod(1,pol))^4

print("more al_MAT tests");
setrand(1);
nf=nfinit(y^2-5);
pol = nf.pol;
al=alginit(nf,[y,-1]);
polrel = algsplittingfield(al).pol;
m1 = matrix(2,2,i,j,algrandom(al,1)/(i+2*j));
{m2 = matrix(2,2,i,j,vector(2,k,random(2)+random(2)*x+random(2)*y+
  random(2)*x*y)~*Mod(1,polrel)*Mod(1,pol)/prime(i+2*j));}
{m3 = [[1,0]~,[1..8]~;[y+x,y-x]~*Mod(1,polrel)*Mod(1,pol),
  [1,3,5,0,-1,-2,0,-2]~/3];}
print("add");
algadd(al,m1,m2)==algadd(al,m2,m1)
algadd(al,m1,m3)==algadd(al,m3,m1)
algadd(al,m1,m2)==algadd(al,m2,m1)
algadd(al,algadd(al,m1,m2),m3) == algadd(al,m1,algadd(al,m2,m3))
print("alg/basis");
algalgtobasis(al,m1) == m1
algbasistoalg(al,m2) == m2
algalgtobasis(al,algbasistoalg(al,algalgtobasis(al,m1))) == algalgtobasis(al,m1)
algalgtobasis(al,algbasistoalg(al,algalgtobasis(al,m2))) == algalgtobasis(al,m2)
algalgtobasis(al,algbasistoalg(al,algalgtobasis(al,m3))) == algalgtobasis(al,m3)
algbasistoalg(al,algalgtobasis(al,algbasistoalg(al,m1))) == algbasistoalg(al,m1)
algbasistoalg(al,algalgtobasis(al,algbasistoalg(al,m2))) == algbasistoalg(al,m2)
algbasistoalg(al,algalgtobasis(al,algbasistoalg(al,m3))) == algbasistoalg(al,m3)
print("charpoly");
mid = [[1,0]~,[0,0]~;[0,0]~,[1,0]~];
t = 123/7;
testcp(m)=
{
  my(P,Q);
  P = algcharpoly(al,m);
  print(algnorm(al,m) == polcoeff(P,0));
  print(algtrace(al,m) == -polcoeff(P,3));
  print(algnorm(al,algsub(al,m,t*mid))==subst(P,x,t));
  Q = algcharpoly(al,m,,1);
  print(algnorm(al,m,1) == polcoeff(Q,0));
  print(algtrace(al,m,1) == -polcoeff(Q,31));
  print(algnorm(al,algsub(al,m,t*mid),1)==subst(Q,x,t));
}
testcp(m1);
testcp(m2);
testcp(m3);
print("inv/div");
algisinv(al,m1,&m1i)
m1i == alginv(al,m1)
algdivl(al,m1,m2) == algmul(al,m1i,m2)
algdivr(al,m2,m1) == algmul(al,m2,m1i)
algisdivl(al,m1,m3,&d13)
algdivl(al,m1,m3) == d13
algisinv(al,m2,&m2i)
m2i == alginv(al,m2)
algdivl(al,m2,m1) == algmul(al,m2i,m1)
algdivr(al,m1,m2) == algmul(al,m1,m2i)
algisdivl(al,m2,m3,&d23)
algdivl(al,m2,m3) == d23
algisinv(al,m3,&m3i)
m3i == alginv(al,m3)
algdivl(al,m3,m1) == algmul(al,m3i,m1)
algdivr(al,m1,m3) == algmul(al,m1,m3i)
algisdivl(al,m3,m2,&d32)
algdivl(al,m3,m2) == d32
midbasis = [[1,0,0,0,0,0,0,0]~,vector(8)~;vector(8)~,[1,0,0,0,0,0,0,0]~];
algmul(al,m1i,m1) == midbasis
algmul(al,m1,m1i) == midbasis
algmul(al,m2i,m2) == midbasis
algmul(al,m2,m2i) == midbasis
algmul(al,m3i,m3) == midbasis
algmul(al,m3,m3i) == midbasis
print("mul");
algmul(al,algmul(al,m1,m2),m3) == algmul(al,m1,algmul(al,m2,m3))
algmul(al,m1,algadd(al,m2,m3)) == algadd(al, algmul(al,m1,m2), algmul(al,m1,m3))
algmul(al,algadd(al,m1,m2),m3) == algadd(al,algmul(al,m1,m3),algmul(al,m2,m3))
print("neg");
algadd(al,m1,algneg(al,m1)) == 0
algadd(al,m2,algneg(al,m2)) == 0
algadd(al,m3,algneg(al,m3)) == 0
print("norm");
algnorm(al,m1)*algnorm(al,m2) == algnorm(al,algmul(al,m1,m2))
algnorm(al,m1)*algnorm(al,m3) == algnorm(al,algmul(al,m1,m3))
algnorm(al,m3)*algnorm(al,m2) == algnorm(al,algmul(al,m3,m2))
print("pow");
algpow(al,m1,5) == algmul(al,algpow(al,m1,2),algpow(al,m1,3))
algalgtobasis(al,algpow(al,m2,3)) == algmul(al,algpow(al,m2,5),algpow(al,m2,-2))
algpow(al,m3,3) == algmul(al,algpow(al,m3,-1),algpow(al,m3,4))
print("sqr");
algsqr(al,m1) == algpow(al,m1,2)
algsqr(al,m2) == algpow(al,m2,2)
algsqr(al,m3) == algpow(al,m3,2)
print("sub");
algsub(al,m2,m3) == algadd(al,m2,algneg(al,m3))
algsub(al,m1,m3) == algadd(al,m1,algneg(al,m3))
algsub(al,m1,m2) == algadd(al,m1,algneg(al,m2))
print("trace");
algtrace(al,m2)+algtrace(al,m3) == algtrace(al,algadd(al,m2,m3))
algtrace(al,m1)+algtrace(al,m3) == algtrace(al,algadd(al,m1,m3))
algtrace(al,m1)+algtrace(al,m2) == algtrace(al,algadd(al,m1,m2))
print("abs trace");
algtrace(al,m2,1)+algtrace(al,m3,1) == algtrace(al,algadd(al,m2,m3),1)
algtrace(al,m1,1)+algtrace(al,m3,1) == algtrace(al,algadd(al,m1,m3),1)
algtrace(al,m1,1)+algtrace(al,m2,1) == algtrace(al,algadd(al,m1,m2),1)
print("algtomatrix");
sm1 = algtomatrix(al,m1);
sm2 = algtomatrix(al,m2);
sm3 = algtomatrix(al,m3);
#sm1==4
#sm1[,1]==4
sm2+sm3 == algtomatrix(al,algadd(al,m2,m3))
sm2*sm3 == algtomatrix(al,algmul(al,m2,m3))
sm1+sm3 == algtomatrix(al,algadd(al,m1,m3))
sm1*sm3 == algtomatrix(al,algmul(al,m1,m3))
sm1+sm2 == algtomatrix(al,algadd(al,m1,m2))
sm1*sm2 == algtomatrix(al,algmul(al,m1,m2))
print("algleftmultable");
M1 = algtomatrix(al,m1,1);
M2 = algtomatrix(al,m2,1);
M3 = algtomatrix(al,m3,1);
#M1==32
#M1[,1]==32
#M2==32
#M2[,1]==32
#M3==32
#M3[,1]==32
M2+M3 == algtomatrix(al,algadd(al,m2,m3),1)
M2*M3 == algtomatrix(al,algmul(al,m2,m3),1)
M1+M3 == algtomatrix(al,algadd(al,m1,m3),1)
M1*M3 == algtomatrix(al,algmul(al,m1,m3),1)
M1+M2 == algtomatrix(al,algadd(al,m1,m2),1)
M1*M2 == algtomatrix(al,algmul(al,m1,m2),1)


print("more al_CSA tests");
setrand(1);
nf = nfinit(y^2-5);
mti = [0,-1,0,0;[1,0]~,0,0,0;0,0,0,-1;0,0,1,0];
mtj = [0,0,Mod(y,y^2-5),0;0,0,0,-y;1,0,0,0;0,-1,0,0];
mtk = [0,0,0,y;0,0,[1,2]~,0;0,1,0,0;1,0,0,0];
mt = [matid(4),mti,mtj,mtk];
al = alginit(nf,mt);
a1 = [1/2,-3,2,4/3,-1,0,1,2/5]~;
a2 = [1+2*y,y/3,5/2,-3*y/7]~*Mod(1,y^2-5);
a3 = algrandom(al,2)/13;
aid = [1,0,0,0]~;
algadd(al,algadd(al,a1,a2),a3) == algadd(al,a1,algadd(al,a2,a3))
algadd(al,a1,a2) == algadd(al,a2,a1)
algbasistoalg(al,algalgtobasis(al,algbasistoalg(al,a1))) == algbasistoalg(al,a1)
algalgtobasis(al,algbasistoalg(al,algalgtobasis(al,a2))) == algalgtobasis(al,a2)
t = 7/3;
testcp(a)=
{
  my(P,Q);
  P = algcharpoly(al,a);
  print(algnorm(al,a) == polcoeff(P,0));
  print(algtrace(al,a) == -polcoeff(P,1));
  print(algnorm(al,algsub(al,a,t*aid))==subst(P,x,t));
  Q = algcharpoly(al,a,,1);
  print(algnorm(al,a,1) == polcoeff(Q,0));
  print(algtrace(al,a,1) == -polcoeff(Q,7));
  print(algnorm(al,algsub(al,a,t*aid),1)==subst(Q,x,t));
}
print("charpoly");
testcp(a1);
testcp(a2);
testcp(a3);
print("inv/div");
algisinv(al,a1,&a1i)
a1i == alginv(al,a1)
algdivl(al,a1,a2) == algmul(al,a1i,a2)
algdivr(al,a2,a1) == algmul(al,a2,a1i)
algisdivl(al,a1,a3,&d13)
algdivl(al,a1,a3) == d13
aidbasis = vector(8,i,i==1)~;
algmul(al,a1i,a1) == aidbasis
algmul(al,a1,a1i) == aidbasis
a2i = alginv(al,a2);
print("mul");
algmul(al,a2i,a2) == aid
algmul(al,a2,a2i) == aid
algmul(al,algmul(al,a1,a2),a3) == algmul(al,a1,algmul(al,a2,a3))
print("neg");
algadd(al,a1,algneg(al,a1)) == 0
algadd(al,a2,algneg(al,a2)) == 0
algadd(al,a3,algneg(al,a3)) == 0
print("norm");
algnorm(al,a1)*algnorm(al,a2) == algnorm(al,algmul(al,a1,a2))
algnorm(al,a1)*algnorm(al,a3) == algnorm(al,algmul(al,a1,a3))
algnorm(al,a3)*algnorm(al,a2) == algnorm(al,algmul(al,a3,a2))
print("pow");
algpow(al,a1,5) == algmul(al,algpow(al,a1,2),algpow(al,a1,3))
algpow(al,a2,3) == algmul(al,algpow(al,a2,5),algpow(al,a2,-2))
algpow(al,a3,3) == algmul(al,algpow(al,a3,-1),algpow(al,a3,4))
print("sqr");
algsqr(al,a1) == algpow(al,a1,2)
algsqr(al,a2) == algpow(al,a2,2)
algsqr(al,a3) == algpow(al,a3,2)
print("sub");
algsub(al,a2,a3) == algadd(al,a2,algneg(al,a3))
algsub(al,a1,a3) == algadd(al,a1,algneg(al,a3))
algsub(al,a1,a2) == algadd(al,a1,algneg(al,a2))
print("trace");
algtrace(al,a2)+algtrace(al,a3) == algtrace(al,algadd(al,a2,a3))
algtrace(al,a1)+algtrace(al,a3) == algtrace(al,algadd(al,a1,a3))
algtrace(al,a1)+algtrace(al,a2) == algtrace(al,algadd(al,a1,a2))
print("abs trace");
algtrace(al,a2,1)+algtrace(al,a3,1) == algtrace(al,algadd(al,a2,a3),1)
algtrace(al,a1,1)+algtrace(al,a3,1) == algtrace(al,algadd(al,a1,a3),1)
algtrace(al,a1,1)+algtrace(al,a2,1) == algtrace(al,algadd(al,a1,a2),1)
print("algtomatrix");
sa1 = algtomatrix(al,a1);
sa2 = algtomatrix(al,a2);
sa3 = algtomatrix(al,a3);
#sa1==2
#sa1[,1]==2
sa2+sa3 == algtomatrix(al,algadd(al,a2,a3))
sa2*sa3 == algtomatrix(al,algmul(al,a2,a3))
sa1+sa3 == algtomatrix(al,algadd(al,a1,a3))
sa1*sa3 == algtomatrix(al,algmul(al,a1,a3))
sa1+sa2 == algtomatrix(al,algadd(al,a1,a2))
sa1*sa2 == algtomatrix(al,algmul(al,a1,a2))
print("algleftmultable");
ma1 = algtomatrix(al,a1,1);
ma2 = algtomatrix(al,a2,1);
ma3 = algtomatrix(al,a3,1);
#ma1==8
#ma1[,1]==8
#ma2==8
#ma2[,1]==8
ma2+ma3 == algtomatrix(al,algadd(al,a2,a3),1)
ma2*ma3 == algtomatrix(al,algmul(al,a2,a3),1)
ma1+ma3 == algtomatrix(al,algadd(al,a1,a3),1)
ma1*ma3 == algtomatrix(al,algmul(al,a1,a3),1)
ma1+ma2 == algtomatrix(al,algadd(al,a1,a2),1)
ma1*ma2 == algtomatrix(al,algmul(al,a1,a2),1)


print("csa pol/polmod bugs");
setrand(1);
nf = nfinit(y^2-5);
mti = [0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
mtj = [0,0,y,0;0,0,0,-y;1,0,0,0;0,-1,0,0];
mtk = [0,0,0,y;0,0,y,0;0,1,0,0;1,0,0,0];
mt = [matid(4),mti,mtj,mtk];
al = alginit(nf,mt*Mod(1,nf.pol));
algrelmultable(al)
a = [y,y,y,y/3]~;
algpow(al,a,4)
algpow(al,a,-2)
algmul(al,a,a)
algnorm(al,a) == algnorm(al,algalgtobasis(al,a))
algnorm(al,a,1) == algnorm(al,algalgtobasis(al,a),1)
algtrace(al,a) == algtrace(al,algalgtobasis(al,a))
algtrace(al,a,1) == algtrace(al,algalgtobasis(al,a),1)
algcharpoly(al,a) == algcharpoly(al,algalgtobasis(al,a))
algcharpoly(al,a,,1) == algcharpoly(al,algalgtobasis(al,a),,1)
algtomatrix(al,a) == algtomatrix(al,algalgtobasis(al,a))

print("csa: denom over Z[y] but not over ZK");
setrand(1);
nf = nfinit(y^2-5);
mti = [0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
mtj = [0,0,(y-1)/2,0;0,0,0,-(y-1)/2;1,0,0,0;0,-1,0,0];
mtk = [0,0,0,(y-1)/2;0,0,(y-1)/2,0;0,1,0,0;1,0,0,0];
mt = [matid(4),mti,mtj,mtk];
al = alginit(nf,mt*Mod(1,nf.pol));
algrelmultable(al)
mti = [0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
mtj = [0,0,(y-1)/3,0;0,0,0,-(y-1)/3;1,0,0,0;0,-1,0,0];
mtk = [0,0,0,(y-1)/3;0,0,(y-1)/3,0;0,1,0,0;1,0,0,0];
mt = [matid(4),mti,mtj,mtk];
al = alginit(nf,mt*Mod(1,nf.pol));

print("al_MAT over al_CSA");
setrand(1);
nf = nfinit(y^2-5);
mti = [0,-1,0,0;1,0,0,0;0,0,0,-1;0,0,1,0];
mtj = [0,0,(y-1)/2,0;0,0,0,-(y-1)/2;1,0,0,0;0,-1,0,0];
mtk = [0,0,0,(y-1)/2;0,0,(y-1)/2,0;0,1,0,0;1,0,0,0];
mt = [matid(4),mti,mtj,mtk];
al = alginit(nf,mt*Mod(1,nf.pol));
m1 = [algrandom(al,2)/2,algrandom(al,1)/3;algrandom(al,2)/5,algrandom(al,3)];
m2 = [[y,1/2,2-y,0]~,[3,y/2,-3*y,1]~;[7,0,0,y]~,[1-y,2,-y,0]~];
algnorm(al,algmul(al,m1,m2)) == algnorm(al,m1)*algnorm(al,m2)
algnorm(al,algmul(al,m1,m2),1) == algnorm(al,m1,1)*algnorm(al,m2,1)
algtrace(al,algadd(al,m1,m2)) == algtrace(al,m1)+algtrace(al,m2)
algtrace(al,algadd(al,m1,m2),1) == algtrace(al,m1,1)+algtrace(al,m2,1)
mid = [[1,0,0,0]~,vector(4)~;vector(4)~,[1,0,0,0]~];
t = -3/7;
testcp(m)=
{
  my(P,Q);
  P = algcharpoly(al,m);
  print(algnorm(al,m) == polcoeff(P,0));
  print(algtrace(al,m) == -polcoeff(P,3));
  print(algnorm(al,algsub(al,m,t*mid))==subst(P,x,t));
  Q = algcharpoly(al,m,,1);
  print(algnorm(al,m,1) == polcoeff(Q,0));
  print(algtrace(al,m,1) == -polcoeff(Q,31));
  print(algnorm(al,algsub(al,m,t*mid),1)==subst(Q,x,t));
}
testcp(m1);
testcp(m2);
print("algleftmultable");
M1 = algtomatrix(al,m1,1);
M2 = algtomatrix(al,m2,1);
#M1==32
#M1[,1]==32
#M2==32
#M2[,1]==32
M1+M2 == algtomatrix(al,algadd(al,m1,m2),1)
M1*M2 == algtomatrix(al,algmul(al,m1,m2),1)

print("Hamilton quaternions");
a = algrandom(,1.);
apply(type,a)
b = algrandom(,1.);
precision(b)
algrandom(,0.)==0
localprec(300); precision(algrandom(,1.))
print("H_neg");
algneg(,a) == -a
algneg(,[a,b;b,a]) == [-a,-b;-b,-a]
algneg(,2.) == -2
algneg(,I) == -I
algneg(,1/2) == -1/2
algneg(,3) == -3
print("H_add");
algadd(,a,b) == a+b
algadd(,I,[1..4]~) == [1,3,3,4]~
algadd(,[1..4]~,10.) == [11.,2,3,4]~
algadd(,2.*I,3/2) == 3/2 + 2.*I
algadd(,[a;b],[2;I]) == [algadd(,a,2);algadd(,b,I)]
algsub(,a,b) == a-b
print("H_trace");
algtrace(,a) == 2*a[1]
algtrace(,b,1) == 4*b[1]
algtrace(,[a,0;1,b]) == algtrace(,a) + algtrace(,b)
algtrace(,[a,0;1,b],1) == 8*(a[1]+b[1])
algtrace(,1) == 2
algtrace(,1/2+I) == 1
algtrace(,matid(2)) == 4
algtrace(,matid(2),1) == 16
print("H_tomatrix");
algtomatrix(,a+b) == algtomatrix(,a)+algtomatrix(,b)
algtomatrix(,a+b,1) == algtomatrix(,a,1)+algtomatrix(,b,1)
algtomatrix(,[1,0,0,0]~)
algtomatrix(,1)
algtomatrix(,[1,0,0,0]~,1)
algtomatrix(,1,1)
algtomatrix(,[0,1,0,0]~) == algtomatrix(,I)
algtomatrix(,[0,1,0,0]~,1) == algtomatrix(,I,1)
algtomatrix(,I)^2 == -1
algtomatrix(,I,1)^2 == -1
algtomatrix(,[0,0,1,0]~)^2 == -1
algtomatrix(,[0,0,1,0]~,1)^2 == -1
algtomatrix(,[0,0,0,1]~)^2 == -1
algtomatrix(,[0,0,0,1]~,1)^2 == -1
algtomatrix(,I)*algtomatrix(,[0,0,1,0]~) == algtomatrix(,[0,0,0,1]~)
M = Mat(1); M[1,1] = a;
algtomatrix(,M) == algtomatrix(,a)
algtomatrix(,M,1) == algtomatrix(,a,1)
M = [1.+I,2;3/2-I,Pi*I];
N = [-7,3+4/5*I;sqrt(2),exp(sqrt(5)*I)];
P = matrix(2,2,i,j,algrandom(,1.));
exponent(algtrace(,algmul(,M,N)) - algtrace(,algmul(,N,M))) < -120
exponent(algmul(,M,algmul(,N,P)) - algmul(,algmul(,M,N),P)) < -120
algtomatrix(,M)*algtomatrix(,N) == algtomatrix(,M*N)
exponent(algtomatrix(,M,1)*algtomatrix(,N,1) - algtomatrix(,M*N,1)) < -120
trace(algtomatrix(,M)) == algtrace(,M[1,1])+algtrace(,M[2,2])
trace(algtomatrix(,N)) == algtrace(,N[1,1])+algtrace(,N[2,2])
{exponent(trace(algtomatrix(,M,1)) - 2*(algtrace(,M[1,1],1) +
  algtrace(,M[2,2],1))) < -120}
{exponent(trace(algtomatrix(,N,1)) - 2*(algtrace(,N[1,1],1) +
  algtrace(,N[2,2],1))) < -120}
print("3x3 matrices");
M = matrix(3,3,i,j,algrandom(,1.));
N = matrix(3,3,i,j,algrandom(,2.));
P = matrix(3,3,i,j,algrandom(,3.));
exponent(algtrace(,algmul(,M,N)) - algtrace(,algmul(,N,M))) < -120
exponent(algmul(,M,algmul(,N,P)) - algmul(,algmul(,M,N),P)) < -120
exponent(algmul(,M,algadd(,N,P)) - algadd(,algmul(,M,N),algmul(,M,P))) < -120
exponent(algtomatrix(,M)*algtomatrix(,N) - algtomatrix(,algmul(,M,N))) < -120
exponent(algtomatrix(,M,1)*algtomatrix(,N,1) - algtomatrix(,algmul(,M,N),1)) < -120
algtomatrix(,M+N) == algtomatrix(,M)+algtomatrix(,N)
exponent(algtomatrix(,M+N,1) - (algtomatrix(,M,1)+algtomatrix(,N,1))) < -120
trace(algtomatrix(,M)) == algtrace(,M[1,1])+algtrace(,M[2,2])+algtrace(,M[3,3])
{exponent(trace(algtomatrix(,N)) - (algtrace(,N[1,1]) + algtrace(,N[2,2]) +
  algtrace(,N[3,3]))) < -120}
{exponent(trace(algtomatrix(,M,1)) - 3*(algtrace(,M[1,1],1) +
  algtrace(,M[2,2],1) + algtrace(,M[3,3],1))) < -120}
{exponent(trace(algtomatrix(,N,1)) - 3*(algtrace(,N[1,1],1) +
  algtrace(,N[2,2],1) + algtrace(,N[3,3],1))) < -110}
algtomatrix(,[-100-1000*I;[1,2,3,4]~])
c = algrandom(,3.);
exponent(algmul(,a,algmul(,b,c)) - algmul(,algmul(,a,b),c)) < -120
algtrace(,algmul(,a,b)) == algtrace(,algmul(,b,a))
algmul(,1,a) == a
algmul(,b,1) == b
algmul(,I,I) == [-1,0,0,0]~
algmul(,[0,0,1,0]~,[0,0,1,0]~) == [-1,0,0,0]~
algmul(,[0,0,0,1]~,[0,0,0,1]~) == [-1,0,0,0]~
algmul(,I,[0,0,1,0]~) == [0,0,0,1]~
exponent(algmul(,a,algadd(,b,c)) - algadd(,algmul(,a,b),algmul(,a,c))) < -120
exponent(algtomatrix(,algmul(,a,b)) - algtomatrix(,a)*algtomatrix(,b)) < -120
exponent(algtomatrix(,algmul(,a,b),1) - algtomatrix(,a,1)*algtomatrix(,b,1)) < -120
algsqr(,M) == algmul(,M,M)
algnorm(,M) == real(matdet(algtomatrix(,M)))
algnorm(,M,1) == matdet(algtomatrix(,M,1))
z=sqrt(2)+Pi*I;
algsqr(,sqrt(2)+Pi*I) == z^2
algnorm(,a) == norml2(a)
algnorm(,a,1) == norml2(a)^2
algnorm(,b) == norml2(b)
algnorm(,b,1) == norml2(b)^2
algnorm(,c) == norml2(c)
algnorm(,c,1) == norml2(c)^2
exponent(algnorm(,c) - real(matdet(algtomatrix(,c)))) < -120
exponent(algnorm(,c,1) - matdet(algtomatrix(,c,1))) < -110
algnorm(,c) == algmul(,c,algsub(,algtrace(,c),c))[1]
algnorm(,z) == norm(z)
algnorm(,z,1) == norm(z)^2
algcharpoly(,a) == x^2 - algtrace(,a)*x + algnorm(,a)
exponent(algcharpoly(,a) - real(charpoly(algtomatrix(,a)))) < -120
algcharpoly(,a,,1) == (x^2 - algtrace(,a)*x + algnorm(,a))^2
exponent(algcharpoly(,a,,1) - charpoly(algtomatrix(,a,1))) < -120
algcharpoly(,z) == x^2 - algtrace(,z)*x + algnorm(,z)
algcharpoly(,z,,1) == (x^2 - algtrace(,z)*x + algnorm(,z))^2
algnorm(,algmul(,a,b)) == algnorm(,a)*algnorm(,b)
exponent(algnorm(,algmul(,M,N)) - algnorm(,M)*algnorm(,N)) < -110
exponent(algcharpoly(,N) - real(charpoly(algtomatrix(,N)))) < -110
m = matrix(3,3,i,j,vectorv(4,k,random(3)));
pol = algcharpoly(,m);
pol == real(charpoly(algtomatrix(,m)))
polcoef(pol,5) == -algtrace(,m)
polcoef(pol,0) == algnorm(,m)
pol = algcharpoly(,m,,1);
pol == charpoly(algtomatrix(,m,1))
polcoef(pol,35) == -algtrace(,m,1)
polcoef(pol,0) == algnorm(,m,1)
print("nonsquare matrices");
M = matrix(4,7,i,j,algrandom(,1.));
N = matrix(7,5,i,j,algrandom(,1.));
P = matrix(5,8,i,j,algrandom(,1.));
exponent(algmul(,M,algmul(,N,P)) - algmul(,algmul(,M,N),P)) < -120
exponent(algsqr(,a) - algmul(,a,a)) < -120
exponent(algsqr(,b) - algmul(,b,b)) < -120
exponent(algsqr(,c) - algmul(,c,c)) < -120
!algisinv(,0)
!algisinv(,vectorv(4))
algisinv(,a)
ai = alginv(,a); exponent(algsub(,algmul(,a,ai),1)) < -120
algisinv(,b,&bi)
bi == alginv(,b)
exponent(algsub(,algmul(,b,bi),1)) < -120
algisinv(,z)
alginv(,z) == 1/z
exponent(algsub(,algmul(,a,algdivl(,a,b)),b)) < -120
algdivl(,b,c) == algmul(,alginv(,b),c)
algdivl(,b,0) == 0
algisdivl(,0,0)
!algisdivl(,0,a)
exponent(algnorm(,[1,a;2,I])) > -64
m = [1,a;2,I];
algisinv(,m,&mi)
mi == alginv(,m)
exponent(algsub(,algmul(,m,mi),matid(2))) < -120
exponent(algsub(,algmul(,mi,m),matid(2))) < -120
n = [I-3/2,b;c,z];
ni = alginv(,n);
exponent(algsub(,algmul(,n,ni),matid(2))) < -120
exponent(algsub(,algmul(,ni,n),matid(2))) < -120
mni = alginv(,algmul(,m,n));
exponent(algsub(,mni, algmul(,ni,mi))) < -120
exponent(algsub(,algmul(,algdivr(,n,m),m),n)) < -120
ra = bestappr(a);
rb = bestappr(b);
rc = bestappr(c);
m = [ra,rb;algmul(,rc,ra),algmul(,rc,rb)];
algnorm(,m) == 0
!algisinv(,m)
n = algmul(,m,[1,[6,7,8,9]~;3,4+I]);
algisdivl(,m,n,&quo)
algmul(,m,quo) == n
quo == algdivl(,m,n)
exponent(algsub(, algpow(,a,3), algmul(,a,algsqr(,a)))) < -120
algpow(,a,0) == 1
algpow(,a,-2) == algsqr(,alginv(,a))
algpow(,[;],0) == [;]
algpow(,[;],7) == [;]
algpow(,[;],-5) == [;]
algpow(,m,0) == matid(2)
algpow(,m,3) == algmul(,algsqr(,m),m)
algpow(,m,-9)
exponent(algsub(,algmul(,algdivr(,a,b),b),a)) < -120
algdivr(,m,n)
exponent(algpoleval(,x^4-7*x,z) - (z^4-7*z)) < -110
exponent(algsub(,algpoleval(,x^2,a),algsqr(,a))) < -120
{exponent(algsub(,algpoleval(,x^3-x+1,b),
  algadd(,algsub(,algpow(,b,3),b),1))) < -120}
exponent(algpoleval(,algcharpoly(,a),a)) < -120
exponent(algpoleval(,algcharpoly(,b),b)) < -120
algdivl(,[;],[;])
H = alginit(1.,1/2);
algtype(H)
algaut(H)
algb(H)
type(algcenter(H))
algchar(H)
algdegree(H)
algdim(H)
algdim(H,1)
alghasse(H)
alghassei(H)
algindex(H)
algisassociative(H)
algiscommutative(H)
algisdivision(H)
algisramified(H)
algissemisimple(H)
algissimple(H)
algissplit(H)
mt = algmultable(H)
algisassociative(mt)
apply(matsize,mt)
mt[1] == 1
mt[2]^2 == -1
mt[3]^2 == -1
mt[4] == mt[2]*mt[3]
mt[3]*mt[2] == -mt[4]
Mat([m[,1] | m <- mt]) == matid(4)
algradical(H)
algsimpledec(H) == [0,[H]]
type(algsplittingfield(H))
algadd(H,a,b) == algadd(,a,b)
algcharpoly(H,a) == algcharpoly(,a)
algdivl(H,a,b) == algdivl(,a,b)
algdivr(H,a,b) == algdivr(,a,b)
alginv(H,a) == alginv(,a)
algisdivl(H,a,b) == algisdivl(,a,b)
algisinv(H,a) == algisinv(,a)
algmul(H,a,b) == algmul(,a,b)
algneg(H,a) == algneg(,a)
algnorm(H,a) == algnorm(,a)
algpoleval(H,x^3+x+1,a) == algpoleval(,x^3+x+1,a)
algpow(H,a,5) == algpow(,a,5)
algpow(H,a,0) == algpow(,a,0)
algpow(H,a,-3) == algpow(,a,-3)
#algrandom(H,1.)
algsqr(H,a) == algsqr(,a)
algsub(H,a,b) == algsub(,a,b)
algtomatrix(H,a) == algtomatrix(,a)
algtrace(H,a) == algtrace(,a)

R = alginit(1.,0);
algtype(R)
type(algaut(R))
algb(R)
type(algcenter(R))
algchar(R)
algdegree(R)
algdim(R)
algdim(R,1)
alghasse(R)
alghassei(R)
algindex(R)
algisassociative(R)
algiscommutative(R)
algisdivision(R)
algisramified(R)
algissemisimple(R)
algissimple(R)
algissplit(R)
mt = algmultable(R)
algisassociative(mt)
apply(matsize,mt)
mt[1] == 1
algradical(R)
algsimpledec(R) == [0,[R]]
type(algsplittingfield(R))
algbasis(R) == matid(1)
alginvbasis(R) == matid(1)
a = algrandom(R,1.);
type(a)
b = algrandom(R,2.);
m22 = matrix(2,2,i,j,algrandom(R,1.));
m22b = matrix(2,2,i,j,algrandom(R,1.));
m23 = matrix(2,3,i,j,algrandom(R,1.));
m32 = matrix(3,2,i,j,algrandom(R,1.));
algadd(R,a,b) == a+b
algadd(R,m22,m22b) == m22 + m22b
algneg(R,a) == -a
algsub(R,a,b) == a-b
algsub(R,m22,m22) == 0
algmul(R,a,b) == a*b
algmul(R,m22,m23) == m22*m23
algsqr(R,a) == a^2
algsqr(R,m22) == m22^2
algtomatrix(R,a) == Mat(a)
algtomatrix(R,b,1) == Mat(b)
algtomatrix(R,m22) == m22
algtomatrix(R,m22b,1) == m22b
algnorm(R,a) == a
algnorm(R,b,1) == b
algnorm(R,m22) == matdet(m22)
algnorm(R,m22b,1) == matdet(m22b)^2
algtrace(R,a) == a
algtrace(R,b,1) == b
algtrace(R,m22) == trace(m22)
algtrace(R,m22b,1) == 2*trace(m22b)
algcharpoly(R,a) == x-a
algcharpoly(R,b,,1) == x-b
algcharpoly(R,m22) == charpoly(m22)
algcharpoly(R,m22b,,1) == charpoly(m22b)^2
exponent(algdivl(R,a,b) - b/a) < -100
exponent(algdivl(R,m22,m22b) - m22^(-1)*m22b) < -100
{m22noninv = matrix(2,1,i,j,round(algrandom(R,10.))) *
  matrix(1,2,i,j,round(algrandom(R,10.)))};
algnorm(R,m22noninv) == 0
exponent(m22noninv * algdivl(R,m22noninv,m22noninv*m22) - m22noninv*m22) < -100
exponent(m22*alginv(R,m22) - matid(2)) < -100
exponent(algdivr(R,a,b) - a/b) < -100
algdivr(R,m22,m22b) == m22*m22b^(-1)
!algisdivl(R,0.,1)
algisdivl(R,0.,0.)
!algisdivl(R,m22noninv,m22)
!algisinv(R,0.)
!algisinv(R,m22noninv)
algisinv(R,a)
algisinv(R,m22b)
algpow(R,a,8) == a^8
exponent(algpow(R,a,-2) - a^(-2)) < -100
algpow(R,a,0) == 1.
algpow(R,m22,3) == m22^3
exponent(algpow(R,m22,-5) - m22^(-5)) < -100
algpow(R,m22,0) == matid(2)
algpoleval(R,x^3-x+1,a) == a^3-a+1

C = alginit(I,0);
algtype(C)
algaut(C)
algb(C)
algcenter(C)
algchar(C)
algdegree(C)
algdim(C)
algdim(C,1)
alghasse(C)
alghassei(C)
algindex(C)
algisassociative(C)
algiscommutative(C)
algisdivision(C)
algisramified(C)
algissemisimple(C)
algissimple(C)
algissplit(C)
mt = algmultable(C)
algisassociative(mt)
apply(matsize,mt)
mt[1] == 1
mt[2]^2 == -1
Mat([m[,1] | m <- mt]) == matid(2)
algradical(C)
algsimpledec(C) == [0,[C]]
type(algsplittingfield(C))
algbasis(C) == matid(2)
alginvbasis(C) == matid(2)
z = algrandom(C,1.);
type(z)
u = algrandom(C,2.);
mc22 = matrix(2,2,i,j,algrandom(C,1.));
mc22b = matrix(2,2,i,j,algrandom(C,1.));
mc23 = matrix(2,3,i,j,algrandom(C,1.));
mc32 = matrix(3,2,i,j,algrandom(C,1.));
algadd(C,z,u) == z+u
algadd(C,m22,mc22) == m22 + mc22
algneg(C,z) == -z
algsub(C,z,u) == z-u
algsub(C,m22,mc22) == m22 - mc22
algmul(C,z,u) == z*u
algmul(C,mc32,mc22) == mc32*mc22
algsqr(C,u) == u^2
algsqr(C,mc22) == mc22^2
algtomatrix(R,z) == Mat(z)
algtomatrix(C,z) == Mat(z)
algtomatrix(C,u,1) == [real(u),-imag(u);imag(u),real(u)]
algtomatrix(C,mc22) == mc22
matsize(algtomatrix(C,mc22,1)) == [4,4]
Set(apply(type,concat(Vec(algtomatrix(C,mc22,1)))))
algtomatrix(C,mc22,1)+algtomatrix(C,mc22b,1) == algtomatrix(C,mc22+mc22b,1)
{exponent(algtomatrix(C,mc22,1)*algtomatrix(C,mc22b,1)
  - algtomatrix(C,mc22*mc22b,1)) < -100}
algnorm(C,z) == z
algnorm(C,u,1) == norm(u)
algnorm(C,mc22) == matdet(mc22)
algnorm(C,mc22b,1) == norm(matdet(mc22b))^2
algtrace(C,z) == z
algtrace(C,u,1) == 2*real(u)
algtrace(C,mc22) == trace(mc22)
algtrace(C,mc22b,1) == 4*real(trace(mc22b))
algcharpoly(C,z) == x-z
algcharpoly(C,u,,1) == x^2 - 2*real(u)*x + norm(u)
algcharpoly(C,m22) == charpoly(m22)
P = charpoly(m22b);
algcharpoly(C,m22b,,1) == real(P*conj(P))^2
algdivl(C,z,u) == u/z
exponent(algdivl(C,mc22,mc22b) - mc22^(-1)*mc22b) < -100
{mc22noninv = matrix(2,1,i,j,round(algrandom(C,10.))) *
  matrix(1,2,i,j,round(algrandom(C,10.)))};
algnorm(C,mc22noninv) == 0
exponent(mc22noninv*algdivl(C,mc22noninv,mc22noninv*mc22)-mc22noninv*mc22)<-100
exponent(mc22*alginv(C,mc22) - matid(2)) < -100
exponent(algdivr(C,z,u) - z/u) < -100
algdivr(C,mc22,mc22b) == mc22*mc22b^(-1)
!algisdivl(R,0.+0.*I,I)
algisdivl(R,0.+0.*I,0.*I)
!algisdivl(C,mc22noninv,mc22)
!algisinv(C,0.*I)
!algisinv(C,m22noninv)
algisinv(C,z)
algisinv(C,mc22b)
algpow(C,z,11) == z^11
exponent(algpow(C,z,-6) - z^(-6)) < -100
algpow(C,z,0) == 1.
algpow(C,mc22,5) == mc22^5
exponent(algpow(C,mc22,-3) - mc22^(-3)) < -100
algpow(C,mc22,0) == matid(2)
exponent(algpoleval(C,x^3-x+1,z) - (z^3-z+1)) < -100

print("algnewprec:");
nf = nfinit(y^2-5);
alg = alginit(nf,[-1,-y]); \\cyclic
bitprecision(alg) < 256
localbitprec(256); alg = algnewprec(alg);
bitprecision(alg) >= 256
alg = algtableinit([Mat(1)],0); \\table
localbitprec(256); alg = algnewprec(alg);
alg = alginit(nf,[Mat(1)]); \\CSA
bitprecision(alg) < 256
localbitprec(256); alg = algnewprec(alg);
bitprecision(alg) >= 256
R == algnewprec(R)
C == algnewprec(C)
H == algnewprec(H)
w = algrandom(al,20);
algpoleval(al, algcharpoly(al,w), w) == 0
algtomatrix(al,algeltfromnf(al,y)) == y

print("algquattobasis / algbasistoquat / algisquatalg");
nf = nfinit(y^2-2);
a = -2;
b = -1-y;
alg = alginit(nf,[a,b]);
algisquatalg(alg) == [a,b]
algquattobasis(alg,[1,0,0,0]~) == 1
i = algquattobasis(alg,[0,1,0,0]~);
algsqr(alg,i) == algeltfromnf(alg,a)
j = algquattobasis(alg,[0,0,1,0]~);
algsqr(alg,j) == algeltfromnf(alg,b)
algmul(alg,i,j) == - algmul(alg,j,i)
algmul(alg,i,j) == algquattobasis(alg,[0,0,0,1]~)
print("linearity");
q1 = vectorv(4,i,vectorv(2,j,random([-10,10]))/random([2,5]));
w1 = algquattobasis(alg,q1);
#w1 == 8
q2 = vectorv(4,i,vectorv(2,j,random([-10,10]))/random([2,5]));
w2 = algquattobasis(alg,q2);
#w2 == 8
algadd(alg,w1,w2) == algquattobasis(alg,q1+q2)
print("inverses");
q1 == apply(c->nfalgtobasis(nf,c),algbasistoquat(alg,w1))
q2 == apply(c->nfalgtobasis(nf,c),algbasistoquat(alg,w2))
print("quadratic with linear term");
v = varhigher("v",y);
rnf = rnfinit(nf, v^2-v-y);
sig = 1-v;
b = y-5;
alg = alginit(rnf, [sig,b]);
a = poldisc(rnf.pol);
algisquatalg(alg) == [a,b]
algquattobasis(alg,[1,0,0,0]~) == 1
i = algquattobasis(alg,[0,1,0,0]~);
algsqr(alg,i) == algeltfromnf(alg,a)
j = algquattobasis(alg,[0,0,1,0]~);
algsqr(alg,j) == algeltfromnf(alg,b)
algmul(alg,i,j) == - algmul(alg,j,i)
algmul(alg,i,j) == algquattobasis(alg,[0,0,0,1]~)
print("linearity");
q1 = vectorv(4,i,vectorv(2,j,random([-10,10])));
w1 = algquattobasis(alg,q1);
#w1 == 8
q2 = vectorv(4,i,vectorv(2,j,random([-10,10])));
w2 = algquattobasis(alg,q2);
#w2 == 8
algadd(alg,w1,w2) == algquattobasis(alg,q1+q2)
print("inverses");
q1 == apply(c->nfalgtobasis(nf,c),algbasistoquat(alg,w1))
q2 == apply(c->nfalgtobasis(nf,c),algbasistoquat(alg,w2))
print("isquatalg");
H = alginit(1.,1/2);
algisquatalg(H)
!algisquatalg(alginit(1.,0))
nf = nfinit(y);
pr11 = idealprimedec(nf,11)[1];
alg = alginit(nf,[[pr11],[1]]);
algisquatalg(alg)!=0
mt = algmultable(alg);
talg = alginit(nf,mt);
!algisquatalg(talg)
talg = algtableinit(mt);
!algisquatalg(talg)
pr17 = idealprimedec(nf,17)[1];
alg = alginit(nf,[3,[[pr11,pr17],[1/3,2/3]],[0]]);
!algisquatalg(alg)

print("doc algquattobasis");
nf = nfinit(y^2+1);
alg = alginit(nf, [2,3*y+1]);
#algquattobasis(alg,[1,2,y,0]~)
algsqr(alg,algquattobasis(alg,[0,1,0,0]~))

print("doc algbasistoquat");
nf = nfinit(y^2+1);
alg = alginit(nf, [3,2*y-1]);
apply(type,algbasistoquat(alg, [1..8]~))

print("doc algisquatalg");
nf = nfinit(y^2-2);
pr = idealprimedec(nf,2)[1];
al = alginit(nf, [[pr],[1,0]]);
[a,b] = algisquatalg(al);
Set(algramifiedplaces(alginit(nf,[a,b]))) == Set([pr,1])

print("alginvol");
mt = [matid(1)];
talg = algtableinit(mt);
!alginvol(talg)
R = alginit(1.,0);
alginvol(R) == matid(1)
w = Pi;
alginvol(,w) == w
C = alginit(I,0);
w = sqrt(2)+I*sqrt(3);
alginvol(C) == matdiagonal([1,-1])
alginvol(C,w) == conj(w)
H = alginit(1.,1/2);
alginvol(H) == matdiagonal([1,-1,-1,-1])
alginvol() == matdiagonal([1,-1,-1,-1])
w = [Pi^2,sqrt(7),-13,4/5]~;
cw = -w; cw[1] = w[1];
alginvol(,w) == cw
nf = nfinit(y^2-2);
mt = qamt(-1,y);
al = alginit(nf,mt);
!alginvol(al)
al = alginit(nf,3);
!alginvol(al)
rnf = rnfinit(nf,x^3-3*x-1);
aut = 2-x^2;
al = alginit(rnf,[aut,-2]);
!alginvol(al)
w = algrandom(al,10);
alginvol(al,w)
localbitprec(256); al = algnewprec(al);
!alginvol(al)
pr1 = idealprimedec(nf,2)[1];
pr2 = idealprimedec(nf,17)[1];
al = alginit(nf,[3,[[pr1,pr2],[2/3,1/3]],[0,0]]);
!alginvol(al)
chk_invol(s,al) =
{
  my(x,n = algdim(al,1),y);
  print1(type(s)=="t_MAT");
  print1(" ", #s == n);
  print1(" ", s^2 == 1);
  print1(" ", matrank(s+matid(n)) == n\4);
  x = vectorv(n\4,i,random(100));
  x = algeltfromnf(al,x);
  print1(" ", s*x==x);
  x = algrandom(al,100);
  y = algrandom(al,100);
  print1(" ", s*algmul(al,x,y) == algmul(al,s*y,s*x));
  print1(" ", alginvol(al,x) == s*x);
  print(" ", alginvol(al,y) == s*y);
};
al = alginit(nf,[1,y]);
s = alginvol(al);
chk_invol(s,al);
localbitprec(256); al = algnewprec(al);
s = alginvol(al);
chk_invol(s,al);
al = alginit(nf,[-7,y],,0);
s = alginvol(al);
chk_invol(s,al);
al = alginit(nf,[-7,y]);
s = alginvol(al);
chk_invol(s,al);
localbitprec(256); al = algnewprec(al);
s = alginvol(al);
chk_invol(s,al);
rnf = rnfinit(nf,x^2+x+1);
aut = -x-1;
al = alginit(rnf,[aut,-13]);
s = alginvol(al);
chk_invol(s,al);
al = alginit(nf,[[pr1,pr2],[1,1]]);
s = alginvol(al);
chk_invol(s,al);
al = alginit(nf,[2,[[pr1,pr2],[0,1/2]],[0,1/2]]);
s = alginvol(al);
chk_invol(s,al);

print("Skolem-Noether");
nf = nfinit(y^2-3);
al = alginit(nf, [1-y,-2]);
u = [1..8]~;
fu = alginvol(al,u);
g = algskolemnoether(al,u,fu);
algisinv(al,g)
algmul(al,g,u) == algmul(al,fu,g)
ii = algquattobasis(al,[0,1,0,0]~);
jj = algquattobasis(al,[0,0,1,0]~);
g = [2..9]~;
ginv = alginv(al,g);
fii = algmul(al,algmul(al,g,ii),ginv);
fjj = algmul(al,algmul(al,g,jj),ginv);
h = algskolemnoether(al,[ii,jj],[fii,fjj]);
algisinv(al,h,&hinv)
algmul(al,h,ii) == algmul(al,fii,h)
algmul(al,h,jj) == algmul(al,fjj,h)
gh = algmul(al,g,hinv);
2*gh == algeltfromnf(al,algtrace(al,gh))
algskolemnoether(al,[],[])
algskolemnoether(al,vectorv(8),vectorv(8))
algskolemnoether(al,u,u)
print("algskolemnoether with CSA");
al = alginit(nf, qamt(2+y,-3));
u = [-8..-1]~;
fu = algsub(al, algeltfromnf(al,algtrace(al,u)), u);
g = algskolemnoether(al,u,fu);
algisinv(al,g)
algmul(al,g,u) == algmul(al,fu,g)
g2 = algsqr(al,g);
2*g2 == algeltfromnf(al, algtrace(al,g2)) \\g^2 in nf
al = alginit(nfinit(y),1);
a = [2]~;
g = algskolemnoether(al,a,a) != 0




\\BUGS

print("nfgrunwaldwang SEGV #1669");
nfgrunwaldwang(nfinit(y),[2,3],[1,2],Vecsmall(1))
nfgrunwaldwang(nfinit(x),[2,3],[1,2],Vecsmall(1))

print("alginit SEGV #2465");
Q=nfinit(y); F=rnfinit(Q,x^3+x^2-2*x-1); alginit(F,[2,x^2-2])
alginit(F,[2,y])

\\alg_model bug for 1-dim al_CSA
al = alginit(nfinit(y),[matid(1)]);
algtomatrix(al,[Mod(1,y)]~)
algtomatrix(al,[1]~)
algtomatrix(al,[1+y-y]~)
algtomatrix(al,[1/2]~)
algtomatrix(al,[Mod(1/2,y)]~)

\\al_MATRIX sqr bug
al = algtableinit([matid(2),[0,0;1,0]],2);
m = [[1,1]~,[1,0]~;[0,1]~,[0,0]~];
type(algsqr(al,m))=="t_MAT"

print("GW modified arguments");
L = [2,3];
Q = nfinit('z);
gw = nfgrunwaldwang(Q,L,[2 | p <- L],[1],'y);
print(L==[2,3]);

print("rnf/gchar confusion (#2473)");
F=nfinit(y^10 - y^9 - 11*y^8 + 13*y^7 + 35*y^6 - 43*y^5 - 36*y^4 + 41*y^3 + 10*y^2 - 7*y - 1);
id=idealprimedec(F, 5)[1];
A=alginit(F, [2, [[id], [1]], [1, 1, 1, 1, 0, 1, 1, 1, 1, 1]],,0);
type(algsplittingfield(A).pol)

\\algpoleval type check
setrand(1);
nf = nfinit(y^2-5);
al = alginit(nf,[y,-1]);
a = [1..8]~;
pol = algcharpoly(al,a);
algpoleval(al,pol,a)==0
algpoleval(al,pol,[;])
pol = algcharpoly(al,a,,1);
algpoleval(al,pol,a)==0
ma = algtomatrix(al,a,1);
algpoleval(al,pol,[a,ma])==0

\\not implemented
al = algtableinit([Mat(1)]);
al2 = algtensor(al,al);
al = algtableinit([Mat(1)],2);
al2 = algtensor(al,al);

print("maxord flag");
setrand(1);
p = randomprime(10^60);
q = randomprime(10^60);
D = p*q;
Q = nfinit(y);
alg = alginit(Q, [-1,-D],,0);
alghasse(alg,idealprimedec(Q,2)[1])
alg = alginit(Q, [-D,-1],,0);
alghassef(alg)
algindex(alg)
algramifiedplaces(alg)
nb = 100;
Lpr = [idealprimedec(Q,p)[1] | p <- primes(nb)];
Lh = [1/2 | pr <- Lpr];
alg = alginit(Q,[2,[Lpr,Lh],[0]],,0);
algbasis(alg) == matid(4)
alg = alginit(Q,[2,[Lpr,Lh],[0]],,1);
algdisc(alg) == - 2^4 * vecprod(primes(nb))^2
nf = nfinit(y^2+y+1);
al1 = alginit(nf,[p,-1]);
P = x^3-q;
rnf = rnfinit(nf,P);
al2 = alginit(rnf, [y*x,-1]);
\\al = algtensor(al1,al2,0); \\too long: 5s ; find a replacement test
mt = qamt(-D,-1);
al = alginit(Q,mt,,0);
r = randomprime(2^20);
alg = alginit(Q, [-1,-D*r^2],,0);
algbasis(alg) == matid(4)
alg = alginit(Q, [-1,-D*r^2],,1);
algbasis(alg) != matid(4)
algdisc(alg)%r != 0
p = randomprime([2^21,2^25]);
q = randomprime([2^21,2^25]);
alg = alginit(Q, [-1,-p*q^2],,2);
algbasis(alg) == matid(4)
algdisc(alg)%q == 0
alghasse(alg, idealprimedec(Q,q)[1]) == 0
\\example from Mickael Montessinos
z = 'z;
{mu=z^2 - 11002587770426695439129164047/1737260475313383983450*z +
6545246845996161752942936173068414/868630237656691991725;}
K=nfinit(mu)[1];
{a=Mod(-69086050716125587677489266397120505050532860277271020543856131112359472587249662596671157785576853587734894096237342986133482192522376606166312001078976428714783686509419622091061230480777960739344862221463*z
+
17453734866925059675086784329655571003277844536255892750682707497315715224615308957737819137643460547574317397225176742916615587901357323690105414054047014710629006726626291809468283041248154785368119402124315203921703504063895910608939,
z^2 - z - 92872063185781870942858883351009206258508089837924172);}
{b=Mod(-1035464865145958113498386343817353611512208005431706435751486532489352629097073992049773530058639270194660491130007336201173807672154956934359635775222574770842789685409237393049361814801314845912471006607076157129175506026341062584943375971447249024144909990346373996322237069233036298963526709971155410826143109337077867748290573536280996027777874316518815261022303435909974867174963523171489569835351872410087590894716041063648356690146913649149359434604377562735743595799274721681898135071375254453371875705493674846620286422579264452470750164641481757486*z
+
266243872090899957611917622625085819912625185933035287288945961691311901961554524941870710600171398449371439959525398334037907904475189170784501224724867894108420227524056470930694025544733616206766010919775405696175885593113192582156794019402900498167170603497231935265954237883930313410463105795157319796329621453835830351071644066742681126927422850589151914181348581283512688655651184057188621686726190394203802175891713113867315165212798716829664371534269293476510694504642348414507472514058827790192348669455400772967473649404232753822915836606995513095160066145989929210528668576404,
z^2 - z - 92872063185781870942858883351009206258508089837924172);}
al=alginit(K,[a,b],,0);

print("segfault in algsubalg for invalid input");
nf = nfinit(y);
al = alginit(nf, [-1,-1]);
alt = algtableinit(algmultable(al),3);
B = [1, 0, 0, 0; 0, 7625597484987, 6608353175723, 6996189950772; 0, 0, 1, 0; 0, 0, 0, 1];
alB = algsubalg(alt,B)[1];
algdim(alB)

print("bad inputs algquattobasis / algbasistoquat / algisquatalg");
nf = nfinit(y);
alg = alginit(nf,[-1,-1]);
algquattobasis(alg,[1,2,3]~);
algquattobasis(alg,1+x-x^2);
algquattobasis(alg,[1+'u,0,0,0]~);
algquattobasis([],[1,y,0,-1]~);
algbasistoquat(alg,[1,2,3]~);
algbasistoquat(alg,[1..4]);
algbasistoquat([],[1..4]~);
mt = algmultable(alg);
alg = alginit(nf, mt);
algquattobasis(alg,[1,y,0,-1]~);
algbasistoquat(alg,[1..4]~);
talg = algtableinit(mt);
algquattobasis(talg,[1,y,0,-1]~);
algbasistoquat(talg,[1..4]~);
H = alginit(1.,1/2);
algquattobasis(H,[1,2,0,-1]~);
algbasistoquat(H,[1..4]~);
alg = alginit(nf,3);
algquattobasis(alg,[1,2,0,-1]~);
algbasistoquat(alg,[1..4]~);
algisquatalg([]);

print("integral coefficients in alginit");
fewops(alg) =
{
  my(a,b,nrd);
  algramifiedplaces(alg);
  a = algrandom(al,10);
  b = algrandom(al,10);
  algmul(al,a,b);
  algadd(al,a,b);
  nrd = algnorm(al,a);
  trd = algtrace(al,a);
  algcharpoly(al,b);
  print(algcharpoly(al,a) == x^2 - trd*x + nrd);
  algtomatrix(al,a);
  print(algsqr(al,a) - algmul(al,algeltfromnf(al,trd),a) + algeltfromnf(al,nrd) == 0);
  1
};
nf = nfinit(y^2-5);
alg = alginit(nf, [-1,(1+y)/2]);
fewops(alg);
alg = alginit(nf, [(1+y)/2, -1]);
fewops(alg);
rnf = rnfinit(nf, x^2-(1+y)/2);
alg = alginit(rnf, [-x,-1]);
fewops(alg);
rnf = rnfinit(nf, x^2+1);
alg = alginit(rnf, [-x,(1+y)/2]);
fewops(alg);

print("quaternion algebra (a,b) with a square");
testasq(pol) =
{
  print("pol=",pol);
  my(nf,a,b,al,d,pr,ii,jj,kk,w,data,relmt,mt,w2,talg);
  nf = nfinit(pol);
  d = poldegree(pol);
  a = (3+y)^2;
  b = -y-7;
  al = alginit(nf, [a,b]);
  print(algdegree(al)==2);
  print(algdim(al)==4);
  print(algdim(al,1)==4*d);
  iferr(algaut(al); print(0), E, print(1));
  iferr(algb(al); print(0), E, print(1));
  print(poldegree(algsplittingfield(al).pol)==2);
  print("splitting data");
  data = algsplittingdata(al);
  relmt = algrelmultable(al);
  print(algramifiedplaces(al)==[]);
  print(alghassef(al)==[[],Vecsmall([])]);
  print(alghassei(al)==Vecsmall(vector(nf.r1,i,0)));
  print("pr");
  pr = idealprimedec(nf,2)[1];
  print(alghasse(al,pr)==0);
  print(alghasse(al,1)==0);
  print(algindex(al,pr)==1);
  print(algindex(al,1)==1);
  print(algindex(al)==1);
  print(algisdivision(al,pr)==0);
  print(algisdivision(al,1)==0);
  print(algisdivision(al)==0);
  print(algisramified(al,pr)==0);
  print(algisramified(al,1)==0);
  print(algisramified(al)==0);
  print(algissplit(al,pr)==1);
  print(algissplit(al,1)==1);
  print(algissplit(al)==1);
  print("i j k");
  ii = algquattobasis(al,[0,1,0,0]~);
  jj = algquattobasis(al,[0,0,1,0]~);
  kk = algquattobasis(al,[0,0,0,1]~);
  w = algrandom(al,10);
  mt = algmultable(al);
  print(#mt==4*d);
  print(algisassociative(mt));
  talg = algtableinit(mt);
  print(!algiscommutative(talg));
  print(algissimple(talg));
  print(algsqr(al,ii) == algeltfromnf(al,a));
  print(algsqr(al,jj) == algeltfromnf(al,b));
  print(algsqr(al,kk) == algeltfromnf(al,-a*b));
  print(algmul(al,ii,jj) == kk);
  print(algmul(al,jj,ii) == -kk);
  print(algnorm(al,ii) == -Mod(a,pol));
  print(algtrace(al,ii) == 0);
  print(algcharpoly(al,jj) == x^2 - Mod(b,pol));
  print(algpoleval(al, algcharpoly(al,w), w) == 0);
  print("w w2 algtomatrix");
  w2 = algrandom(al,20);
  print(algtomatrix(al,w)*algtomatrix(al,w2)
    == algtomatrix(al,algmul(al,w,w2)));
  print(algtomatrix(al,w)+algtomatrix(al,w2)
    == algtomatrix(al,algadd(al,w,w2)));
  print(algtomatrix(al,w,1)*algtomatrix(al,w2,1)
    == algtomatrix(al,algmul(al,w,w2),1));
  print(algtomatrix(al,w,1)+algtomatrix(al,w2,1)
    == algtomatrix(al,algadd(al,w,w2),1));
  \\print(algdisc(al,1) == matrix(0,2));
  print(matsize(algbasis(al))==[4*d,4*d]);
  print(algbasis(al)*alginvbasis(al) == 1);
  print(algbasis(al)!=1);
  print(abs(algdisc(al)) == 2^(4*d)*nf.disc^4);
  print(algisquatalg(al) == [a,b]);
  print(algquattobasis(al, algbasistoquat(al,w)) == w);
  localbitprec(256); algnewprec(al);
};
testasq(y);
testasq(y^2-2);
testasq(y^3-y-1);

print("segfault algquattobasis"); \\ James Rickards
setrand(7);
F=nfinit(y);
A=alginit(F, [-133, 1461405]);
algbasistoquat(A, [-64899, -75545, -8782, 138586]~);
algbasistoquat(A, algquattobasis(A, [1,0,1,1]~))
algbasistoquat(A, algquattobasis(A, [1,1,1,0]~))
alginvol([]);
alginvol([],[1,2,3,4]~);
alginvol(,[1..5]~);
al = alginit(nfinit(y),[-1,-1]);
alginvol(al,[1,2,3]~);

print("bad inputs algskolemnoether");
nf = nfinit(y^2-3);
al = alginit(nf, [1-y,-2]);
u = [1..8]~;
fu = u; fu[1]++;
algskolemnoether(al,u,fu); \\not homomorphism
Q = nfinit(y);
al = alginit(Q,3);
u = algalgtobasis(al,[0,0,1]~);
v = algpoleval(al,x^2+x+1,u); \\not simple
fv = algpoleval(al,3-x,v);
algskolemnoether(al,v,fv); \\infinite loop
algskolemnoether(al,v,[]);
algskolemnoether(al,v,[]~);
algskolemnoether(al,[]~,fv);
algskolemnoether(al,[v,v],[fv,[]]);
almt = algtableinit(qamt(-2,-7));
algskolemnoether(almt,[1..4]~,[1..4]~)
algskolemnoether([],[1..4]~,[1..4]~)
H = alginit(1.,1/2);
a = [1.,2.,3.,4.]~;
fa = alginvol(,a);
algskolemnoether(H,a,fa);

print("quatalg [a,b] with a in basis form");
nf = nfinit(y^3-9);
a = [1,2,3]~;
b = [4,5,6]~;
al = 'al;
al = alginit(nf, [a,b]);
apply(type,algisquatalg(al))
al2 = alginit(nf, [nfbasistoalg(nf,a),b]);
algisisom(al,al2)
