`type/pN2spart` := proc(spart)
    return isSpartValid(spart);
end proc:

`type/a_indet` := proc(a) local bool;
	if convert(a,string)[1] = "a" and type(a,indexed) then bool:=true; else bool:=false; end if;
	return bool;
end proc:

`type/b_indet` := proc(a) local bool;
	if convert(a,string)[1] = "b" and type(a,indexed) then bool:=true; else bool:=false; end if;
	return bool;
end proc:
`type/z_var` := proc(expr) local bool;
	bool:=false;
	if convert(expr, string)[1]= "z" and type(expr, commutative) and nops(indets(expr)) <2 and degree(expr)=1 then bool:=true; end if;
	return bool;
end proc:

`type/AC_phi` := proc(expr) local bool;
	bool:=false;
	if convert(expr, string)[1..3] = "phi" and type(expr, anticommutative) and nops(indets(expr)) <2 then bool:= true; end if;
	return bool;
end proc:

`type/AC_theta` := proc(expr) local bool;
	bool:=false;
	if convert(expr, string)[1..3] = "the" and type(expr, anticommutative) and nops(indets(expr)) <2 then bool:= true; end if;
	return bool;
end proc:

`type/powersum_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..2] = "p[" and type(expr,indexed) then bool := true; else bool:= false; end if;
    return bool;
end proc:

`type/monomial_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..2] = "m[" and type(expr, indexed) then bool := true; else bool := false; end if;
    return bool;
end proc:

`type/homogeneous_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..2] = "h[" and type(expr, indexed) then bool := true; else bool := false; end if;
    return bool;
end proc:

`type/elementary_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..2] = "e[" and type(expr, indexed) then bool := true; else bool := false; end if;
    return bool;
end proc:
`type/g_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..2] = "g[" and type(expr, indexed) then bool := true; else bool := false; end if;
    return bool;
end proc:

`type/schur_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..2] = "s[" and convert(expr,string)[2] <> "b" and type(expr, indexed) then bool := true; else bool := false; end if;
    return bool;
end proc:

`type/schurEtoile_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..4] = "sEt[" and type(expr, indexed) then bool := true; else bool := false; end if;
    return bool;
end proc:

`type/schurbar_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..5] = "sbar[" and type(expr, indexed) then bool := true; else bool := false; end if;
    return bool;
end proc:
`type/schurbarEtoile_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..7] = "sbarEt[" and type(expr, indexed) then bool := true; else bool := false; end if;
    return bool;
end proc:

`type/ep_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..3] = "ep[" and type(expr, indexed) then bool := true; else bool := false; end if;
    return bool;
end proc:

