// File: /workspace/github_c_makefile_star2_O3/mishun[P]plantri/plantri.c
// Function: canon
static int 
canon(int lcolour[], EDGE *can_numberings[][MAXE], int *nbtot, int *nbop)

/* Checks whether the last vertex (number: nv-1) is canonical or not. 
   Returns 1 if yes, 0 if not. One of the criterions a canonical vertex 
   must fulfill is that its colour is minimal.

   IT IS ASSUMED that the values of the colour function are positive
   and at most INT_MAX-MAXN.
 
   A possible starting edge for the construction of a representation is 
   one with lexicographically minimal colour pair (start,INT_MAX-end).
   In can_numberings[][] the canonical numberings are stored as sequences 
   of oriented edges.  For every 0 <= i,j < *nbtot and every 
   0 <= k < ne the edges can_numberings[i][k] and can_numberings[j][k] can 
   be mapped onto each other by an automorphism. The first 
   *nbop numberings are orientation preserving while 
   the rest is orientation reversing.

   In case of only 1 automorphism, in can_numberings[0][0] the "canonical" 
   edge is given.  It is one edge emanating at the canonical vertex. The 
   rest of the numbering is not given. 

   In case of nontrivial automorphisms, can[0] starts with a list of edges 
   adjacent to nv-1. In case of an orientation preserving numbering the deges 
   are listed in ->next direction, otherwise in ->prev direction.

   Works OK if at least one vertex has valence >= 3. Otherwise some numberings 
   are computed twice, since changing the orientation (the cyclic order around 
   each vertex) doesn't change anything */
{
    int i, last_vertex, test;
    int minstart, maxend; /* (minstart,maxend) will be the chosen colour 
                                pair of an edge */
    EDGE *startlist_last[5], *startlist[5*MAXN], *run, *end;
    int list_length_last, list_length;
    int representation[MAXE];
    EDGE *numblist[MAXE], *numblist_mirror[MAXE]; /* lists of edges where 
                        starting gives a canonical representation */
    int numbs = 1, numbs_mirror = 0;
    int colour[MAXN];

    for (i=0; i<nv; i++) colour[i]=lcolour[i]+MAXN;
                               /* to distinguish colours from vertices */
    last_vertex = nv-1;
    minstart = colour[last_vertex];

/* determine the smallest possible end for the vertex "last_vertex" */

    list_length_last = 1; startlist_last[0] = end = firstedge[last_vertex];
    maxend = colour[end->end];

    for (run = end->next; run != end; run = run->next)
      { if (colour[run->end] > maxend)
          { startlist_last[0] = run; 
            list_length_last = 1; maxend = colour[run->end];}
        else if (colour[run->end] == maxend)
          { startlist_last[list_length_last] = run; list_length_last++; }
      }

/* Now we know the pair that SHOULD be minimal and we can determine a list 
   of all edges with this colour pair. If a new pair is found that is even 
   smaller, we can return 0 at once */

    list_length = 0;

    for (i = 0; i < last_vertex; i++) 
      { if (colour[i] < minstart) return 0;
        if (colour[i] == minstart)
          { run = end = firstedge[i];
            do
            {
              if (colour[run->end] > maxend) return 0;
              if (colour[run->end] == maxend)
                { startlist[list_length] = run; list_length++; }
              run = run->next;
            } while (run != end);
          }
      }

/* OK -- so there is no smaller pair and now we have to determine the 
   smallest representation around vertex "last_vertex": */

    testcanon_first_init(startlist_last[0], representation, colour);
    numblist[0] = startlist_last[0];
    test = testcanon_mirror_init(startlist_last[0], representation, colour);
    if (test == 1) 
      { numbs_mirror = 1; numblist_mirror[0] = startlist_last[0]; }
    else if (test == 2)  
      { numbs_mirror = 1; numbs = 0; 
        numblist_mirror[0] = startlist_last[0]; }

    for (i = 1; i < list_length_last; i++)
      { test = testcanon_init(startlist_last[i], representation, colour);
        if (test == 1) { numblist[numbs] = startlist_last[i]; numbs++; }
        else if (test == 2) 
          { numbs_mirror = 0; numbs = 1; numblist[0] = startlist_last[i]; }
            test = testcanon_mirror_init(startlist_last[i], 
                                                     representation, colour);
          if (test == 1)  
            { numblist_mirror[numbs_mirror] = startlist_last[i]; 
              numbs_mirror++; }
          else if (test == 2) 
            { numbs_mirror = 1; numbs = 0; 
              numblist_mirror[0] = startlist_last[i]; }
      }

/* Now we know the best representation we can obtain starting at last_vertex. 
   Now we will check all the others. We can return 0 at once if we find a 
   better one */

    for (i = 0; i < list_length; i++)
      { test = testcanon(startlist[i], representation, colour);
        if (test == 1) { numblist[numbs] = startlist[i]; numbs++; }
        else if (test == 2) return 0;
        test = testcanon_mirror(startlist[i], representation, colour);
        if (test == 1) 
          { numblist_mirror[numbs_mirror] = startlist[i]; numbs_mirror++; }
        else if (test == 2) return 0;
      }

    *nbop = numbs;
    *nbtot = numbs+numbs_mirror;

    if (*nbtot>1)
      { for (i = 0; i < numbs; i++) 
          construct_numb(numblist[i], can_numberings[i]); 
        for (i = 0; i < numbs_mirror; i++, numbs++) 
          construct_numb_mirror(numblist_mirror[i],can_numberings[numbs]);
      }
    else 
      { if (numbs) can_numberings[0][0] = numblist[0];
        else can_numberings[0][0] = numblist_mirror[0]; }

    return 1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x2868, %rsp           # imm = 0x2868
movslq 0x23e322(%rip), %r10    # 0x244610
testq %r10, %r10
jle 0x6307
xorl %eax, %eax
movl (%rdi,%rax,4), %ecx
addl $0x40, %ecx
movl %ecx, 0x50(%rsp,%rax,4)
incq %rax
cmpq %rax, %r10
jne 0x62f5
movl 0x4c(%rsp,%r10,4), %eax
leaq 0x216dd(%rip), %rcx     # 0x279f0
movq -0x8(%rcx,%r10,8), %rdi
movq %rdi, 0x20(%rsp)
movslq 0x4(%rdi), %r8
movl 0x50(%rsp,%r8,4), %r14d
movq 0x18(%rdi), %r8
movl $0x1, %ebp
cmpq %rdi, %r8
je 0x636c
movl %r14d, %r9d
movslq 0x4(%r8), %r11
movl 0x50(%rsp,%r11,4), %r14d
cmpl %r9d, %r14d
jle 0x6351
movq %r8, 0x20(%rsp)
movl $0x1, %ebp
jmp 0x6360
jne 0x635d
movslq %ebp, %rbp
movq %r8, 0x20(%rsp,%rbp,8)
incl %ebp
movl %r9d, %r14d
movq 0x18(%r8), %r8
movl %r14d, %r9d
cmpq %rdi, %r8
jne 0x6337
xorl %r15d, %r15d
movl $0x0, %ebx
cmpl $0x2, %r10d
jl 0x63c9
decq %r10
movl %r10d, %r11d
xorl %r13d, %r13d
xorl %edi, %edi
xorl %ebx, %ebx
cmpl %eax, 0x50(%rsp,%rdi,4)
jl 0x6623
jne 0x63c1
movq (%rcx,%rdi,8), %r8
movq %r8, %r9
movslq 0x4(%r9), %r10
cmpl %r14d, 0x50(%rsp,%r10,4)
jg 0x6623
jne 0x63b8
movslq %ebx, %rbx
movq %r9, 0x1e60(%rsp,%rbx,8)
incl %ebx
movq 0x18(%r9), %r9
cmpq %r8, %r9
jne 0x639a
incq %rdi
cmpq %r11, %rdi
jne 0x6387
movq %rdx, 0x10(%rsp)
movq %rsi, 0x18(%rsp)
movq 0x20(%rsp), %r14
leaq 0x150(%rsp), %r12
leaq 0x50(%rsp), %r13
movq %r14, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0xbc12
movq %r14, 0x12c0(%rsp)
movq %r14, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0xbd27
cmpl $0x2, %eax
je 0x642f
movl $0x1, %r12d
cmpl $0x1, %eax
jne 0x6440
movq %r14, 0x720(%rsp)
movl $0x1, %r12d
movl $0x1, %r15d
jmp 0x6440
movq %r14, 0x720(%rsp)
movl $0x1, %r15d
xorl %r12d, %r12d
cmpl $0x2, %ebp
jl 0x64ea
movl %ebp, %eax
movq %rax, 0x8(%rsp)
movl $0x1, %r14d
leaq 0x50(%rsp), %rbp
movq 0x20(%rsp,%r14,8), %r13
movq %r13, %rdi
leaq 0x150(%rsp), %rsi
movq %rbp, %rdx
callq 0xbe9c
cmpl $0x2, %eax
je 0x648d
cmpl $0x1, %eax
jne 0x649e
movslq %r12d, %r12
movq %r13, 0x12c0(%rsp,%r12,8)
incl %r12d
jmp 0x649e
movq %r13, 0x12c0(%rsp)
xorl %r15d, %r15d
movl $0x1, %r12d
movq %r13, %rdi
leaq 0x150(%rsp), %rsi
movq %rbp, %rdx
callq 0xbd27
cmpl $0x2, %eax
je 0x64cb
cmpl $0x1, %eax
jne 0x64dc
movslq %r15d, %r15
movq %r13, 0x720(%rsp,%r15,8)
incl %r15d
jmp 0x64dc
movq %r13, 0x720(%rsp)
movl $0x1, %r15d
xorl %r12d, %r12d
incq %r14
cmpq %r14, 0x8(%rsp)
jne 0x645b
testl %ebx, %ebx
jle 0x656d
movl %ebx, %eax
movq %rax, 0x8(%rsp)
leaq 0x150(%rsp), %rbx
leaq 0x50(%rsp), %r13
xorl %r14d, %r14d
movq 0x1e60(%rsp,%r14,8), %rbp
movq %rbp, %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0xc011
cmpl $0x1, %eax
je 0x652a
cmpl $0x2, %eax
jne 0x6538
jmp 0x6620
movslq %r12d, %r12
movq %rbp, 0x12c0(%rsp,%r12,8)
incl %r12d
movq %rbp, %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0xc13b
cmpl $0x1, %eax
je 0x6555
cmpl $0x2, %eax
jne 0x6563
jmp 0x6620
movslq %r15d, %r15
movq %rbp, 0x720(%rsp,%r15,8)
incl %r15d
incq %r14
cmpq %r14, 0x8(%rsp)
jne 0x6505
movq 0x10(%rsp), %rax
movl %r12d, (%rax)
leal (%r15,%r12), %eax
movq 0x18(%rsp), %rcx
movl %eax, (%rcx)
cmpl $0x2, %eax
jl 0x65f7
leaq 0x21764(%rip), %rbx     # 0x27cf0
testl %r12d, %r12d
jle 0x65b8
movl %r12d, %r13d
xorl %ebp, %ebp
movq %rbx, %r14
movq 0x12c0(%rsp,%rbp,8), %rdi
movq %r14, %rsi
callq 0xc265
incq %rbp
addq $0xba0, %r14            # imm = 0xBA0
cmpq %rbp, %r13
jne 0x6599
movl $0x1, %r13d
testl %r15d, %r15d
jle 0x6623
movslq %r12d, %rax
movl %r15d, %r14d
imulq $0xba0, %rax, %rax      # imm = 0xBA0
addq %rax, %rbx
xorl %r15d, %r15d
movq 0x720(%rsp,%r15,8), %rdi
movq %rbx, %rsi
callq 0xc396
incq %r15
addq $0xba0, %rbx            # imm = 0xBA0
cmpq %r15, %r14
jne 0x65d6
jmp 0x6623
testl %r12d, %r12d
leaq 0x720(%rsp), %rax
leaq 0x12c0(%rsp), %rcx
cmoveq %rax, %rcx
movq (%rcx), %rax
movq %rax, 0x216d8(%rip)     # 0x27cf0
movl $0x1, %r13d
jmp 0x6623
xorl %r13d, %r13d
movl %r13d, %eax
addq $0x2868, %rsp           # imm = 0x2868
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq