upper by default
local x=a'i' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=false})
${ a} ^i$ GOOD time: 0.129000ms
stack: size: 0

    local x=a'^i' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=false})
    ${ a} ^i$ GOOD time: 0.127000ms
    stack: size: 0

      local x=a'_i' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=true})
      ${ a} _i$ GOOD time: 0.137000ms
      stack: size: 0

        local x=a'ij' print(x) assert(#x==3 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=false} and x[3]==Tensor.Index{symbol='j', lower=false})
        ${{ a} ^i} ^j$ GOOD time: 0.360000ms
        stack: size: 0

          local x=a'i_j' print(x) assert(#x==3 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=false} and x[3]==Tensor.Index{symbol='j', lower=true})
          ${{ a} ^i} _j$ GOOD time: 0.175000ms
          stack: size: 0

            local x=a'^ij' print(x) assert(#x==3 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=false} and x[3]==Tensor.Index{symbol='j', lower=false})
            ${{ a} ^i} ^j$ GOOD time: 0.137000ms
            stack: size: 0

              local x=a'^i_j' print(x) assert(#x==3 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=false} and x[3]==Tensor.Index{symbol='j', lower=true})
              ${{ a} ^i} _j$ GOOD time: 0.134000ms
              stack: size: 0

                local x=a'_i^j' print(x) assert(#x==3 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=true} and x[3]==Tensor.Index{symbol='j', lower=false})
                ${{ a} _i} ^j$ GOOD time: 0.261000ms
                stack: size: 0

                  local x=a'_ij' print(x) assert(#x==3 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=true} and x[3]==Tensor.Index{symbol='j', lower=true})
                  ${{ a} _i} _j$ GOOD time: 0.410000ms
                  stack: size: 0

                    multi-char
                    upper by default
                    local x=a' i' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=false})
                    ${ a} ^i$ GOOD time: 0.217000ms
                    stack: size: 0
                      upper by default
                      local x=a' \\mu' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='\\mu', lower=false})
                      ${ a} ^{\mu}$ GOOD time: 0.127000ms
                      stack: size: 0

                        local x=a' ^\\mu' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='\\mu', lower=false})
                        ${ a} ^{\mu}$ GOOD time: 0.144000ms
                        stack: size: 0

                          local x=a' _\\mu' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='\\mu', lower=true})
                          ${ a} _{\mu}$ GOOD time: 0.105000ms
                          stack: size: 0

                            local x=a' \\mu \\nu' print(x) assert(#x==3 and x[1]==a and x[2]==Tensor.Index{symbol='\\mu', lower=false} and x[3]==Tensor.Index{symbol='\\nu', lower=false})
                            ${{ a} ^{\mu}} ^{\nu}$ GOOD time: 0.145000ms
                            stack: size: 0

                              commas are lower by default
                              local x=a',i' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=true, derivative=','})
                              ${ a} _{,i}$ GOOD time: 0.108000ms
                              stack: size: 0

                                local x=a',^i' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=false, derivative=','})
                                ${ a} ^{,i}$ GOOD time: 0.147000ms
                                stack: size: 0

                                  local x=a',_i' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=true, derivative=','})
                                  ${ a} _{,i}$ GOOD time: 0.127000ms
                                  stack: size: 0

                                    local x=a'^,i' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=false, derivative=','})
                                    ${ a} ^{,i}$ GOOD time: 0.122000ms
                                    stack: size: 0

                                      local x=a'_,i' print(x) assert(#x==2 and x[1]==a and x[2]==Tensor.Index{symbol='i', lower=true, derivative=','})
                                      ${ a} _{,i}$ GOOD time: 0.341000ms
                                      stack: size: 0

                                        TODO multiple indexes with commas mixed
                                        TODO multiple indexes with commas mixed with multiple chars


                                        simplifyAssertNe(a'^,i', a'_,i')
                                        ${{ a} ^{,i}} \ne {{ a} _{,i}}$
                                        GOOD
                                        time: 4.488000ms
                                        stack: size: 7
                                        • Init
                                        • Prune
                                        • Expand
                                        • Prune
                                        • Factor
                                        • Prune
                                        • Tidy