`type/ph_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..3] = "ph[" and type(expr, indexed) then bool := true; else bool := false; end if;
    return bool;
end proc:

`type/jack_symbolic` := proc(expr) local bool;
	if convert(expr,string)[1..2] = "P[" and type(expr, indexed) then bool := true; else bool := false; end if;
end proc:

`type/superbase` := proc(expr) local bool;
	bool:= type(expr, monomial_symbolic) or type(expr, powersum_symbolic) or type(expr, elementary_symbolic) or type(expr, homogeneous_symbolic) or type(expr, g_symbolic) or type(expr, schur_symbolic) or type(expr, schurEtoile_symbolic) or type(expr, schurbar_symbolic) or type(expr, schurbarEtoile_symbolic) or type(expr, ep_symbolic) or type(expr, ph_symbolic) or type(expr, jack_symbolic);
	return bool;
end proc:

`type/superindexed`:= proc(expr) local bool;
	bool:= type(expr, indexed) and type([op(expr)], pN2spart);
	return bool;
end proc:

super_whattype:= proc(expr)
	local element_of_basis, sample, types, which_one, the_one;
	element_of_basis:= indets(expr, superbase);
	if nops(element_of_basis) = 0 then return other; end if;
	sample:= element_of_basis[1];
	types:= [
				powersum_symbolic,
				monomial_symbolic,
				homogeneous_symbolic,
				elementary_symbolic,
				g_symbolic,
				schur_symbolic,
				schurEtoile_symbolic,
				schurbar_symbolic,
				schurbarEtoile_symbolic,
				ep_symbolic,
				ph_symbolic,
				jack_symbolic
			];
	which_one:= map(x-> type(sample, x), types);
	the_one:= ListTools:-Search(true, which_one);
	return types[the_one];
end proc:


type $SS <struct {
        @real f32,
        @imag f32}>
var $sconst1 <struct {
        @f11 i32,
        @f22 <$SS>,
        @f33 i32,
        @f44 i32,
        @f55 f32,
        @f66 f32}> = [ 6=1007.0f, 2= [1=11.11f, 2=22.22f], 3=-273, 4=75, 1=1425926, 5=6023.0f ]
func $printf (var %p1 <* i8>)void
func $main ( ) i32 {
   call &printf (addrof a32 $sconst1)
   return (constval i32 0) }

 # EXEC: %irbuild Main.mpl
 # EXEC: %irbuild Main.irb.mpl
 # EXEC: %cmp Main.irb.mpl Main.irb.irb.mpl


# This defines the chain complex version of the Barratt-Eccles operad.
# Basis elements of E(A) are represented by expressions T(...), where
# there is at least one argument, each argument is a list containing
# each element of A precisely once, and no two adjacent arguments are
# the same.

`is_element/barratt_eccles` := (A::set) -> proc(x)
 local y,z,i;

 if x = 0 then return true; fi;

 if type(x,`+`) then
  return `and`(op(map(`is_element/barratt_eccles`(A),[op(x)])));
 fi;

 if type(x,`*`) then
  y,z := selectremove(type,[op(x)],integer);
  return (nops(z) = 1 and `is_element/barratt_eccles`(A)(z[1]));
 fi;

 if not type(x,specfunc(T)) then return false; fi;

 if nops(T) = 0 then return false; fi;

 for i from 1 to nops(x) do
  if not(`is_element/ord`(A)(op(i,x))) then
   return false;
  fi;
 od;

 for i from 1 to nops(x) - 1 do
  if op(i,x) = op(i+1,x) then return false; fi;
 od;

 return true;
end:

# Auxiliary function feeding into `diff/barratt_eccles`

`diff0/barratt_eccles` := (A::set) -> proc(x)
 local y,n,i;

 y := 0;
 n := nops(x);

 for i from 1 to n do
  if 1 < i and i < n and op(i-1,x) = op(i,x) then
   continue;
  fi;

  y := y + (-1)^(i-1) * T(op(1..i-1,x),op(i+1..n,x));
 od;

 return y;
end:

# Differential on the chain complex
`diff/barratt_eccles` := (A::set) -> apply_linear(`diff0/barratt_eccles`(A));

# Auxiliary function feeding into `deg/barratt_eccles`
`deg0/barratt_eccles` := (A) -> (x) -> nops(x) - 1;

# Degree function
`deg/barratt_eccles` := (A) -> apply_deg(`deg0/barratt_eccles`(A));

# This is the circle product for the operad structure.
# It is assumed that B is a subset of A and u is in E(A/B) and v is in E(B),
# where A/B is implemented as A \ B u {B}.

`o0/barratt_eccles` := (A,B) -> proc(u,v)
 local d,e,SS,x,s,p,w,u0,v0,w0,i;

 d := nops(u) - 1;
 e := nops(v) - 1;
 SS := `list_elements/shuffles`(d,e);

 x := 0;

 for s in SS do
  p := `to_grid_path/shuffles`(d,e)(s);
  w := NULL;
  for i from 0 to d+e do
   u0 := op(p[i][1]+1,u);
   v0 := op(p[i][2]+1,v);
   w0 := subs(B = op(v0),u0);
   w := w,w0;
  od:
  x := x + `sgn/shuffles`(d,e)(s) * T(w);
 od:

 return x;
end:

`o/barratt_eccles` := (A,B) -> apply_bilinear(`o0/barratt_eccles`(A,B));

# We now have various functions related to an interesting filtration
# of the operad.
`flip_count/barratt_eccles` := (A::set) -> proc(x)
 local m,a,b,k,rr,i,r0,r1;

 m := table():
 for a in A do
  for b in A do
   m[a,b] := 0;
  od;
 od;

 k := nops(x);
 rr := map(`rank_table/ord`(A),[op(x)]);

 for i from 1 to k-1 do
  r0 := rr[i];
  r1 := rr[i+1];

  for a in A do
   for b in A do
    if (r1[b] - r1[a]) * (r0[b] - r0[a]) < 0 then
     m[a,b] := m[a,b] + 1;
    fi;
   od;
  od;
 od;

 return eval(m);
end:

`flip_count_matrix/barratt_eccles` := (A::set) -> proc(u,s_)
 local m;
 m := `flip_count/barratt_eccles`(A)(args);
 return Matrix([seq([seq(m[a,b],b in A)],a in A)]);
end:

`max_flip_count/barratt_eccles` := (A::set) -> proc(x)
 local m,mm,a,b;

 m := `flip_count/barratt_eccles`(A)(x);

 mm := 0;
 for a in A do
  for b in A do
   mm := max(mm,m[a,b]);
  od;
 od;

 return mm;
end:

`is_member/barratt_eccles_cells` := (A::set) -> proc(ms)
 local m,s,AA,a,b;

 if not(type(ms,list) and nops(ms) = 2) then return false; fi;

 m,s := op(ms);

 if not(`is_element/ord`(A)(s)) then return false; fi;
 if not(type(m,table)) then return false; fi;

 AA := {seq(seq([a,b],b in A),a in A)};
 if {indices(m)} <> AA then return false; fi;

 for a in A do
  for b in A do
   if not(type(m[a,b],nonnegint)) then return false; fi;
  od:
 od:

 for a in A do
  if m[a,a] <> 0 then return false; fi;
  for b in A do
   if m[a,b] <> m[b,a] then return false; fi;
  od;
 od;

 return true;
end:

`is_cell_member/barratt_eccles` := (A::set) -> (ms) -> proc(x)
 local m0,m1,s,a,b,y,z;

 if x = 0 then return true; fi;
 if type(x,`+`) then
  return `and`(seq(`is_cell_member/barratt_eccles`(A)(ms)(y),y in x));
 fi;
 if type(x,`*`) then
  y,z := selectremove(type,[op(x)],integer);
  if nops(z) = 1 then
   return `is_cell_member/barratt_eccles`(A)(ms)(z[1]);
  else
   return false;
  fi;
 fi;

 m0,s := op(ms);
 m1 := `flip_count/barratt_eccles`(A)(T(op(x),s));

 for a in A do
  for b in A do
   if m1[a,b] > m0[a,b] then return false; fi;
  od;
 od;

 return true;
end:

`filtration0/barratt_eccles` := (A::set) -> proc(x)
 local m,m_max,s,rr,k,i,r0,r1,a,b;

 if type(x,integer) then return 0; fi;

 return 1 + `max_flip_count/barratt_eccles`(A)(x);
end:

`filtration/barratt_eccles` := (A::set) ->
 apply_max_deg(`filtration0/barratt_eccles`(A));