text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

AVX_4x64f.setRules(rec(
  binrules := [ rec(
          perm := rec(
              spl := Tensor(
                  L(4, 2),
                  I(2)
                ),
              l := 1,
              N := 4,
              n := 2,
              r := 2 ),
          instr := [ rec(
                  instr := vpermf128_4x64f,
                  p := [ 1, 3 ] ), rec(
                  instr := vpermf128_4x64f,
                  p := [ 2, 4 ] ) ],
          v := 4,
          vperm := VPerm(Tensor(
                L(4, 2),
                I(2)
              ), (y, x) -> chain(assign(vref(y, 0, 4), vpermf128_4x64f(vref(x, 0, 4), vref(x, 4, 4), [ 1, 3 ])), assign(vref(y, 4, 4), vpermf128_4x64f(vref(x, 0, 4), vref(x, 4, 4), [ 2, 4 ]))), 4, 2) ), rec(
          perm := rec(
              spl := L(8, 4),
              l := 1,
              N := 8,
              n := 4,
              r := 1 ),
          instr := [ rec(
                  instr := vunpacklo_4x64f,
                  p := [  ] ), rec(
                  instr := vunpackhi_4x64f,
                  p := [  ] ) ],
          v := 4,
          vperm := VPerm(Tensor(
                L(4, 2),
                I(2)
              ), (y, x) -> chain(assign(vref(y, 0, 4), vpermf128_4x64f(vref(x, 0, 4), vref(x, 4, 4), [ 1, 3 ])), assign(vref(y, 4, 4), vpermf128_4x64f(vref(x, 0, 4), vref(x, 4, 4), [ 2, 4 ]))), 4, 2) *
            VPerm(Tensor(
                L(4, 2),
                I(2)
              ) *
              L(8, 4), (y, x) -> chain(assign(vref(y, 0, 4), vunpacklo_4x64f(vref(x, 0, 4), vref(x, 4, 4), [  ])), assign(vref(y, 4, 4), vunpackhi_4x64f(vref(x, 0, 4), vref(x, 4, 4), [  ]))), 4, 4.2000000000000002) *
            VTensor(I(2), 4) ), rec(
          perm := rec(
              spl := L(8, 2),
              l := 1,
              N := 8,
              n := 2,
              r := 1 ),
          instr := [ rec(
                  instr := vunpacklo_4x64f,
                  p := [  ] ), rec(
                  instr := vunpackhi_4x64f,
                  p := [  ] ) ],
          v := 4,
          vperm := VTensor(I(2), 4) *
            VPerm(L(8, 2) *
              Tensor(
                L(4, 2),
                I(2)
              ), (y, x) -> chain(assign(vref(y, 0, 4), vunpacklo_4x64f(vref(x, 0, 4), vref(x, 4, 4), [  ])), assign(vref(y, 4, 4), vunpackhi_4x64f(vref(x, 0, 4), vref(x, 4, 4), [  ]))), 4, 4.2000000000000002) *
            VPerm(Tensor(
                L(4, 2),
                I(2)
              ), (y, x) -> chain(assign(vref(y, 0, 4), vpermf128_4x64f(vref(x, 0, 4), vref(x, 4, 4), [ 1, 3 ])), assign(vref(y, 4, 4), vpermf128_4x64f(vref(x, 0, 4), vref(x, 4, 4), [ 2, 4 ]))), 4, 2) ) ],
  unrules := [  ],
  x_I_vby2 := [ [ rec(
              instr := vpermf128_4x64f,
              p := [ 1, 3 ] ), rec(
              instr := vperm2_4x64f,
              p := [ 1, 2, 3, 4 ] ) ], [ rec(
              instr := vpermf128_4x64f,
              p := [ 2, 3 ] ), rec(
              instr := vpermf128_4x64f,
              p := [ 2, 4 ] ) ] ] ));
AVX_8x32f.setRules(rec(
  binrules := [ rec(
          perm := rec(
              spl := Tensor(
                  L(4, 2),
                  I(4)
                ),
              l := 1,
              N := 4,
              n := 2,
              r := 4 ),
          instr := [ rec(
                  instr := vpermf128_8x32f,
                  p := [ 1, 3 ] ), rec(
                  instr := vpermf128_8x32f,
                  p := [ 2, 4 ] ) ],
          v := 8,
          vperm := VPerm(Tensor(
                L(4, 2),
                I(4)
              ), (y, x) -> chain(assign(vref(y, 0, 8), vpermf128_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 1, 3 ])), assign(vref(y, 8, 8), vpermf128_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 2, 4 ]))), 8, 2) ), rec(
          perm := rec(
              spl := L(16, 8),
              l := 1,
              N := 16,
              n := 8,
              r := 1 ),
          instr := [ rec(
                  instr := vunpacklo_8x32f,
                  p := [  ] ), rec(
                  instr := vunpackhi_8x32f,
                  p := [  ] ) ],
          v := 8,
          vperm := VPerm(Tensor(
                L(4, 2),
                I(4)
              ), (y, x) -> chain(assign(vref(y, 0, 8), vpermf128_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 1, 3 ])), assign(vref(y, 8, 8), vpermf128_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 2, 4 ]))), 8, 2) *
            VPerm(Tensor(
                L(4, 2),
                I(4)
              ) *
              L(16, 8), (y, x) -> chain(assign(vref(y, 0, 8), vunpacklo_8x32f(vref(x, 0, 8), vref(x, 8, 8), [  ])), assign(vref(y, 8, 8), vunpackhi_8x32f(vref(x, 0, 8), vref(x, 8, 8), [  ]))), 8, 4.2000000000000002) *
            VTensor(I(2), 8) ), rec(
          perm := rec(
              spl := Tensor(
                  L(8, 4),
                  I(2)
                ),
              l := 1,
              N := 8,
              n := 4,
              r := 2 ),
          instr := [ rec(
                  instr := vshuffle_8x32f,
                  p := [ 1, 2, 1, 2 ] ), rec(
                  instr := vshuffle_8x32f,
                  p := [ 3, 4, 3, 4 ] ) ],
          v := 8,
          vperm := VPerm(Tensor(
                L(4, 2),
                I(4)
              ), (y, x) -> chain(assign(vref(y, 0, 8), vpermf128_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 1, 3 ])), assign(vref(y, 8, 8), vpermf128_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 2, 4 ]))), 8, 2) *
            VPerm(Tensor(
                L(4, 2),
                I(4)
              ) *
              Tensor(
                L(8, 4),
                I(2)
              ), (y, x) -> chain(assign(vref(y, 0, 8), vshuffle_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 1, 2, 1, 2 ])), assign(vref(y, 8, 8), vshuffle_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 3, 4, 3, 4 ]))), 8, 4.2000000000000002) *
            VTensor(I(2), 8) ), rec(
          perm := rec(
              spl := Tensor(
                  L(8, 2),
                  I(2)
                ),
              l := 1,
              N := 8,
              n := 2,
              r := 2 ),
          instr := [ rec(
                  instr := vshuffle_8x32f,
                  p := [ 1, 2, 1, 2 ] ), rec(
                  instr := vshuffle_8x32f,
                  p := [ 3, 4, 3, 4 ] ) ],
          v := 8,
          vperm := VTensor(I(2), 8) *
            VPerm(Tensor(
                L(8, 2),
                I(2)
              ) *
              Tensor(
                L(4, 2),
                I(4)
              ), (y, x) -> chain(assign(vref(y, 0, 8), vshuffle_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 1, 2, 1, 2 ])), assign(vref(y, 8, 8), vshuffle_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 3, 4, 3, 4 ]))), 8, 4.2000000000000002) *
            VPerm(Tensor(
                L(4, 2),
                I(4)
              ), (y, x) -> chain(assign(vref(y, 0, 8), vpermf128_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 1, 3 ])), assign(vref(y, 8, 8), vpermf128_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 2, 4 ]))), 8, 2) ), rec(
          perm := rec(
              spl := L(16, 2),
              l := 1,
              N := 16,
              n := 2,
              r := 1 ),
          instr := [ rec(
                  instr := vshuffle_8x32f,
                  p := [ 1, 3, 1, 3 ] ), rec(
                  instr := vshuffle_8x32f,
                  p := [ 2, 4, 2, 4 ] ) ],
          v := 8,
          vperm := VTensor(I(2), 8) *
            VPerm(L(16, 2) *
              Tensor(
                L(4, 2),
                I(4)
              ), (y, x) -> chain(assign(vref(y, 0, 8), vshuffle_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 1, 3, 1, 3 ])), assign(vref(y, 8, 8), vshuffle_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 2, 4, 2, 4 ]))), 8, 4.2000000000000002) *
            VPerm(Tensor(
                L(4, 2),
                I(4)
              ), (y, x) -> chain(assign(vref(y, 0, 8), vpermf128_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 1, 3 ])), assign(vref(y, 8, 8), vpermf128_8x32f(vref(x, 0, 8), vref(x, 8, 8), [ 2, 4 ]))), 8, 2) ) ],
  unrules := [ rec(
          perm := rec(
              spl := Tensor(
                  I(2),
                  L(4, 2)
                ),
              l := 2,
              N := 4,
              n := 2,
              r := 1 ),
          instr := rec(
              instr := vperm_8x32f,
              p := [ 1, 3, 2, 4 ] ),
          v := 8,
          vperm := VPerm(Tensor(
                I(2),
                L(4, 2)
              ), (y, x) -> assign(vref(y, 0, 8), vperm_8x32f(vref(x, 0, 8), [ 1, 3, 2, 4 ])), 8, 0.90000000000000002) ), rec(
          perm := rec(
              spl := Tensor(
                  L(4, 2),
                  I(2)
                ),
              l := 1,
              N := 4,
              n := 2,
              r := 2 ),
          instr := rec(
              instr := vcxtr_8x32f,
              p := [  ] ),
          v := 8,
          vperm := VPerm(Tensor(
                L(4, 2),
                I(2)
              ), (y, x) -> assign(vref(y, 0, 8), vcxtr_8x32f(vref(x, 0, 8), [  ])), 8, 4.5) ) ],
  x_I_vby2 := [ [ rec(
              instr := vpermf128_8x32f,
              p := [ 1, 3 ] ), rec(
              instr := vpermf128_8x32f,
              p := [ 1, 4 ] ) ], [ rec(
              instr := vpermf128_8x32f,
              p := [ 2, 3 ] ), rec(
              instr := vpermf128_8x32f,
              p := [ 2, 4 ] ) ] ] ));


text:
#!/usr/bin/gap

# time gap -o 8g clifford.gap

# Build clifford groups, up to 3 qubits, and
# search for T operators defined by field extensions......

Print("running clifford.gap\n");;

# See:
# https://www.mathstat.dal.ca/~selinger/papers/clifford.pdf

r2 := Sqrt(2);;
ir2 := 1/r2;;

i := [[1, 0], [0, 1]];;
w := [[E(4), 0], [0, E(4)]];;
x := [[0, 1], [1, 0]];;
z := [[1, 0], [0, -1]];;
s := [[1, 0], [0, E(4)]];;
h := [[ir2, ir2], [ir2, -ir2]];;

Cliff1 := Group(w, s, h);; # Order 192
Pauli1 := Group(w, x, z);; # Order 32

for U in Cliff1 do
    found := false;;
    #Udag := Inverse(U);
    #Print("found? ");
    for g in Pauli1 do
        if (U*g*Inverse(U)*Inverse(g) in Pauli1)  then found:=true; break; fi;
    od;
    if not found then Print("Not found\n"); fi;
od;

xi := KroneckerProduct(x, i);;
ix := KroneckerProduct(i, x);;
zi := KroneckerProduct(z, i);;
iz := KroneckerProduct(i, z);;
si := KroneckerProduct(s, i);;
is := KroneckerProduct(i, s);;
hi := KroneckerProduct(h, i);;
ih := KroneckerProduct(i, h);;
wi := KroneckerProduct(w, i);;

cz := [
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, -1]];;

Cliff2 := Group(si, is, hi, ih, wi, cz);; # Order 92160
#for g in Cliff2 do Print(g, "\n"); od;
Pauli2 := Group(wi, xi, ix, zi, iz);;

# Works:
for U in Cliff2 do
    found := false;;
    #Udag := Inverse(U);
    #Print("found? ");
    for g in Pauli2 do
        if (U*g*Inverse(U)*Inverse(g) in Pauli2)  then found:=true; break; fi;
    od;
    if not found then Print("Not found\n"); fi;
od;

a := [
    [0, 1, 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
    [-1, 0, 0, 0]];; # a in G2 = true

#Print(a*a, "\n");
#Print(a*a*a, "\n");
#Print(a*a*a*a, "\n");

# Print(Order(G2));

xii := KroneckerProduct(xi, i);;
ixi := KroneckerProduct(i, xi);;
iix := KroneckerProduct(i, ix);;

zii := KroneckerProduct(zi, i);;
izi := KroneckerProduct(i, zi);;
iiz := KroneckerProduct(i, iz);;

sii := KroneckerProduct(si, i);;
isi := KroneckerProduct(i, si);;
iis := KroneckerProduct(i, is);;

hii := KroneckerProduct(hi, i);;
ihi := KroneckerProduct(i, hi);;
iih := KroneckerProduct(i, ih);;

wii := KroneckerProduct(wi, i);;

icz := KroneckerProduct(i, cz);;
czi := KroneckerProduct(cz, i);;

ca := [
    [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, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 0],
    [0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, -1, 0, 0, 0]];;

cb := [
    [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, 0, 1, 0],
    [0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, -1, 0, 0, 0],
    [0, 0, 0, 0, 0, -1, 0, 0]];;

cc := [
    [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, 0, 0, 1],
    [0, 0, 0, 0, -1, 0, 0, 0],
    [0, 0, 0, 0, 0, -1, 0, 0],
    [0, 0, 0, 0, 0, 0, -1, 0]];;

Tofolli := [
    [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, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 1, 0]];;

Cliff3 := Group(sii, isi, iis, hii, ihi, iih, wii, icz, czi);; # Order 743178240
Pauli3 := Group(wii, xii, ixi, iix, zii, izi, iiz);; # Order 256

# Print(Order(Pauli3), "\n");;

# ca in Cliff3 = false
# ca in third level of clifford hierarchy = true

Cliff3_12 := Group(sii, isi, hii, ihi, wii, czi);;
Cliff3_13 := Group(sii, iis, hii, iih, wii);; # cz on 1&3 ??
Cliff3_23 := Group(isi, iis, ihi, iih, wii, icz);;

#SmCliff3 := Group(sii, isi, iis, hii, ihi, iih, icz, czi);; # Order 743178240

Print("warming up...\n");
Order(Cliff3);; # need this line otherwise membership test eats all memory...!
Print("Ok\n");

in_third_level := function(U)
    # Is U in the third level of the clifford hierarchy ?
    local A;
    for g in Pauli3 do
        A := U*g*Inverse(U)*Inverse(g);
        if A in Cliff3_12 then continue; fi;
        if A in Cliff3_13 then continue; fi;
        if A in Cliff3_23 then continue; fi;
        if A in Cliff3 then continue; fi;
        return false; # no
    od;
    return true; # yes
end;;

Print("in_third_level(ca):", in_third_level(ca), "\n"); # true
Print("in_third_level(cb):", in_third_level(cb), "\n"); # true
Print("in_third_level(cc):", in_third_level(cc), "\n"); # true
Print("in_third_level(Tofolli):", in_third_level(Tofolli), "\n"); # true
Print("in_third_level(Tofolli*ca):", in_third_level(Tofolli*ca), "\n"); # false

U3 := [
    [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, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0]];

Print("# Where do control control 1-qubit Pauli gates live ?\n");
for g in Pauli1 do
    #Print(g, "\n");
    U3{[7,8]}{[7,8]} := g;
    if U3 in Pauli3 then Print("1\c"); continue; fi;
    if U3 in Cliff3 then Print("2\c"); continue; fi;
    if in_third_level(U3) then Print("3\c"); else Print(".\c"); fi;
od;
Print("\n");

Print("# Where do control control 1-qubit clifford gates live ?\n");
for g in Cliff1 do
    #Print(g, "\n");
    U3{[7,8]}{[7,8]} := g;
    if U3 in Pauli3 then Print("1\c"); continue; fi;
    if U3 in Cliff3 then Print("2\c"); continue; fi;
    if in_third_level(U3) then Print("3\c"); else Print(".\c"); fi;
od;
Print("\n");

Print("# Where do control 2-qubit Pauli gates live ?\n");
for g in Pauli2 do
    #Print(g, "\n");
    U3{[5,6,7,8]}{[5,6,7,8]} := g;
    if U3 in Pauli3 then Print("1\c"); continue; fi;
    if U3 in Cliff3 then Print("2\c"); continue; fi;
    if in_third_level(U3) then Print("3\c"); else Print(".\c"); fi;
od;
Print("\n");

Print("# Where do control 2-qubit clifford gates live ?\n");
for g in Cliff2 do
    #Print(g, "\n");
    U3{[5,6,7,8]}{[5,6,7,8]} := g;
    if U3 in Pauli3 then Print("1\c"); continue; fi;
    if U3 in Cliff3 then Print("2\c"); continue; fi;
    if in_third_level(U3) then Print("3\c"); else Print(".\c"); fi;
od;

Print("\n");

Print("Done.\n");

ext: gap

max_stars_repo_name: punkdit/bruhat

max_issues_repo_name: punkdit/bruhat

max_forks_repo_name: punkdit/bruhat


text:
#######################################################################
# Description: A function to calculate orbits, described in           #
#              section 3.1.                                           #
# Input: - integer 0 < a <= n + 1                                     #
#        - list of generators S                                       #
# Output: - list of integers 'orbit'                                  #
#######################################################################

OrbitSimple := function(a, S)
    local orbit, b, x;
    orbit := [a];
    for b in orbit do
        for x in S do
            if not b^x in orbit then
                Add(orbit, b^x);
            fi;
        od;
    od;
    return orbit;
end;

#######################################################################
#######################################################################

#######################################################################
# Description: A function to calculate orbits and belonging Schreier- #
#              vectors, described in section 3.1.                     #
# Input: - integer 0 < a <= n                                         #
#        - list of generators S                                       #
# Output: - list of integers 'orbit'                                  #
#         - belonging Schreier-vector 'sv' as list of integers        #
#######################################################################

OrbitSV := function(a, S, n)
    local orbit, b, x, i, sv;
    orbit := [a];  sv := [1..n]*0;  sv[a] := -1;
    for b in orbit do
        for i in [1..Length(S)] do
            if not b^S[i] in orbit then
                Add(orbit, b^S[i]);  sv[b^S[i]] := i;
            fi;
        od;
    od;
    return [orbit, sv];
end;

#######################################################################
#######################################################################

#######################################################################
# Description: A function to calculate transversal elements, described#
#              in section 3.1.                                        #
# Input: - orbit element b of type integer 0 < b <= n                 #
#        - Schreier-vector 'sv' as list of integers in range [1..n]   #
#        - list of generators S                                       #
# Output: - transversal element of b w.r.t. a and <S>                 #
#######################################################################

Transversal := function(b, sv, S)
    local u, k;
    if sv[b] = 0 then
        return false;
    fi;
    u := ();  k := sv[b];
    while not k = -1 do
        u := S[k]*u;  b := b^(S[k]^-1);  k := sv[b];
    od;
    return u;
end;

ext: gi

max_stars_repo_name: AlexanderKlemps/parallel-schreier-sims

max_issues_repo_name: AlexanderKlemps/parallel-schreier-sims

max_forks_repo_name: AlexanderKlemps/parallel-schreier-sims


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

Class(RulesRC, RuleSet);

RCExpandData := function(datavar)
   local rdatavar, r, i;
   Constraint(IsBound(datavar.value));
   rdatavar := Dat1d(TDouble, datavar.t.size*2);
   r := x->When(IsValue(x), ReComplex(Complex(x.v)), re(x));
   i := x->When(IsValue(x), ImComplex(Complex(x.v)), im(x));
   rdatavar.value := V(ConcatList(datavar.value.v, x->[r(x), i(x)]));
   return rdatavar;
end;

RewriteRules(RulesRC, rec(
 RC_Diag := Rule([RC, @(1,Diag)], e -> RCDiag(RCData(@(1).val.element))),

 RC_Compose := Rule([RC, @(1, Compose)], e -> Compose(List(@(1).val.children(), RC))),
 RC_SUM := Rule([RC, @(1, SUM)], e -> SUM(List(@(1).val.children(), RC))),
 RC_SUMAcc := Rule([RC, @(1, SUMAcc)], e -> SUMAcc(List(@(1).val.children(), RC))),

 RC_Container := Rule([RC, @(1, [BB,Buf,Inplace,Grp,NoPull,NoPullLeft,NoPullRight, NoDiagPullin, NoDiagPullinLeft, NoDiagPullinRight ])], e -> ObjId(@(1).val)(RC(@(1).val.child(1)))),

 RC_RStep := Rule([RC, @(1, RecursStep)], e -> RecursStep(2*@(1).val.yofs, 2*@(1).val.xofs,
                                                      RC(@(1).val.child(1)))),

 RC_Data := Rule([RC, @(1, Data)], e -> Data(@(1).val.var, @(1).val.value,
                                        RC(@(1).val.child(1))).attrs(@(1).val)),

 RC_ISum := Rule([RC, @(1, ISum)], e -> ISum(@(1).val.var, @(1).val.domain, RC(@(1).val.child(1)))),

 RC_ICompose := Rule([RC, @(1, ICompose)], e -> ICompose(@(1).val.var, @(1).val.domain, RC(@(1).val.child(1)))),

 RC_Gath := Rule([RC, @(1, Gath)], e -> Gath(fTensor(@(1).val.func, fId(2)))),
 RC_Scat := Rule([RC, @(1, [Scat, ScatAcc])], e -> ObjId(@(1).val)(fTensor(@(1).val.func, fId(2)))),
 RC_Prm := Rule([RC, @(1, Prm)], e -> Prm(fTensor(@(1).val.func, fId(2)))),

 RC_RowColVec := Rule([RC, @(1, [RowVec, ColVec], e->not IsSymbolic(e.element.domain()))],
     e -> RC(@(1).val.toDiagBlk())),

# RC_ScatGath := Rule([RC, @(1, ScatGath)], e -> ScatGath(fTensor(@(1).val.sfunc, fId(2)), fTensor(@(1).val.gfunc, fId(2)))),

 RC_O := Rule([RC, @(1, O)], e -> O(2*@(1).val.params[1], 2*@(1).val.params[2])),

 # yes, this does happen
 RC_RCDiag := Rule([RC, @(1, RCDiag)], e -> let(
     func := @(1).val.element,
     D := Dat1d(func.range(), func.domain()),
     j := Ind(func.domain()/2),
     re := nth(D, 2*j),
     im := nth(D, 2*j+1),
     Data(D, func,  # use Data, to preserve fPrecompute that might be present in <func>
          IterDirectSum(j, RC( Blk([[re, -im], [im, re]]) )).sums()))),

 # NB: add a rule for barring real diagonals with replication:
 #    RCData(FData(..real..) o f) -> FData o (f x proj(2))
 RCData_fCompose_FData := Rule([RCData, [fCompose, @(1,FData), @(2)]],
     e -> fCompose(FData(RCExpandData(@(1).val.var)), fTensor(@(2).val, fId(2)))),

 RCData_FData := Rule([RCData, @(1, FData, x -> IsBound(x.var.value) or x.var.t.t=TReal or ObjId(x.var.t.t)=T_Real)],
     e -> let(t := @(1).val.var.t.t,
	 Cond(t = TReal or ObjId(t) = T_Real,
	     diagTensor(FData(@(1).val.var), fConst(t, 2, t.one())),
	     FData(RCExpandData(@(1).val.var))))),

 # NOTE: works for real constants only
 RCData_fConst := Rule([RCData, [@(1,fConst), 1, @(2)]],
     e -> FList(TReal, [ReComplex(Complex(@(2).val)), ImComplex(Complex(@(2).val))])),

 RCData_fPrecompute := Rule([RCData, [fPrecompute, @(1)]], e -> fPrecompute(RCData(@(1).val))),

# YSV: Feb07, lets see what happens without this rule!
# #  RCData_fCompose := Rule([RCData, @(1, fCompose)],
# #      e -> let(ch := @(1).val.children(),
# #        fCompose(RCData(ch[1]), fTensor(fCompose(Drop(ch, 1)), fId(2))))),

 RCData_diagDirsum := Rule([RCData, @(1,diagDirsum)],
      e -> ApplyFunc(diagDirsum, List(@(1).val.children(), RCData))),

# RCData_fCompose_FDataOfs := Rule([RCData, [FDataOfs, @(1), @(2), @(3)]],
#     e -> FDataOfs(RCExpandData(@(1).val), 2 * @(2).val, 2 * @(3).val)),

 RC_Blk := Rule([RC, @(1, Blk)], e -> Blk(RealMatComplexMat(@(1).val.element))),
 RC_Blk1 := Rule([RC, @(1, Blk1)], e -> Blk(RealMatComplexMat([[@(1).val.element]]))),

 RC_Scale := Rule([RC, @(1, Scale)], e ->
     RC(Diag(fConst(Rows(@(1).val), @(1).val.scalar))) * RC(@(1).val.child(1))),

 RC_I := Rule([RC, @(1, I)], e -> I(2*Cols(@1.val))),

 RC_OLMultiplication := Rule([RC, @(1, OLMultiplication)],
     e -> let( p := @(1).val.rChildren(), RCOLMultiplication(p[1], p[2]))),
 RC_OLConjMultiplication := Rule([RC, @(1, OLConjMultiplication)],
     e -> let( p := @(1).val.rChildren(), RCOLConjMultiplication(p[1], p[2]))),

));


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

#F ExpandRotationsSPL33( <spl> )
#F   descends <spl> and replaces rotations by a product of three
#F   matrices such that multiplication with a vector requires
#F   3 adds and 3 mults rather than 2 adds and 4 mults. More
#F   precisely:
#F      x  y        1  1  0                        1 0
#F     -y  x   -->  0 -1  1  * diag(x-y, y, x+y) * 1 1
#F                                                 0 1
#F   Exceptions are the cases y = x and y = -x (angles +-pi/4)
#F   which are replaced by (2 adds and 2 mults)
#F
#F      x * F_2 * (1,2)   # y = x
#F      x * (1,2) * F_2   # y = -x
#F
ExpandRotationsSPL33 := S -> SubstTopDownNR(S, Rot, x->x.expandWinograd());

#F ExpandRotationsSPL33a( <spl> )
#F   descends <spl> and replaces rotations by a product of three
#F   matrices such that multiplication with a vector requires
#F   3 adds and 3 mults rather than 2 adds and 4 mults. More
#F   precisely:
#F     x y      1 (1-x)/y   1 0   1 (1-x)/y
#F    -y x      0   1       y 1   0   1
#F   Exceptions are the cases y = x and y = -x (angles +-pi/4)
#F   which are replaced by (2 adds and 2 mults)
#F
#F      x * F_2 * (1,2)   # y = x
#F      x * (1,2) * F_2   # y = -x
#F
ExpandRotationsSPL33a := S -> SubstTopDownNR(S, Rot, x->x.expandLifting());

#F ExpandRotationsSPL24( <spl> )
#F   descends <spl> and replaces rotations by the corresponding matrix,
#F   which requires (the maximum of) 2 additions and 4 multiplications.
#F
ExpandRotationsSPL24 := S -> SubstTopDownNR(S, Rot, x->x.expandDef());

ExpandRotationsSPLRandom := S -> SubstTopDownNR(S, Rot, x->x.expandRandom());

#F ExpandMonomialSPL( <spl> )
#F   descends <spl> and replaces monomials by products perm * diag.
#F
ExpandMonomialSPL :=
    S -> SubstTopDownNR(S, @.cond(s->ObjId(s)=Mon),
		 s-> Perm(s.element.perm, Length(s.element.diag)) *
                     Diag(s.element.diag));

#F The Exporting Functions
#F -----------------------
#F

#F ExpandRotationsSPL( <spl> )
#F
ExpandRotationsSPL := function ( S )
    Constraint(IsSPL(S));

    # EXPAND_ROTATIONS is one of (see above)
    # - ExpandRotations33      sums * diag * sums
    # - ExpandRotations33a     3 lifting steps (fused mult/add)
    # - ExpandRotations24      by definition
    if EXPAND_ROTATIONS = 1 then  S := ExpandRotationsSPL33(S);
    elif EXPAND_ROTATIONS = 2 then S := ExpandRotationsSPL33a(S);
    elif EXPAND_ROTATIONS = 3 then S := ExpandRotationsSPL24(S);
    elif EXPAND_ROTATIONS = 4 then S := ExpandRotationsSPLRandom(S);
    else Error("invalid value for EXPAND_ROTATIONS (see Doc(EXPAND_ROTATIONS))");
    fi;

    return S;
end;

# PrintNumberToSPLNC( <x> )
#   prints the scalar <x> in SPL syntax.

PrintNumberToSPLNC := function ( x )
  local precision, p, a, extra, c, n;

  precision := 16;

  # scalar case
  if IsScalar(x) then
    PrintScalarToSPLNC(x);
    return;
  # integers
  elif IsInt(x) then
    if x < 0 then Print("(", x, ".0)");
    else Print(x, ".0");
    fi;
    return;
  # rationals
  elif IsRat(x) then
    if x < 0 then Print("(", x, ")");
    else Print(x);
    fi;
    return;
  # floats
  elif IsDouble(x) then
      if x < 0 then Print(StringDouble("(%.17e)", x));
      else Print(StringDouble("%.17e", x));
      fi;
      return;
  # complex numbers
  elif IsComplex(x) then
      Print(StringComplex("(%.17e, %.17e)", x));
      return;
  fi;

  # sqrt of a rational and real
  if x = GaloisCyc(x, -1) and IsRat(x^2) then
    if x = -Sqrt(x^2) then
      Print("(-sqrt(");
      PrintNumberToSPLNC(x^2);
      Print("))");
    else
      Print("sqrt(");
      PrintNumberToSPLNC(x^2);
      Print(")");
    fi;
    return;
  fi;

  # x = a/b * cos(c*pi/d)
  p := RecognizeCosPi(x);
  if p <> false then
    extra := false;
    if p[1] < 0 then
      Print("(");
      extra := true;
    fi;
    if p[1] = 1 then
      Print("cos(");
    elif p[1] = -1 then
      Print("-cos(");
    else
      Print(p[1], "*cos(");
    fi;

    a := Numerator(p[2]);
    if a = 1 then
      Print("pi/", Denominator(p[2]), ")");
    elif a = -1 then
      Print("-pi/", Denominator(p[2]), ")");
    else
      Print(Numerator(p[2]), "*pi/", Denominator(p[2]), ")");
    fi;

    if extra then
      Print(")");
    fi;
    return;
  fi;

  # x = sqrt(2) * a/b * cos(c*pi/d)
  # this captures sum of two cosines/sines
  # the reason to include this is that the
  # substitution rule for rotations (see ExpandRotationsSPL33 or 24)
  # creates such numbers
  p := RecognizeCosPi(x/Sqrt(2));
  if p <> false then
    extra := false;
    if p[1] < 0 then
      Print("(");
      extra := true;
    fi;

    a := Numerator(p[1]);
    if a = 1 then
      Print("sqrt(2)");
    elif a = -1 then
      Print("-sqrt(2)");
    else
      Print(a, "*sqrt(2)");
    fi;
    if not IsInt(p[1]) then
      Print("/", Denominator(p[1]));
    fi;
    Print("*cos(");

    a := Numerator(p[2]);
    if a = 1 then
      Print("pi/", Denominator(p[2]), ")");
    elif a = -1 then
      Print("-pi/", Denominator(p[2]), ")");
    else
      Print(Numerator(p[2]), "*pi/", Denominator(p[2]), ")");
    fi;

    if extra then
      Print(")");
    fi;
    return;
  fi;

  # x = b/(a* CosPi(c/d))
  p := RecognizeCosPi(1/x);
  if p <> false then
    extra := false;
    if p[1] < 0 then
      Print("(-");
      extra := true;
    fi;
    Print(Denominator(p[1]), "/(", AbsInt(Numerator(p[1])), "*cos(");

    a := Numerator(p[2]);
    if a = 1 then
      Print("pi/", Denominator(p[2]), ")");
    elif a = -1 then
      Print("-pi/", Denominator(p[2]), ")");
    else
      Print(Numerator(p[2]), "*pi/", Denominator(p[2]), ")");
    fi;
    Print(")");

    if extra then
      Print(")");
    fi;
    return;
  fi;

  # x is a root of unity
  # note that w(n) (in spl) is E(n)^(n-1)
  a := NofCyc(x);
  if x^(2*a) = 1 then
    c := CoeffsCyc(x, a);
    n := PositionProperty(c, i -> i <> 0);
    if c[n] = 1 then
      if n = 2 then # x = E(a)
        Print("w(", a, ")");
      else
        Print("w(", a, ", ", n - 1, ")");
      fi;
    else # c[n] = -1
      if n = 2 then # x = -E(a)
        Print("(-w(", a, "))");
      else
        Print("(-w(", a, ", ", n - 1, "))");
      fi;
    fi;
    return;
  fi;

  # x is real
  if x = GaloisCyc(x, -1) then
       PrintNumberToSPLNC(ReComplex(Complex(x)));
  else
       PrintNumberToSPLNC(Complex(x));
  fi;
end;


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

# 2-operand intermediate representation.
# Here we define 2-op commands and 3-op -> 2-op
# conversion functions.
#
# This is relevant if one needs very low-level x86 representation,
# eg. to optimize register use and generate assembly code.
#

Class(assign_two_op, assign, rec(
    op_in := self >> Set(ArgsExp(self.exp)),
    op_out := self >> Set([]),
    op_inout := self >> Set([self.loc])
));

Class(assign_add, assign_two_op);
Class(assign_mul, assign_two_op);
Class(assign_sub, assign_two_op);
Class(assign_neg, assign_two_op);

# Examples:
#   assign(t1, add(t1, t2)) == assign_add(t1, t2),
#   assign(t1, add(t2, t3)) == chain(assign(t1, t2), assign_add(t2, t3)).
#

Class(TwoOpCodeRuleSet, RuleSet);
RewriteRules(TwoOpCodeRuleSet, rec(
    add := Rule([assign, @(1), [add, @(2), @(3)]], e -> let(
	    s2:=Length(SuccLoc(@(2).val)), s3:=Length(SuccLoc(@(3).val)),
	When(Length(Filtered(List(@(2).val.succ,x->x.def.n),y->y>@(1).val.def.n))>0,
#	When(IsBound(@(2).val.live_out) or (s3 < s2 and not IsBound(@(3).val.live_out)),
	    chain(assign(@(1).val, @(3).val), # copy+destroy @(3)
		  assign_add(@(1).val, @(2).val)),
	    chain(assign(@(1).val, @(2).val), # copy+destroy @(2)
		  assign_add(@(1).val, @(3).val))))),

    mul := Rule([assign, @(1), [mul, @(2), @(3)]], e -> let(
	    s2:=Length(SuccLoc(@(2).val)), s3:=Length(SuccLoc(@(3).val)),
	When(Length(Filtered(List(@(2).val.succ,x->x.def.n),y->y>@(1).val.def.n))>0,
#	When(IsBound(@(2).val.live_out) or (s3 <= s2 and not IsBound(@(3).val.live_out)),
	    chain(assign(@(1).val, @(3).val), # copy+destroy @(3)
		  assign_mul(@(1).val, @(2).val)),
	    chain(assign(@(1).val, @(2).val), # copy+destroy @(2)
		  assign_mul(@(1).val, @(3).val))))),

    sub := Rule([assign, @(1), [sub, @(2), @(3)]], e ->
	    chain(assign(@(1).val, @(2).val),
		  assign_sub(@(1).val, @(3).val))),

    neg := Rule([assign, @(1), [neg, @(2)]], e ->
            chain(assign(@(1).val, @(2).val),
	          assign_neg(@(1).val)))
));

ElimRedundantCopyChain := function(code)
    local varmap, c, newcmds, succs;
    varmap := tab();
    newcmds := [];
    for c in code.cmds do
        c := SubstVars(c, varmap);
        if ObjId(c)=assign and ObjId(c.loc)=var and ObjId(c.exp)=var and
	   not IsBound(c.exp.live_out) and
	   Filtered(SuccLoc(c.exp), x->x<>c.loc and x.def.n > c.n)=[] then
	    varmap.(c.loc.id) := c.exp;
	else
	    Add(newcmds, c);
	fi;
    od;
    return chain(newcmds);
end;

# Convert three-operand code -> two-operand code
#
TwoOpCode := function(code)
    # NOTE: write a better binsplit
    code := BinSplit(BinSplit(BinSplit(code)));
    MarkLiveness(code);
    code := TwoOpCodeRuleSet(code);
    code := FlattenCode(code);
    MarkLiveness(code);
#    code := ElimRedundantCopyChain(code);
#    code := CopyPropagate(code);
    return code;
end;

X86Code := function(code, numregs)
    local dims;
    if IsBound(code.dimensions) then dims := code.dimensions; fi;
    MarkLiveness(code);
    code := HashConsts(code, rec(declareConstants := true));
    code := TwoOpCode(code);
    MarkLiveness(code);
    code := RegAlloc(code, numregs, TDouble);
    code := DeclareHidden(code);
    if IsBound(dims) then code.dimensions := dims; fi;
    return code;
end;

# assumes <code> is a chain of assigns
TwoOpSSA := function(code)
    local varmap, c, newcmds, succs, a, b, sa, sb, so, v, overwrite, antidep;
    Constraint(IsChain(code) and ForAll(code.cmds, IsAssign));
    varmap := tab();
    newcmds := [];
    for c in code.cmds do
        c.exp := SubstVars(c.exp, varmap);

        if (ObjId(c.exp) in [add, sub, mul]) and ForAny(c.exp.args, IsVar) then
	    Constraint(Length(c.exp.args)=2);
	    [a,b] := c.exp.args;
	    sa := Filtered(SuccLoc(a), x -> x.def.n > c.n);
	    sb := Filtered(SuccLoc(b), x -> x.def.n > c.n);

	    if not IsVar(b) then overwrite := a;
	    elif not IsVar(a) then overwrite := b;
	    elif ObjId(c.exp)=sub then overwrite :=a;
	    elif IsBound(b.live_out) or
		 ((Length(sa) < Length(sb)) and not IsBound(a.live_out)) then
		overwrite := a;
	    else
		overwrite := b;
	    fi;
	    antidep := false;
	    so := When(overwrite=a, sa, sb);
	    if so <> [] then
		v := overwrite.clone();
		v.succ := so;
		overwrite.succ := Difference(overwrite.succ, so);
		Add(newcmds, assign(v, overwrite));
		varmap.(overwrite.id) := v;
		antidep := v;
	    fi;
	    if antidep<>false then c.antidep := [antidep]; fi;
	    Add(newcmds, c);

	else
	    Add(newcmds, c);
	fi;
    od;
    return chain(newcmds);
end;

Class(DirectTwoOpMapping, RuleSet);
RewriteRules(DirectTwoOpMapping, rec(
    add := Rule([assign, @(1), [add, @(2), @(3)]], e ->
	Cond(@(1).val = @(2).val, assign_add(@(2).val, @(3).val),
	     @(1).val = @(3).val, assign_add(@(3).val, @(2).val),
	     Error("Statement ", e, " is not 2-op ready, must be a=a+b, or b=a+b"))),

    mul := Rule([assign, @(1), [mul, @(2), @(3)]], e ->
	Cond(@(1).val = @(2).val, assign_mul(@(2).val, @(3).val),
	     @(1).val = @(3).val, assign_mul(@(3).val, @(2).val),
	     Error("Statement ", e, " is not 2-op ready, must be a=a*b, or b=a*b"))),

    sub := Rule([assign, @(1), [sub, @(2), @(3)]], e ->
	Cond(@(1).val = @(2).val, assign_sub(@(2).val, @(3).val),
	     Error("Statement ", e, " is not 2-op ready, must be a=a-b")))
));
# def b1
# a1: consume b1
# a2: consume b1

# def b1
# cpy b1->b2

# a1: consume b1
# a2: consume b2


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

## Vector Multiplication operator
## VOLMultiplication(<number inputs>, <length inputs>, <length vector>)
Class(VOLMultiplication, RewritableObject, BaseMat, OLBase, rec(
    dims := self >> [self.rChildren()[2] * self.rChildren()[3], StripList(Replicate(self.rChildren()[1], self.rChildren()[2] * self.rChildren()[3]))],
));

#F RCVOLMultiplication(<number inputs>, <length inputs>, <length vector>)
#F   is a vRC(VOLMultiplication(<number inputs>, <length inputs>, <length vector>/2))
#F   inputs/output is in inteleaved complex format: [re1, im1, re2, im2, ...]

Class(RCVOLMultiplication, RewritableObject, BaseMat, OLBase, rec(
    dims := self >> [self.rChildren()[2] * self.rChildren()[3], StripList(Replicate(self.rChildren()[1], self.rChildren()[2] * self.rChildren()[3]))],
));

#F VRCOLMultiplication(<number inputs>, <length inputs>, <length vector>)
#F   inputs/output is in vector inteleaved complex format:
#F     [[re1, re2, ..., re_v], [im1, im2, ..., im_v], [re_(v+1), ...], ...]

Class(VRCOLMultiplication, RewritableObject, BaseMat, OLBase, rec(
    dims := self >> [2 * self.rChildren()[2] * self.rChildren()[3], StripList(Replicate(self.rChildren()[1], 2 * self.rChildren()[2] * self.rChildren()[3]))],
));

## VOLConjMultiplication(<number inputs>, <length inputs>, <length vector>)
Class(VOLConjMultiplication, RewritableObject, BaseMat, OLBase, rec(
    dims := self >> [self.rChildren()[2] * self.rChildren()[3], StripList(Replicate(self.rChildren()[1], self.rChildren()[2] * self.rChildren()[3]))],
));

#F RCVOLConjMultiplication(<complex input length>, <length vector>)
#F   is a vRC(VTensor(OLConjMultiplication(<complex input length>), <length vector>/2))
#F   inputs/output is in inteleaved complex format: [re1, im1, re2, im2, ...]

Class(RCVOLConjMultiplication, RewritableObject, BaseMat, OLBase, rec(
    dims := self >> [self.rChildren()[2] * self.rChildren()[3], StripList(Replicate(self.rChildren()[1], self.rChildren()[2] * self.rChildren()[3]))],
));

#F VRCOLConjMultiplication(<complex input length>, <length vector>)
#F   inputs/output is in vector inteleaved complex format:
#F     [[re1, re2, ..., re_v], [im1, im2, ..., im_v], [re_(v+1), ...], ...]

Class(VRCOLConjMultiplication, RewritableObject, BaseMat, OLBase, rec(
    dims := self >> [2 * self.rChildren()[2] * self.rChildren()[3], StripList(Replicate(self.rChildren()[1], 2 * self.rChildren()[2] * self.rChildren()[3]))],
));


text:
InstallGlobalFunction(IsCommutator,
function(f, w)
	local fp, hom, res;
	fp := CommutatorFactorGroup(f);
	hom := GroupHomomorphismByImages(f, fp, [f.1, f.2], [fp.1, fp.2]);
	res :=  IsOne(Image(hom, w));
	return res;
end);


text:
package main

import (
	"fmt"
)

type Bowser interface {
	Hi()
}

type Possum interface {
	Hi()
    Pebbles()
}

type Unsat interface {
	Hi()
    Pebbles()
    MissMe()
}

type B struct{}

func (b *B) Hi() {
	fmt.Printf("B.Hi called\n")
}
func (b *B) Pebbles() {}

    chk := 0
	var v Bowser = &B{}
	switch v.(type) {
    case Possum:
		fmt.Printf("ooh! it types as a Possum!\n")
        chk = 2
	case Bowser:
		fmt.Printf("yabadadoo! it types as a Bowser!\n")
        chk = 1
	}
    fmt.Printf("chk = '%v'\n", chk)

    // and verify that v implements Bowser too:
    asBowser, isBowser := v.(Bowser)
    asIsNil := (asBowser == nil)

    // negative check, should not convert:
    asUn, isUn := v.(Unsat)
    asUnNil := (asUn == nil)

max_stars_repo_name: gijit/gi-minimal

max_issues_repo_name: gijit/gi-minimal

max_forks_repo_name: gijit/gi-minimal


text:
Hanoi := function(n)
	local move;
	move := function(n, a, b, c) # from, through, to
		if n = 1 then
			Print(a, " -> ", c, "\n");
		else
			move(n - 1, a, c, b);
			move(1, a, b, c);
			move(n - 1, b, a, c);
		fi;
	end;
	move(n, "A", "B", "C");
end;

Hanoi(1);
# A -> C

Hanoi(2);
# A -> B
# A -> C
# B -> C

Hanoi(3);
# A -> C
# A -> B
# C -> B
# A -> C
# B -> A
# B -> C
# A -> C

max_issues_repo_name: seanwallawalla-forks/RosettaCodeData

max_forks_repo_name: seanwallawalla-forks/RosettaCodeData


text:
# Complete multipartite graphs.
BindGlobal("CompleteMultipartiteGraph", function(arg)
    local sizes, dp, F, G, m, n;
    F := function(x, y) return x[1] <> y[1]; end;
    if Length(arg) = 0 then
        Error("at least one argument expected");
        return fail;
    elif Length(arg) = 1 then
        sizes := arg[1];
        dp := DirectProduct(List(sizes, i -> SymmetricGroup(i)));
        return Graph(dp, Union(List([1..Length(sizes)],
            i -> List([1..sizes[i]], j -> [i, j]))),
            OnSum(dp), F, true);
    else
        m := arg[1];
        n := arg[2];
        return Graph(WreathProductSymmetricGroups(n, m),
                     Cartesian([1..m], [1..n]),
                     function(x, g)
                        local y;
                        y := (n*(x[1]-1)+x[2])^g - 1;
                        return [Int(y/n)+1, y mod n + 1];
                     end, F, true);
    fi;
end);

# Cycle graphs.
BindGlobal("CycleGraph", n -> Graph(DihedralGroup(IsPermGroup, 2*n), [1..n],
    OnPoints, function(x, y)
        return (x-y) mod n in [1,n-1];
    end, true));

# Cocktail party graphs.
BindGlobal("CocktailPartyGraph",
    n -> CompleteMultipartiteGraph(n, 2)
);

# Paley graphs.
# For q = 1 (mod 4) a prime power, the graph is strongly regular.
# For q = 3 (mod 4) a prime power, the graph is directed.
BindGlobal("PaleyGraph", function(q)
    local dp;
    dp := DirectProduct(FieldAdditionPermutationGroup(q),
        Group(GeneratorsOfGroup(FieldMultiplicationPermutationGroup(q))[1]^2));
    return Graph(dp, Elements(GF(q)), OnPaley(q, dp),
        function(x, y)
            return IsOne((x-y)^((q-1)/2));
        end, true);
end);

# Latin square graphs.
BindGlobal("LatinSquareGraph", function(arg)
    local dim, dp, G, invt, vcs;
    if Length(arg) = 0 then
        Error("at least one argument expected");
        return fail;
    fi;
    G := arg[1];
    if Length(arg) > 1 then
        invt := arg[2];
    else
        invt := true;
    fi;
    if IsGroup(G) then
        dp := DirectProduct(G, G);
        if invt then
            vcs := Cartesian(G, G);
        else
            vcs := [[One(G), One(G)]];
        fi;
        return Graph(dp, vcs, OnLatinSquare(dp),
            function(x, y)
                return x <> y and (x[1] = y[1] or x[2] = y[2]
                                or x[1]*x[2] = y[1]*y[2]);
            end, invt);
    else
        dim := DimensionsMat(G);
        return AdjFunGraph(Cartesian([1..dim[1]], [1..dim[2]]),
            function(x, y)
                return x <> y and (x[1] = y[1] or x[2] = y[2]
                                or G[x[1]][x[2]] = G[y[1]][y[2]]);
            end);
    fi;
end);

# Complete Taylor graphs, i.e. complete bipartite graphs minus a matching.
BindGlobal("CompleteTaylorGraph", function(n)
    local G;
    G := EdgeOrbitsGraph(Group([(1,2)(n+1,n+2),
                    PermList(Concatenation([2..n], [1], [n+2..2*n], [n+1])),
                    PermList(Concatenation([n+1..2*n], [1..n]))]), [1, n+2]);
    AssignVertexNames(G, Cartesian([1, 2], [1..n]));
    return G;
end);

max_stars_repo_name: jaanos/gap-graphs

max_issues_repo_name: jaanos/gap-graphs

max_forks_repo_name: jaanos/gap-graphs


text:
##  Copyright (c) 2018-2021, Carnegie Mellon University
##  See LICENSE for details

#F FDataNT(<datavar>, <nt>)
#F
Class(FDataNT, Function, rec(
    __call__ := (self, datavar, nt) >> WithBases(self, rec(
        var := datavar,
        operations := PrintOps,
        nt := nt,
        domain := self >> Rows(self.nt)
    )),

    rChildren := self >> [ self.var, self.nt, self._domain, self._range],
    rSetChild := rSetChildFields("var", "nt", "_domain", "_range"),
    from_rChildren := (self, rch) >> ObjId(self)(rch[1], rch[2]).setDomain(rch[4]).setRange(rch[5]),

    domain := self >> self.len,
    print := self >> Print(self.name,"(",self.var,", ",self.nt,")"),

# these are not yet right
    at := (self, n) >> When(IsInt(n) and IsValue(self.ofs) and IsBound(self.var.value),
        self.var.value.v[n + self.ofs.v + 1],
        nth(self.var, n + self.ofs)),

    tolist := self >> List([0..EvalScalar(self.len-1)], i -> nth(self.var, self.ofs+i)),
    lambda := self >> let(x := Ind(self.domain()), Lambda(x, nth(self.var, self.ofs+x))),
# up to here

    domain := self >> Rows(self.nt),
    range := self >> When(self._range=false, self.var.t.t, self._range),
    inline := true,
    free := self >> self.ofs.free()
));

# These need to be implemented properly -- for now they are just markers in TDAG
Class(TColMaj, TPtr);

max_stars_repo_name: franzfranchetti/spiral-package-fftx

max_issues_repo_name: franzfranchetti/spiral-package-fftx

max_forks_repo_name: franzfranchetti/spiral-package-fftx


text:
# Adjacency function for Kneser-type graphs.
BindGlobal("DisjointSets", function(x, y)
    return Intersection(x, y) = [];
end);

# Adjacency function for doubled Odd and Grassmann graphs.
BindGlobal("SymmetrizedInclusion", function(x, y)
    return x <> y and (IsSubset(x, y) or IsSubset(y, x));
end);

# Adjacency function for roots of E_8.
BindGlobal("RootAdjacency", function(x, y)
    return x*y = 8;
end);

# Adjacency function for forms graphs.
BindGlobal("RankAdjacency",
    r -> function(x, y)
        return RankMat(x-y) in r;
    end);

# Adjacency function for adjacency matrices.
BindGlobal("MatrixAdjacency",
    M -> function(x, y)
        return M[x][y] = 1;
    end);

# Adjacency function for adjacency lists.
BindGlobal("ListAdjacency",
    L -> function(x, y)
        return y in L[x];
    end);

# Point-line incidence
BindGlobal("PointLineIncidence", function(x, y)
    return x in y or y in x;
end);


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

Class(TraceBase, rec());

Class(TraceRewrite, TraceBase, rec(
        __call__ := (self, name,input,output,env) >> WithBases(self, rec(name:=name, input:=input,output:=output,env:=env,operations := PrintOps)),
       print := self >> Print("Rewrite(", self.name,",",self.input,",",self.output,")")
));

Class(TraceExpansion, TraceBase, rec(
        __call__ := (self, name,input,output,env) >> WithBases(self, rec(name:=name, input:=input,output:=output,env:=env,operations := PrintOps)),
       print := self >> Print("Expansion(", self.name,",",self.input,",",self.output,")")
));

Class(TraceTreeExpansion, TraceBase, rec(
        __call__ := (self, name,input,output,children,subtrees,env) >> WithBases(self, rec(name:=name, input:=input,output:=output,children:=children,subtrees:=subtrees, env:=env,operations := PrintOps)),
       print := self >> Print("TreeExpansion(", self.name,",",self.input,",",self.output,",",self.children,")")
));

Class(TraceConversion, TraceBase, rec(
        __call__ := (self, name,input,output,env) >> WithBases(self, rec(name:=name, input:=input,output:=output, env:=env, operations := PrintOps)),
       print := self >> Print("Conversion(", self.name,",",self.input,",",self.output,")")
));

Class(TraceLogPrinter, rec(
        __call__ := (self) >> WithBases(self, rec()),

        addRewrite := (self, name,input,output,env) >>
                           Print("\n------------------------------------------------------------------\n",
                                 "RULE: ", name,
                                 "\n------------------------------------------------------------------\n",
                                 "old expression",
                                 "\n------------------------------------------------------------------\n",
                                 input,
                                 "\n------------------------------------------------------------------\n",
                                 "new expression",
                                 "\n------------------------------------------------------------------\n",
                                 output,
                                 "\n------------------------------------------------------------------\n"),

        addExpansion := (self, name,input,output,env) >>
                           Print("\n==================================================================\n",
                                 "EXPANSION RULE: ", name,
                                 "\n------------------------------------------------------------------\n",
                                 "SPL expression:",
                                 "\n------------------------------------------------------------------\n",
                                 input,
                                 "\n------------------------------------------------------------------\n",
                                 "Sigma-SPL expression:",
                                 "\n------------------------------------------------------------------\n",
                                 output,
                                 "\n\n"),

        addTreeExpansion := meth(self, name,input,output,children,subtrees,env)
                           local d;
                           Print("\n==================================================================\n",
                                 "TREE EXPANSION RULE: ", name,
                                 "\n------------------------------------------------------------------\n",
                                 "original expression:",
                                 "\n------------------------------------------------------------------\n",
                                 input, "\n");

                           if Length(children) <> 0 then
                               Print("\n------------------------------------------------------------------\n",
                                     "subtree substitutions: ",
                                     "\n------------------------------------------------------------------\n");
                               DoForAll(children, i->Print(i, "\n\n"));
                               Print("\n------------------------------------------------------------------\n",
                                     "subtrees substituted: ",
                                     "\n------------------------------------------------------------------\n");
                               Print(subtrees, "\n");
                           fi;
                           # NOTE: pass and save var
                           # d := Collect(output, @(1, var, e->IsBound(e.value)));
                           #if (d <>[]) then
                           #   Print("\n------------------------------------------------------------------\n",
                           #          "data tables: ",
                            #         "\n------------------------------------------------------------------\n");
                            #   DoForAll(d, i->Print(i.id, " := ", i.value, "\n\n"));
                           #fi;

                           Print("------------------------------------------------------------------\n",
                                 "substituted expression:",
                                 "\n------------------------------------------------------------------\n",
                                 output, "\n\n");
                       end,

        addConversion := (self, name,input,output,env) >>
                           Print("\n==================================================================\n",
                                 "CONVERSION RULE: ", name,
                                 "\n------------------------------------------------------------------\n",
                                 "icode:",
                                 "\n------------------------------------------------------------------\n",
                                 input,
                                 "\n------------------------------------------------------------------\n",
                                 "icode:",
                                 "\n------------------------------------------------------------------\n",
                                 output,
                                 "\n\n"),

        beginRuleset := (self, ruleset, input) >>
                           Print("\n******************************************************************\n",
                                 "BEGIN RULESET: ", ruleset.inType, " -> ", ruleset.outType,
                                 "\n------------------------------------------------------------------\n",
                                 "Ruleset:", ruleset,
                                 "\n------------------------------------------------------------------\n",
                                 "Initial ", ruleset.inType,
                                 "\n------------------------------------------------------------------\n",
                                 input,
                                 "\n******************************************************************\n"),

        endRuleset := (self, ruleset,output) >>
                           Print("\n******************************************************************\n",
                                 "END RULESET: ", ruleset.inType, " -> ", ruleset.outType,
                                 "\n------------------------------------------------------------------\n",
                                 "Final ", ruleset.outType,
                                 "\n------------------------------------------------------------------\n",
                                 output,
                                 "\n******************************************************************\n\n"),

        beginStage := (self, from, to, input) >>
                           Print("******************************************************************\n",
                                 "BEGIN TRACE: ",from," -> ", to,
                                 "\n------------------------------------------------------------------\n",
                                 from, " expression:",
                                 "\n------------------------------------------------------------------\n",
                                 input,
                                 "\n******************************************************************\n"),

        endStage := (self, from, to, output) >>
                           Print("\n******************************************************************\n",
                                 "END TRACE: ",from," -> ", to,
                                 "\n------------------------------------------------------------------\n",
                                 to," expression:",
                                 "\n------------------------------------------------------------------\n",
                                 output,
                                 "\n******************************************************************\n\n"),

		addNote := (self, note) >>
                           Print("\n------------------------------------------------------------------\n",
                                 "NOTE:\n", note, "\n",
                                  "------------------------------------------------------------------\n")

                         #NOTE:
                         #d := Collect(spl, @(1, var, e->IsBound(e.value)));
                         #if (d <>[]) then
                         #    Print("\n------------------------------------------------------------------\n",
                         #          "data tables: ",
                         #          "\n------------------------------------------------------------------\n");
                         #    DoForAll(d, i->Print(i.id, " := ", i.value, "\n\n"));
                        #fi;
));

Class(TraceLogToFile, TraceLogPrinter, rec(
        __call__ := (self, filename) >> WithBases(self, rec(filename:=filename)),

        addRewrite    := (self, name,input,output,env) >> AppendTo(self.filename, self.__bases__[1].__bases__[1].addRewrite           (name,input,output,env)),
        addExpansion  := (self, name,input,output,env) >> AppendTo(self.filename, self.__bases__[1].__bases__[1].addExpansion   (name,input,output,env)),
        addTreeExpansion  := (self, name,input,output,children,subtrees,env) >> AppendTo(self.filename, self.__bases__[1].__bases__[1].addTreeExpansion(name,input,output,children,subtrees,env)),
        addConversion := (self, name,input,output,env) >> AppendTo(self.filename, self.__bases__[1].__bases__[1].addConversion (name,input,output,env)),

        beginRuleset  := (self, ruleset, input   ) >> AppendTo(self.filename, self.__bases__[1].__bases__[1].beginRuleset  (ruleset, input   )),
        endRuleset    := (self, ruleset, output  ) >> AppendTo(self.filename, self.__bases__[1].__bases__[1].endRuleset    (ruleset, output  )),
        beginStage    := (self, from, to, input  ) >> AppendTo(self.filename, self.__bases__[1].__bases__[1].beginStage    (from, to, input  )),
        endStage      := (self, from, to, output ) >> AppendTo(self.filename, self.__bases__[1].__bases__[1].endStage      (from, to, output )),
		addNote       := (self, note             ) >> AppendTo(self.filename, self.__bases__[1].__bases__[1].addNote       (note ))
));

Class(TraceLogCollector, rec(
        __call__ := (self) >> WithBases(self, rec(log:=[])),

        addRewrite := meth(self, name,input,output,env)
                    local e;
                    e := TraceRewrite(name, input,output,env);
                    Add(self.log, e);
                    return e;
                end,

        addExpansion := meth(self, name,input,output,env)
                    local e;
                    e := TraceExpansion(name, input,output, env);
                    Add(self.log, e);
                    return e;
                end,

        addTreeExpansion := meth(self, name,input,output,children,subtrees,env)
                    local e;
                    e := TraceTreeExpansion(name, input,output,children,subtrees,env);
                    Add(self.log, e);
                    return e;
                end,

        addConversion := meth(self, name,input,output,env)
                    local e;
                    e := TraceConversion(name, input,output, env);
                    Add(self.log, e);
                    return e;
                end,

        beginRuleset := (self, ruleset, input) >> 0,
        endRuleset := (self, ruleset, output) >> 0,
        beginStage := (self, from, to, input) >> 0,
        endStage := (self, from, to, output) >> 0,
		addNote := (self, note) >> 0

));

Class(TraceLog, rec(

        __call__ := (self) >> WithBases(self, rec(plugins := [])),

        addPlugin := (self, plugin) >>  Add(self.plugins, plugin),

        addRewrite := meth(self, name,input,output,env)
                    local p;
                    for p in self.plugins do
                          p.addRewrite(name,input,output,env);
                     od;
                end,

        addExpansion := meth(self, name,input,output,env)
                    local p;
                    for p in self.plugins do
                        p.addExpansion(name,input,output,env);
                    od;
                end,

        addTreeExpansion := meth(self, name,input,output,children,subtrees,env)
                    local p;
                    for p in self.plugins do
                        p.addTreeExpansion(name,input,output,children,subtrees,env);
                    od;
                end,

        addConversion := meth(self, name,input,output,env)
                    local p;
                    for p in self.plugins do
                        p.addConversion(name,input,output,env);
                    od;
                end,

        beginRuleset := meth(self, ruleset, input)
                    local p;
                    for p in self.plugins do
                        p.beginRuleset(ruleset, input);
                    od;
                end,

        endRuleset := meth(self, ruleset,output)
                    local p;
                    for p in self.plugins do
                        p.endRuleset(ruleset,output);
                    od;
                end,

        beginStage := meth(self, from, to, input)
                    local p;
                    for p in self.plugins do
                        p.beginStage(from, to, input);
                    od;
                end,

        endStage := meth(self, from, to, output)
                    local p;
                    for p in self.plugins do
                        p.endStage(from, to, output);
                    od;
                end,

		addNote := meth(self, note)
                    local p;
                    for p in self.plugins do
                        p.addNote(note);
                    od;
                end
));

# Global variable. Will be moved to 'opts' eventually.
trace_log := TraceLog();

# Convenience functions

TraceToConsole := function()
    trace_log.addPlugin(TraceLogPrinter());
end;

TraceToFile := function(filename)
    trace_log.addPlugin(TraceLogToFile(filename));
end;

trace_collector := TraceLogCollector();
TraceToMemory := function()
    trace_log.addPlugin(trace_collector);
    return(trace_collector);
end;

TraceNote := function(note)
	trace_log.addNote(note);
end;

# --- Example of trace system initialization:---
#trace_log.addPlugin(TraceLogPrinter());
#trace_log.addPlugin(TraceLogToFile("trace.g"));
# Save reference to collector for later use
#trace_collector := TraceLogCollector();
#trace_log.addPlugin(trace_collector);


text:
##  Copyright (c) 2018-2021, Carnegie Mellon University
##  See LICENSE for details

Import(simt);

Class(FFTXCUDAOpts, FFTXOpts, simt.TitanVDefaults, rec(
    tags := [],
    operations := rec(Print := s -> Print("<FFTX CUDA options record>")),
    max_threads := 2048,
    max_blocks := 1024,
    max_heap := 1024 * 1024 * 1024
));

cudaOpts := function(arg)
    local opts;
    opts := Copy(FFTXCUDAOpts);
    opts.breakdownRules.Circulant := [Circulant_PRDFT_FDataNT];
    opts.breakdownRules.PRDFT := List([PRDFT1_Base1, PRDFT1_Base2, PRDFT1_CT, PRDFT1_PF, PRDFT_PD, PRDFT_Rader], _noT);
    opts.breakdownRules.IPRDFT := List([ IPRDFT1_Base1, IPRDFT1_Base2, IPRDFT1_CT, IPRDFT_PD, IPRDFT_Rader ], _noT);
    opts.breakdownRules.PRDFT3 := List([ PRDFT3_Base1, PRDFT3_Base2, PRDFT3_CT ], _noT);
    return opts;

    return opts;
end;

Declare(ParseOptsCUDA);

Class(FFTXCUDADefaultConf, rec(
    getOpts := (self, t) >> ParseOptsCUDA(self, t),
    operations := rec(Print := s -> Print("<FFTX CUDA Default Configuration>")),
    useCUDA := true
));

Class(FFTXCUDADeviceDefaultConf, rec(
    getOpts := (self, t) >> ParseOptsCUDA(self, t),
    operations := rec(Print := s -> Print("<FFTX CUDA Device Default Configuration>")),
    useCUDADevice := true
));

cudaConf := rec(
    defaultName := "defaultCUDAConf",
    defaultOpts := (arg) >> FFTXCUDADefaultConf,
    devFunc := true,
    confHandler := cudaOpts
);

fftx.FFTXGlobals.registerConf(cudaConf);

getTargetOS := function()
    local tgt;

    if LocalConfig.osinfo.isWindows() then
        tgt := "win-x64-cuda";
    elif LocalConfig.osinfo.isLinux() then
        tgt := "linux-cuda";
    elif LocalConfig.osinfo.isDarwin() then
        tgt := "linux-cuda";    ## may work
    fi;
    return tgt;
end;

#--
Class(FFTXCUDADeviceOpts, FFTXCUDAOpts, simt.TitanVDefaults, rec(
    tags := [],
    devFunc := true,
    target := rec ( name := getTargetOS() ),
    operations := rec(Print := s -> Print("<FFTX CUDA Device options record>"))
));

cudaDeviceOpts := function(arg) # specific to WarpX size 100...
    local opts;
    opts := Copy(FFTXCUDADeviceOpts);
    opts.breakdownRules.Circulant := [Circulant_PRDFT_FDataNT];
    opts.breakdownRules.PRDFT := List([PRDFT1_Base1, PRDFT1_Base2, CopyFields(PRDFT1_CT,
            rec(allChildren := P ->Filtered(PRDFT1_CT.allChildren(P), i->When(P[1] = 100, Cols(i[1]) = 4, true)))),
        PRDFT_PD], _noT);
    opts.breakdownRules.IPRDFT := List([ IPRDFT1_Base1, IPRDFT1_Base2, IPRDFT1_CT, IPRDFT_PD ], _noT);
    opts.breakdownRules.PRDFT3 := List([ PRDFT3_Base1, PRDFT3_Base2, PRDFT3_CT ], _noT);
    opts.breakdownRules.DFT := [ DFT_Base,
        CopyFields(DFT_CT, rec(children := nt ->Filtered(DFT_CT.children(nt), i->When(nt.params[1] = 100, Cols(i[1]) = 4, true)))),
        DFT_PD ];
    opts.breakdownRules.TTensorInd := [dsA_base, L_dsA_L_base, dsA_L_base, L_dsA_base];
    return opts;
end;

cudaDeviceConf := rec(
    defaultName := "defaultCUDADeviceConf",
    defaultOpts := (arg) >> FFTXCUDADeviceDefaultConf,
    confHandler := cudaDeviceOpts
);

fftx.FFTXGlobals.registerConf(cudaDeviceConf);

# this is a first experimental opts-deriving logic. This needs to be done extensible and properly
ParseOptsCUDA := function(conf, t)
    local tt, _tt, _tt2, _conf, _opts, _HPCSupportedSizesCUDA, _thold,
    MAX_KERNEL, MAX_PRIME, MIN_SIZE, MAX_SIZE, size1, filter;

    # all dimensions need to be inthis array for the high perf MDDFT conf to kick in for now
    # size 320 is problematic at this point and needs attention. Need support for 3 stages to work first
    MAX_KERNEL := 21;
    MAX_PRIME := 13;
    MIN_SIZE := 32;
    MAX_SIZE := 320;

    _thold := MAX_KERNEL;
    filter := (e) -> When(e[1] * e[2] <= _thold ^ 2, e[1] <= _thold and e[2] <= _thold, e[1] <= _thold and e[2] >= _thold);
    size1 := Filtered([MIN_SIZE..MAX_SIZE], i -> ForAny(DivisorPairs(i), filter) and ForAll(Factors(i), j -> not IsPrime(j) or j <= MAX_PRIME));
    _HPCSupportedSizesCUDA := size1;

#    _HPCSupportedSizesCUDA := [80, 96, 100, 224, 320];
#    _thold := 16;

    if IsBound(conf.useCUDADevice) then
#        # detect real MD convolution
#        _tt := Collect(t, RCDiag)::Collect(t, MDPRDFT)::Collect(t, IMDPRDFT)::Collect(t, TTensorI);
#        if Length(_tt) = 4 then
#            _conf := FFTXGlobals.confWarpXCUDADevice();
#            _opts := FFTXGlobals.getOpts(_conf);
#            return _opts;
#        fi;

        # detect batch of DFT/PRDFT
        if ((Length(Collect(t, TTensorInd)) >= 1) or let(lst := Collect(t, TTensorI), (Length(lst) >= 1) and ForAll(lst, l->l.params[2] > 1))) and
            ((Length(Collect(t, DFT)) = 1) or (Length(Collect(t, PRDFT)) = 1) or (Length(Collect(t, IPRDFT)) = 1)) then
            _conf := FFTXGlobals.confBatchFFTCUDADevice();
            _opts := FFTXGlobals.getOpts(_conf);

            # opts for high performance CUDA cuFFT
            if ForAll(Flat(List(Collect(t, @(1, [DFT, PRDFT, IPRDFT])), j-> j.params[1])), i -> i in _HPCSupportedSizesCUDA)  then
                _opts.breakdownRules.TTwiddle := [ TTwiddle_Tw1 ];
                _opts.tags := [ASIMTKernelFlag(ASIMTGridDimX), ASIMTBlockDimY, ASIMTBlockDimX];

                _opts.globalUnrolling := 2*_thold + 1;

                _opts.breakdownRules.TTensorI := [CopyFields(IxA_L_split, rec(switch := true)),
                    fftx.platforms.cuda.L_IxA_SIMT, fftx.platforms.cuda.IxA_L_SIMT]::_opts.breakdownRules.TTensorI;
                _opts.breakdownRules.DFT := [CopyFields(DFT_tSPL_CT, rec(switch := true,
                    filter := e-> When(e[1]*e[2] <= _thold^2, e[1] <= _thold and e[2] <= _thold, e[1] <= _thold and e[2] >= _thold)))]::_opts.breakdownRules.DFT;

                _opts.unparser.simt_synccluster := _opts.unparser.simt_syncblock;
                _opts.postProcessSums := (s, opts) -> let(s1 := ApplyStrategy(s, [ MergedRuleSet(RulesFuncSimp, RulesSums, RulesSIMTFission) ], BUA, opts),
                    When(Collect(t, PRDFT)::Collect(t, IPRDFT) = [],
                        FixUpCUDASigmaSPL_3Stage(s1, opts),
                        FixUpCUDASigmaSPL_3Stage_Real(s1, opts)));
                _opts.postProcessCode := (c, opts) -> FixUpTeslaV_Code(c, opts);
#                _opts.postProcessCode := (c, opts) -> FixUpTeslaV_Code(PingPong_3Stages(c, opts), opts);
                _opts.fixUpTeslaV_Code := true;

                _opts.operations.Print := s -> Print("<FFTX CUDA HPC Batch DFT options record>");

            fi;
            return _opts;
        fi;

        # detect 3D DFT/Batch DFT
        _tt := Collect(t, MDDFT)::Collect(t, MDPRDFT)::Collect(t, IMDPRDFT);
        if Length(_tt) = 1 and Length(_tt[1].params[1]) = 3 then
            _conf := FFTXGlobals.confFFTCUDADevice();
            _opts := FFTXGlobals.getOpts(_conf);

            # opts for high performance CUDA cuFFT
            if ForAll(_tt[1].params[1], i-> i in _HPCSupportedSizesCUDA) then
                _opts.breakdownRules.MDDFT := [fftx.platforms.cuda.MDDFT_tSPL_Pease_SIMT];
                _opts.breakdownRules.MDPRDFT := [fftx.platforms.cuda.MDPRDFT_tSPL_Pease_SIMT];
                _opts.breakdownRules.IMDPRDFT := [fftx.platforms.cuda.IMDPRDFT_tSPL_Pease_SIMT];
                _opts.breakdownRules.TTwiddle := [ TTwiddle_Tw1 ];

                _opts.globalUnrolling := 2*_thold + 1;

                _opts.breakdownRules.TTensorI := [CopyFields(IxA_L_split, rec(switch := true)),
                    fftx.platforms.cuda.L_IxA_SIMT, fftx.platforms.cuda.IxA_L_SIMT]::_opts.breakdownRules.TTensorI;
                _opts.breakdownRules.DFT := [CopyFields(DFT_tSPL_CT, rec(switch := true,
                    filter := e-> When(e[1]*e[2] <= _thold^2, e[1] <= _thold and e[2] <= _thold, e[1] <= _thold and e[2] >= _thold)))]::_opts.breakdownRules.DFT;

                _opts.unparser.simt_synccluster := _opts.unparser.simt_syncblock;
#                _opts.postProcessSums := (s, opts) -> let(s1 := ApplyStrategy(s, [ MergedRuleSet(RulesFuncSimp, RulesSums, RulesSIMTFission) ], BUA, opts),
#                    FixUpCUDASigmaSPL_3Stage(s1, opts));
                _opts.postProcessSums := (s, opts) -> let(s1 := ApplyStrategy(s, [ MergedRuleSet(RulesFuncSimp, RulesSums, RulesSIMTFission) ], BUA, opts),
                    When(Collect(t, MDPRDFT)::Collect(t, IMDPRDFT) = [],
                        FixUpCUDASigmaSPL_3Stage(s1, opts),
                        FixUpCUDASigmaSPL_3Stage_Real(s1, opts)));

                _opts.postProcessCode := (c, opts) -> FixUpTeslaV_Code(c, opts);
#                _opts.postProcessCode := (c, opts) -> FixUpTeslaV_Code(PingPong_3Stages(c, opts), opts);
                _opts.fixUpTeslaV_Code := true;

                if ((Length(Collect(t, TTensorInd)) >= 1) or let(lst := Collect(t, TTensorI), (Length(lst) >= 1) and ForAll(lst, l->l.params[2] > 1))) then
                    _opts.operations.Print := s -> Print("<FFTX CUDA HPC Batch MDDFT/MDPRDFT/MDIPRDFT options record>");
                    _opts.tags := [ASIMTKernelFlag(ASIMTGridDimX), ASIMTGridDimY, ASIMTBlockDimY, ASIMTBlockDimX];
                else
                    _opts.operations.Print := s -> Print("<FFTX CUDA HPC MDDFT/MDPRDFT/MDIPRDFT options record>");
                    _opts.tags := [ASIMTKernelFlag(ASIMTGridDimX), ASIMTBlockDimY, ASIMTBlockDimX];
                fi;

                _opts.HPCSupportedSizesCUDA := _HPCSupportedSizesCUDA;

            fi;

            return _opts;
        fi;

        # detect 3D DFT/iDFT but non-convolution case
        _tt := Collect(t, MDDFT);
        if Length(_tt) = 2 and ForAll(_tt, i->Length(i.params[1]) = 3) and Sum(List(_tt, i->i.params[2])) = Product(_tt[1].params[1]) then
            _conf := FFTXGlobals.confFFTCUDADevice();
            _opts := FFTXGlobals.getOpts(_conf);

            # opts for high performance CUDA cuFFT
            if Length(Filtered(_tt, i -> ObjId(i) = MDDFT)) > 0 and ForAll(_tt[1].params[1], i-> i in _HPCSupportedSizesCUDA) then
                _opts.breakdownRules.MDDFT := [fftx.platforms.cuda.MDDFT_tSPL_Pease_SIMT];
                _opts.breakdownRules.MDPRDFT := [fftx.platforms.cuda.MDPRDFT_tSPL_Pease_SIMT];
                _opts.breakdownRules.IMDPRDFT := [fftx.platforms.cuda.IMDPRDFT_tSPL_Pease_SIMT];
                _opts.breakdownRules.TTwiddle := [ TTwiddle_Tw1 ];
                _opts.tags := [ASIMTKernelFlag(ASIMTGridDimX), ASIMTBlockDimY, ASIMTBlockDimX];

                _opts.globalUnrolling := 2*_thold + 1;

                _opts.breakdownRules.TTensorI := [CopyFields(IxA_L_split, rec(switch := true)),
                    fftx.platforms.cuda.L_IxA_SIMT, fftx.platforms.cuda.IxA_L_SIMT]::_opts.breakdownRules.TTensorI;
                _opts.breakdownRules.DFT := [CopyFields(DFT_tSPL_CT, rec(switch := true,
                    filter := e-> When(e[1]*e[2] <= _thold^2, e[1] <= _thold and e[2] <= _thold, e[1] <= _thold and e[2] >= _thold)))]::_opts.breakdownRules.DFT;

                _opts.unparser.simt_synccluster := _opts.unparser.simt_syncblock;
                _opts.postProcessSums := (s, opts) -> let(s1 := ApplyStrategy(s, [ MergedRuleSet(RulesFuncSimp, RulesSums, RulesSIMTFission) ], BUA, opts),
                    FixUpCUDASigmaSPL_3Stage(s1, opts));
                _opts.postProcessCode := (c, opts) -> FixUpTeslaV_Code(PingPong_3Stages(c, opts), opts);
                _opts.fixUpTeslaV_Code := true;

                _opts.operations.Print := s -> Print("<FFTX CUDA HPC MDDFT options record>");

            fi;

            return _opts;
        fi;

        # promote with default conf rules
        tt := _promote1(Copy(t));

        if ObjId(tt) = TFCall then
            _tt := tt.params[1];
            # check for convolution
            if (ObjId(_tt) in [MDRConv, MDRConvR, IOPrunedMDRConv]) or ((ObjId(_tt) in [TTensorI, TTensorInd]) and (ObjId(_tt.params[1]) in [MDRConv, MDRConvR])) then
                _conf := FFTXGlobals.confMDRConvCUDADevice();
                _opts := FFTXGlobals.getOpts(_conf);

                # opts for high performance CUDA cuFFT
                if (ObjId(_tt) in [MDRConv, MDRConvR, IOPrunedMDRConv] and ForAll(_tt.params[1], i-> i in _HPCSupportedSizesCUDA)) or
                    (ObjId(_tt) in [TTensorI, TTensorInd] and ForAll(_tt.params[1].params[1], i-> i in _HPCSupportedSizesCUDA)) then
                    _opts.breakdownRules.MDDFT := [fftx.platforms.cuda.MDDFT_tSPL_Pease_SIMT];
                    _opts.breakdownRules.MDPRDFT := [fftx.platforms.cuda.MDPRDFT_tSPL_Pease_SIMT];
                    _opts.breakdownRules.IMDPRDFT := [fftx.platforms.cuda.IMDPRDFT_tSPL_Pease_SIMT];
                    _opts.breakdownRules.TTwiddle := [ TTwiddle_Tw1 ];

                    _opts.globalUnrolling := 2*_thold + 1;

                    _opts.breakdownRules.TTensorI := [CopyFields(IxA_L_split, rec(switch := true)),
                        fftx.platforms.cuda.L_IxA_SIMT, fftx.platforms.cuda.IxA_L_SIMT]::_opts.breakdownRules.TTensorI;
                    _opts.breakdownRules.DFT := [CopyFields(DFT_tSPL_CT, rec(switch := true,
                        filter := e-> When(e[1]*e[2] <= _thold^2, e[1] <= _thold and e[2] <= _thold, e[1] <= _thold and e[2] >= _thold)))]::_opts.breakdownRules.DFT;

                    _opts.unparser.simt_synccluster := _opts.unparser.simt_syncblock;
    #                _opts.postProcessSums := (s, opts) -> let(s1 := ApplyStrategy(s, [ MergedRuleSet(RulesFuncSimp, RulesSums, RulesSIMTFission) ], BUA, opts),
    #                    FixUpCUDASigmaSPL_3Stage(s1, opts));
                    _opts.postProcessSums := (s, opts) -> let(s1 := ApplyStrategy(s, [ MergedRuleSet(RulesFuncSimp, RulesSums, RulesSIMTFission) ], BUA, opts),
                        When(Collect(t, MDPRDFT)::Collect(t, IMDPRDFT) = [],
                            FixUpCUDASigmaSPL_3Stage(s1, opts),
                            FixUpCUDASigmaSPL_3Stage_Real(s1, opts)));

                    _opts.postProcessCode := (c, opts) -> FixUpTeslaV_Code(c, opts);
    #                _opts.postProcessCode := (c, opts) -> FixUpTeslaV_Code(PingPong_3Stages(c, opts), opts);
                    _opts.fixUpTeslaV_Code := true;

                    if ((Length(Collect(t, TTensorInd)) >= 1) or let(lst := Collect(t, TTensorI), (Length(lst) >= 1) and ForAll(lst, l->l.params[2] > 1))) then
                        _opts.operations.Print := s -> Print("<FFTX CUDA HPC Batch MDRConv/MDRConvR/IOPrunedMDRConv options record>");
                        _opts.tags := [ASIMTKernelFlag(ASIMTGridDimX), ASIMTGridDimY, ASIMTBlockDimY, ASIMTBlockDimX];
                    else
                        _opts.operations.Print := s -> Print("<FFTX CUDA HPC MDRConv/MDRConvR/IOPrunedMDRConv options record>");
                        _opts.tags := [ASIMTKernelFlag(ASIMTGridDimX), ASIMTBlockDimY, ASIMTBlockDimX];
                    fi;

                    _opts.HPCSupportedSizesCUDA := _HPCSupportedSizesCUDA;

                fi;

                return _opts;
            fi;
            # check for Hockney. This is for N=130
            if ObjId(_tt) = IOPrunedMDRConv  and _tt.params[1] = [130,130,130] then
                _conf := FFTXGlobals.confHockneyMlcCUDADevice();
                _opts := FFTXGlobals.getOpts(_conf);
                return _opts;
            fi;
            # check for general Hockney.
            if ObjId(_tt) = IOPrunedMDRConv then
                _conf := FFTXGlobals.confMDRConvCUDADevice();
                _opts := FFTXGlobals.getOpts(_conf);
                _opts.tags := [ASIMTKernelFlag(ASIMTGridDimY), ASIMTGridDimX, ASIMTBlockDimZ];
                return _opts;
            fi;
        fi;

        # check for WarpX
        _conf := FFTXGlobals.confWarpXCUDADevice();
        _opts := FFTXGlobals.getOpts(_conf);
        tt := _opts.preProcess(Copy(t));
        if ObjId(tt) = TFCall and ObjId(tt.params[1]) = TCompose then
            _tt := tt.params[1].params[1];
            # detect promoted WarpX
            if IsList(_tt) and Length(_tt) = 3 and List(_tt, ObjId) = [ TNoDiagPullinRight, TRC, TNoDiagPullinLeft ] then
                return _opts;
            fi;
        fi;
        # we are doing nothing special
        return FFTXGlobals.getOpts(conf);
    fi;
    if IsBound(conf.useCUDA) then
        return FFTXGlobals.getOpts(conf);
    fi;

    # Here we have to handle GPU configs
    Error("Don't know how to derive opts!\n");
end;

max_stars_repo_name: mikefranusich/spiral-package-fftx

max_issues_repo_name: mikefranusich/spiral-package-fftx

max_forks_repo_name: mikefranusich/spiral-package-fftx


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

# A variable is volatile if its value can change invisibly.
# For scalar variables this can never happen, because we keep track of all reads/writes, and also convert
# program to SSA on the fly.
#
# For arrays, however, this CAN happen, if an array is not scalarized -- because we do
# not keep track of reads/writes, and we do not convert to array SSA.
#
# Knowing the volatility allows us to block CSE from eliminating loads to the same location,
# which would be unsafe.
#
# The error due to lack of volatility checking occurs in the simple case of unrolling the
# following piece of code, without scalarizing T:
#
# loop i
#     T[0] = X[i]
#     Y[i] = T[0]
#
# unrolled:
#   T[0] = X[0]
#   Y[0] = T[0]
#
#   T[0] = X[1]
#   Y[1] = T[0]
#
#   T[0] = X[2]
#   Y[2] = T[0]
#
# CSE without considering T to be volatile:
#
#   T[0] = X[0]
#   s1 = T[0]
#   Y[0] = s1
#
#   T[0] = X[1]
#   Y[1] = s1
#
#   T[0] = X[2]
#   Y[2] = s1
#
#
var.isVolatile := self >> IsArrayT(self.t) and (self in Compile.doNotScalarize);

IsVolatileExp := x -> Cond(
    IsRec(x) and IsBound(x.isVolatile), x.isVolatile(),
    IsRec(x) and IsBound(x.rChildren),
        ForAny(x.rChildren(), IsVolatileExp),
    false
);

Class(CSE, rec(
    _op := (oid, args) -> oid.__name__
        :: Cond(IsBound(args[1]) and IsRec(args[1]) and IsBound(args[1].id), args[1].id, "")
        :: Cond(IsBound(args[2]) and IsRec(args[2]) and IsBound(args[2].id), args[2].id, ""),

    # returns a pair [lst, index]
    _lookup := meth(self, exp)
        local op, pos, args, lst;
	if not IsRec(exp) or not IsBound(exp.rChildren) or IsParam(exp) then
	    return false;
	fi;
	args := exp.rChildren();
	op   := self._op(ObjId(exp), args);
        if not IsBound(self.csetab.(op)) then
	    return false;
	else
	    lst := self.csetab.(op);
	    pos := PositionProperty(lst, ent -> ent.args=args);
	    return When(pos=false, false, [lst, pos]);
	fi;
    end,

    _add := meth(self, loc, oid, args)
        local op, ent;
	op := self._op(oid, args);
	ent := rec(loc := loc, args := args);
        if not IsBound(self.csetab.(op)) then
            self.csetab.(op) := [ent];
	else
            Add(self.csetab.(op), ent);
	fi;
    end,

    cseLookup := meth(self, exp)
        local lkup, lst, idx;
	lkup := self._lookup(exp);
	if lkup = false then return false;
	else
	    [lst, idx] := lkup;
	    return lst[idx].loc;
	fi;
    end,

    cseInvalidate := meth(self, exp)
        local lkup, lst, idx;
	lkup := self._lookup(exp);
	if lkup = false then return false;
	else
	    [lst, idx] := lkup;
	    Unbind(lst[idx]); # this introduces holes to the list, which gap allows
	fi;
    end,

    cseAdd := meth(self, loc, exp)
        local ent, v, co, args, a, b;
	if not IsBound(exp.isExpComposite) then return; fi;
	args := exp.rChildren();
	if ForAny(args, IsVolatileExp) then return; fi;

	self._add(loc, ObjId(exp), args);

	if ObjId(exp) = mul and exp.t.isSigned() and Length(exp.args)=2 and IsValue(exp.args[1]) then
	    v := Copy(exp.args[1]);
	    v.v := -v.v; # negate
	    self._add(neg(loc), mul, [v, exp.args[2]]);

        elif ObjId(exp) in [add,sub] and Length(exp.args)=2 and not IsValue(exp.args[1]) and not IsValue(exp.args[2]) then
            ent := loc;
            [a, b] := exp.args;

            if ObjId(exp)=sub then
                co := self.cseLookup(add(a, b));
                if co=false then
                    co  := self.cseLookup(add(b, a));
                fi;
                [ent,co] := [co, ent];
            else
                co := self.cseLookup(sub(a, b));
                if co=false then
                   co := self.cseLookup(sub(b, a));
                   [b, a] := exp.args;
                fi;
            fi;

            if ent<>false and co<>false then
		self._add( 2 * a, add, [ent, co]);
		self._add( 2 * a, add, [co, ent]);
		self._add( 2 * b, sub, [ent, co]);
		self._add(-2 * b, sub, [co, ent]);
            fi;

        fi;
    end,

    cseCmd := meth(self, cmd)
        local lkup;
	lkup := self.cseLookup(cmd.exp);
	if lkup <> false then
	    cmd.exp := lkup;
	else
	    self.cseAdd(cmd.loc, cmd.exp);
	fi;
    end,

    init :=  self >> WithBases(self, rec(csetab := tab())),

    __call__ := meth(self, code)
        self.csetab := tab();
	DoForAll( Collect(code, assign),
	          cmd -> self.cseCmd(cmd));
	return code;
    end
));


text:
RandNGen := function(n)
	local v, rand;
	v := [1 .. n - 1]*0;
	Add(v, 1);
	rand := function()
		return Random(v);
	end;
	return rand;
end;

UnbiasedGen := function(rand)
	local unbiased;
	unbiased := function()
		local a, b;
		while true do
			a := rand();
			b := rand();
			if a <> b then
				break;
			fi;
		od;
		return a;
	end;
	return unbiased;
end;

range := [2 .. 6];
v := List(range, RandNGen);
w := List(v, UnbiasedGen);
apply := gen -> Sum([1 .. 1000000], n -> gen());

# Some tests (2 is added as a witness, since in this case RandN is already unbiased)
PrintArray(TransposedMat([range, List(v, apply), List(w, apply)]));
# [ [       2,  499991,  499041 ],
#   [       3,  333310,  500044 ],
#   [       4,  249851,  500663 ],
#   [       5,  200532,  500448 ],
#   [       6,  166746,  499859 ] ]


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

#dummy var to keep copyright out of doc string
_dummy := 0;

TimeRec := (i,m) -> rec(index := i, measured := m);

IsTimeRec := r -> IsRec(r) and IsBound(r.index) and IsBound(r.measured);

#F TimeRuleTrees(spl, opts, treenums)
#F
#F    Times each rule tree indexed in list and returns a list of records
#F    spl      - SPL object to build rule trees from
#F    opts     - options
#F    treenums - list of integer indexes to rule trees for SPL object
#F               Must all be from 1 to NofRuleTrees(SPL, obj)
#F
#F	  TimeRec records in returned list of form:
#F    {
#F      index    := <integer, index of tree>,
#F      measured := <float, measured timing value, typically cycles>
#F    }
#F
#F    if opts.timingResultsFile is set, prints results to file

TimeRuleTrees := function(spl, opts, treenums)
	local retlist, idx, tree, meas, verbosity, maxidx, toFile, resultsFile, mem;

	# validate args
	if (not IsSPL(spl)) or (not IsRec(opts)) or (not IsList(treenums)) then
		Error("usage: TimeRuleTrees(spl, opts, treenums)");
	fi;

	# validate list of indexes
	maxidx := NofRuleTrees(spl, opts);
	if not ForAll(treenums, x -> IsInt(x) and x > 0 and x <= maxidx) then
		Error("List of tree indexes must be in range 1..<number of trees for spl>");
	fi;

	verbosity := Cond(IsBound(opts.verbosity), opts.verbosity, 0);

	if verbosity > 0 then
		Print("Timing ", Length(treenums), " rule trees\n");
	fi;

	toFile := IsBound(opts.timingResultsFile) and IsString(opts.timingResultsFile);
	if toFile then
		resultsFile := opts.timingResultsFile;
		PrintTo(resultsFile, "# Timing results for ", spl, "\n\n");
	fi;

	retlist := [];
	for idx in treenums do
		tree := RuleTreeN(spl, idx, opts);
		if tree <> false then
			meas := CMeasureRuleTree(tree, opts);
			Add(retlist, TimeRec(idx, meas));
			if verbosity > 1 then
				Print(idx, ": ", meas, "\n");
			fi;
			if toFile then
				AppendTo(resultsFile, idx, ", ", meas, "\n");
			fi;
		fi;

		ResetCodegen();
	od;
	return retlist;
end;

#F BestTimedRuleTree(reclist)
#F
#F    Finds the TimeRec in reclist with the best time
#F    reclist - list of timing records as returned by TimeRuleTrees
#F
#F	  Returns a copy of the best TimeRec

BestTimedRuleTree := function(reclist)
	local bestRec, tmRec;

	# validate list of timing records
	if not ForAll(reclist, r -> IsTimeRec(r)) then
		Error("reclist is not a valid list of timing records");
	fi;

	bestRec := reclist[1];
	for tmRec in reclist do
		if tmRec.measured < bestRec.measured then
			bestRec := tmRec;
		fi;
	od;

	return Copy(bestRec);
end;

#F TimeStridedRuleTrees(spl, opts, sample_count)
#F
#F    Time a strided list of indexed rule trees starting with index 1
#F    Calculates stride from <rule tree count> / sample_count
#F
#F    Returns a list of timing records (TimeRec)

TimeStridedRuleTrees := function(spl, opts, sample_count)
	local n_trees, stride, index_list;

	if sample_count < 1 then
		Error("<sample_count> must be greater than 0");

	fi;

	n_trees := NofRuleTrees(spl, opts);

	if sample_count > n_trees then
		Error("<sample_count> (", sample_count, ") is larger than number of rule trees (",
			n_trees, ")");
	fi;

	stride := n_trees / sample_count;
	index_list := List([0..(sample_count-1)], x -> 1 + Int(x * stride));

	return TimeRuleTrees(spl, opts, index_list);
end;


text:
--
-- An instance of this template must have a $Export section and the export_terminals option
--
-- Macros that may be redefined in an instance of this template
--
--     $eof_token
--     $additional_interfaces
--     $super_stream_class -- subclass com.ibm.lpg.Utf8LpgLexStream for getKind
--     $prs_stream_class -- use /.PrsStream./ if not subclassing
--
-- B E G I N N I N G   O F   T E M P L A T E   LexerTemplateD
--
%Options programming_language=rt_cpp,margin=4
%Options table
%options action-block=("*.h", "/.", "./")
%options ParseTable=ParseTable
%Options prefix=Char_

--
-- This template requires that the name of the EOF token be set
-- to EOF and that the prefix be "Char_" to be consistent with
-- KeywordTemplateD.
--
%Eof
    EOF
%End

--
-- This template also requires that the name of the parser EOF
-- Token to be exported be set to EOF_TOKEN
--
%Export
    EOF_TOKEN
%End

%Define
    --
    -- Macros that are be needed in an instance of this template
    --
    $eof_token /.$_EOF_TOKEN./

    $additional_interfaces /../
    $super_stream_class /.$file_prefix$Utf8LpgLexStream./
    $prs_stream_class /.IPrsStream./
    $super_class /.Object./

    --
    -- Macros useful for specifying actions
    --
    $Header
    /.
                //
                // Rule $rule_number:  $rule_text
                //
                ./

    $DefaultAction
    /.$Header$case $rule_number: { ./

    $BeginAction /.$DefaultAction./

    $EndAction
    /.          break;
                }./

    $BeginJava
    /.$BeginAction
                $symbol_declarations./

    $EndJava /.$EndAction./

    $NoAction
    /.$Header$case $rule_number:
                    break; ./

    $BeginActions
    /.
         void ruleAction( int ruleNumber)
        {
            switch(ruleNumber)
            {./

    $SplitActions
    /.
	            default:
	                ruleAction$rule_number(ruleNumber);
	                break;
	        }
	        return;
	    }

	     void ruleAction$rule_number(int ruleNumber)
	    {
	        switch (ruleNumber)
	        {./

    $EndActions
    /.
                default:
                    break;
            }
            return;
        }./
%End

%Globals
    /.
    ./
%End

%Headers
    /.
	#pragma once
    #include <iostream>
    #include "IPrsStream.h"
    #include "Object.h"
    #include "ParseTable.h"
    #include "RuleAction.h"
    #include "stringex.h"
    #include "Token.h"
    #include "$sym_type.h"
    #include "$prs_type.h"
    #include "$kw_lexer_class.h"
    #include "LexParser.h"
    #include "Utf8LpgLexStream.h"
    struct $action_type :public $super_class,  public RuleAction$additional_interfaces
    {
		struct  $super_stream_class;
         $super_stream_class *lexStream= nullptr;
        ~$action_type(){
            delete lexStream;
            delete lexParser;
        }
         inline  static ParseTable* prs = new $prs_type();
         ParseTable* getParseTable() { return prs; }

         LexParser* lexParser = new LexParser();
         LexParser* getParser() { return lexParser; }

         int getToken(int i) { return lexParser->getToken(i); }
         int getRhsFirstTokenIndex(int i) { return lexParser->getFirstToken(i); }
         int getRhsLastTokenIndex(int i) { return lexParser->getLastToken(i); }

         int getLeftSpan() { return lexParser->getToken(1); }
         int getRightSpan() { return lexParser->getLastToken(); }

         void resetKeywordLexer()
        {
            if (kwLexer == nullptr)
                  this->kwLexer = new $kw_lexer_class(lexStream->getInputBytes(), $_IDENTIFIER);
            else this->kwLexer->setInput(lexStream->getInputBytes());
        }

         void reset(const std::wstring&  filename, int tab)
        {
			delete lexStream;
            lexStream = new $super_stream_class(filename, tab);
            lexParser->reset((ILexStream*) lexStream, prs,this);
            resetKeywordLexer();
        }

         void reset(shared_ptr_string input_bytes, const std::wstring& filename)
        {
            reset(input_bytes, filename, 1);
        }

         void reset(shared_ptr_string input_bytes, const std::wstring& filename, int tab)
        {
            lexStream = new $super_stream_class(input_bytes, filename, tab);
            lexParser->reset((ILexStream*) lexStream, prs,  this);
            resetKeywordLexer();
        }

         $action_type(const std::wstring& filename, int tab)
        {
            reset(filename, tab);
        }

         $action_type(shared_ptr_string input_bytes, const std::wstring&  filename, int tab)
        {
            reset(input_bytes, filename, tab);
        }

         $action_type(shared_ptr_string input_bytes, const std::wstring&  filename)
        {
            reset(input_bytes, filename, 1);
        }

         $action_type() {}

         ILexStream* getILexStream() { return lexStream; }

        /**
         * @deprecated replaced by {@link #getILexStream()}
         */
         ILexStream* getLexStream() { return lexStream; }

         void initializeLexer($prs_stream_class * prsStream, int start_offset, int end_offset)
        {
            if (lexStream->getInputBytes().size() == 0)
                throw  std::exception("LexStream was not initialized");
            lexStream->setPrsStream(prsStream);
            prsStream->makeToken(start_offset, end_offset, 0); // Token list must start with a bad token
        }

         void lexer($prs_stream_class* prsStream)
        {
            lexer(nullptr, prsStream);
        }

         void lexer(Monitor* monitor, $prs_stream_class* prsStream)
        {
            if (lexStream->getInputBytes().size() == 0)
                  throw  std::exception("lexStream was not initialized");

            lexStream->setPrsStream(prsStream);

            prsStream->makeToken(0, 0, 0); // Token list must start with a bad token

            lexParser->parseCharacters(monitor);  // Lex the input characters

            int i = lexStream->getStreamIndex();
            prsStream->makeToken(i, i, $eof_token); // and end with the end of file token
            prsStream->setStreamLength(prsStream->getSize());

            return;
        }
    ./
%End

%Rules
    /.$BeginActions./
%End

%Trailers
    /.
        $EndActions
    };
    ./
%End

--
-- E N D   O F   T E M P L A T E
--

max_stars_repo_name: kuafuwang/LPG-VScode

max_issues_repo_name: kuafuwang/LPG-VScode

max_forks_repo_name: kuafuwang/LPG-VScode