simplifyAssertEq(x, x)
${x} = {x}$
GOOD
time: 1.530000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertNe(x, y)
${x} \ne {y}$
GOOD
time: 0.502000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy


assert(x:match(x))
GOOD time: 0.070000ms
stack: size: 0

    assert(not x:match(y))
    GOOD time: 0.047000ms
    stack: size: 0

      constants

      implicit mul by 1
      simplifyAssertAllEq({const(2):match(const(2)*W(1))}, {const(1)})
      ${1} = {1}$
      ${1} = {1}$
      ${1} = {1}$
      GOOD
      time: 3.440000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      simplifyAssertAllEq({const(2):match(const(1)*W(1))}, {const(2)})
      ${1} = {1}$
      ${2} = {2}$
      ${2} = {2}$
      GOOD
      time: 1.569000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy
      implicit divide by 1
      simplifyAssertAllEq({const(2):match(const(2)/W(1))}, {const(1)})
      ${1} = {1}$
      lhs: 1=false
      rhs: 1=$1$
      when comparing key 1
      BAD
      /home/chris/Projects/lua/symmath/export/Export.lua:106: attempt to index local 'x' (a boolean value)
      stack traceback:
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:181: in function '__index'
      /home/chris/Projects/lua/symmath/export/Export.lua:106: in function 'precedence'
      /home/chris/Projects/lua/symmath/export/Export.lua:121: in function 'testWrapStrOfChildWithParenthesis'
      /home/chris/Projects/lua/symmath/export/LaTeX.lua:74: in function 'wrapStrOfChildWithParenthesis'
      /home/chris/Projects/lua/symmath/export/LaTeX.lua:209: in function 'apply'
      /home/chris/Projects/lua/symmath/export/LaTeX.lua:664: in function '__call'
      /home/chris/Projects/lua/symmath/export/LaTeX.lua:672: in function 'applyLaTeX'
      /home/chris/Projects/lua/symmath/export/LaTeX.lua:715: in function
      [C]: in function 'print'
      /home/chris/Projects/lua/symmath/export/MathJax.lua:127: in function 'printbr'
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:171: in function
      [C]: in function 'xpcall'
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:167: in function 'simplifyAssertAllEq'
      [string "simplifyAssertAllEq({const(2):match(const(2)/..."]:1: in main chunk
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:238: in function
      [C]: in function 'xpcall'
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:237: in function 'exec'
      match.lua:233: in function 'cb'
      /home/chris/Projects/lua/ext/timer.lua:54: in function 'timer'
      match.lua:6: in main chunk
      [C]: at 0x5602f61ee3e0 21 BAD
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:183: failed
      stack traceback:
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:246: in function
      [C]: in function 'error'
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:183: in function 'simplifyAssertAllEq'
      [string "simplifyAssertAllEq({const(2):match(const(2)/..."]:1: in main chunk
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:238: in function
      [C]: in function 'xpcall'
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:237: in function 'exec'
      match.lua:233: in function 'cb'
      /home/chris/Projects/lua/ext/timer.lua:54: in function 'timer'
      match.lua:6: in main chunk
      [C]: at 0x5602f61ee3e0
      time: 1.252000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy
      implicit integer factoring
      simplifyAssertAllEq({const(4):match(const(2)*W(1))}, {const(2)})
      ${1} = {1}$
      lhs: 1=false
      rhs: 1=$2$
      when comparing key 1
      BAD
      /home/chris/Projects/lua/symmath/export/Export.lua:106: attempt to index local 'x' (a boolean value)
      stack traceback:
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:181: in function '__index'
      /home/chris/Projects/lua/symmath/export/Export.lua:106: in function 'precedence'
      /home/chris/Projects/lua/symmath/export/Export.lua:121: in function 'testWrapStrOfChildWithParenthesis'
      /home/chris/Projects/lua/symmath/export/LaTeX.lua:74: in function 'wrapStrOfChildWithParenthesis'
      /home/chris/Projects/lua/symmath/export/LaTeX.lua:209: in function 'apply'
      /home/chris/Projects/lua/symmath/export/LaTeX.lua:664: in function '__call'
      /home/chris/Projects/lua/symmath/export/LaTeX.lua:672: in function 'applyLaTeX'
      /home/chris/Projects/lua/symmath/export/LaTeX.lua:715: in function
      [C]: in function 'print'
      /home/chris/Projects/lua/symmath/export/MathJax.lua:127: in function 'printbr'
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:171: in function
      [C]: in function 'xpcall'
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:167: in function 'simplifyAssertAllEq'
      [string "simplifyAssertAllEq({const(4):match(const(2)*..."]:1: in main chunk
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:238: in function
      [C]: in function 'xpcall'
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:237: in function 'exec'
      match.lua:233: in function 'cb'
      /home/chris/Projects/lua/ext/timer.lua:54: in function 'timer'
      match.lua:6: in main chunk
      [C]: at 0x5602f61ee3e0 21 BAD
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:183: failed
      stack traceback:
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:246: in function
      [C]: in function 'error'
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:183: in function 'simplifyAssertAllEq'
      [string "simplifyAssertAllEq({const(4):match(const(2)*..."]:1: in main chunk
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:238: in function
      [C]: in function 'xpcall'
      /home/chris/Projects/lua/symmath/tests/unit/unit.lua:237: in function 'exec'
      match.lua:233: in function 'cb'
      /home/chris/Projects/lua/ext/timer.lua:54: in function 'timer'
      match.lua:6: in main chunk
      [C]: at 0x5602f61ee3e0
      time: 0.778000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      functions


      simplifyAssertAllEq({sin(x):match(sin(W(1)))}, {x})
      ${1} = {1}$
      ${x} = {x}$
      ${x} = {x}$
      GOOD
      time: 0.875000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      functions and mul mixed

      simplifyAssertAllEq({sin(2*x):match(sin(W(1)))}, {2 * x})
      ${1} = {1}$
      ${{{2}} {{x}}} = {{{2}} {{x}}}$
      ${{{2}} {{x}}} = {{{2}} {{x}}}$
      GOOD
      time: 4.732000ms
      stack: size: 8
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • *:Tidy:apply
      • Tidy


      simplifyAssertAllEq({sin(2*x):match(sin(2 * W(1)))}, {x})
      ${1} = {1}$
      ${x} = {x}$
      ${x} = {x}$
      GOOD
      time: 0.835000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      matching c*f(x) => c*sin(a*x)

      simplifyAssertAllEq({sin(2*x):match(W{1, dependsOn=x} * W{index=2, cannotDependOn=x})}, {sin(2*x), one})
      ${2} = {2}$
      ${\sin\left( {{{2}} {{x}}}\right)} = {\sin\left( {{{2}} {{x}}}\right)}$
      ${\sin\left( {{{2}} {{x}}}\right)} = {\sin\left( {{{2}} {{x}}}\right)}$
      ${1} = {1}$
      ${1} = {1}$
      GOOD
      time: 6.958000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      simplifyAssertAllEq({sin(2*x):match(sin(W{1, cannotDependOn=x} * x))}, {const(2)})
      ${1} = {1}$
      ${2} = {2}$
      ${2} = {2}$
      GOOD
      time: 1.151000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      add


      simplifyAssertAllEq({x:match(W{2, cannotDependOn=x} + W{1, dependsOn=x})}, {x, zero})
      ${2} = {2}$
      ${x} = {x}$
      ${x} = {x}$
      ${0} = {0}$
      ${0} = {0}$
      GOOD
      time: 1.600000ms
      stack: size: 8
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Constant:Tidy:apply
      • Tidy

      simplifyAssertEq((x + y), (x + y))
      ${{x} + {y}} = {{x} + {y}}$
      GOOD
      time: 4.227000ms
      stack: size: 8
      • Init
      • Prune
      • Expand
      • Prune
      • +:Factor:apply
      • Factor
      • Prune
      • Tidy

      assert((x + y):match(x + y))
      GOOD time: 0.071000ms
      stack: size: 0

        add match to first term

        simplifyAssertAllEq({(x + y):match(W(1) + y)}, {x})
        ${1} = {1}$
        ${x} = {x}$
        ${x} = {x}$
        GOOD
        time: 1.193000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        add match to second term

        simplifyAssertAllEq({(x + y):match(x + W(1))}, {y})
        ${1} = {1}$
        ${y} = {y}$
        ${y} = {y}$
        GOOD
        time: 1.119000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        change order

        simplifyAssertAllEq({(x + y):match(y + W(1))}, {x})
        ${1} = {1}$
        ${x} = {x}$
        ${x} = {x}$
        GOOD
        time: 1.041000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        add match to zero, because nothing's left

        simplifyAssertAllEq({(x + y):match(x + y + W(1))}, {zero})
        ${1} = {1}$
        ${0} = {0}$
        ${0} = {0}$
        GOOD
        time: 1.012000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy


        simplifyAssertAllEq({(x + y):match(W(1))}, {x + y})
        ${1} = {1}$
        ${{x} + {y}} = {{x} + {y}}$
        ${{x} + {y}} = {{x} + {y}}$
        GOOD
        time: 6.848000ms
        stack: size: 8
        • Init
        • Prune
        • Expand
        • Prune
        • +:Factor:apply
        • Factor
        • Prune
        • Tidy

        doubled-up matches should only work if they match

        assert(not (x + y):match(W(1) + W(1)))
        GOOD time: 0.925000ms
        stack: size: 0

          this too, this would work only if x + x and not x + y

          simplifyAssertAllEq({(x + x):match(W(1) + W(1))}, {x})
          ${1} = {1}$
          ${x} = {x}$
          ${x} = {x}$
          GOOD
          time: 0.659000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy

          this too

          simplifyAssertAllEq({(x + x):match(W{1, atMost=1} + W{2, atMost=1})}, {x, x})
          ${2} = {2}$
          ${x} = {x}$
          ${x} = {x}$
          ${x} = {x}$
          ${x} = {x}$
          GOOD
          time: 0.506000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy

          this should match (x+y), 0

          simplifyAssertAllEq({(x + y):match(W(1) + W(2))}, {x + y, zero})
          ${2} = {2}$
          ${{x} + {y}} = {{x} + {y}}$
          ${{x} + {y}} = {{x} + {y}}$
          ${0} = {0}$
          ${0} = {0}$
          GOOD
          time: 2.974000ms
          stack: size: 8
          • Init
          • Prune
          • Expand
          • Prune
          • +:Factor:apply
          • Factor
          • Prune
          • Tidy


          simplifyAssertAllEq({(x + y):match(W{1, atMost=1} + W{2, atMost=1})}, {x, y})
          ${2} = {2}$
          ${x} = {x}$
          ${x} = {x}$
          ${y} = {y}$
          ${y} = {y}$
          GOOD
          time: 0.979000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy

          for these to work, I have to add the multi-wildcard stuff to the non-wildcard elements, handled in add.wildcardMatches

          simplifyAssertAllEq({x:match(W(1) + W(2))}, {x, zero})
          ${2} = {2}$
          ${x} = {x}$
          ${x} = {x}$
          ${0} = {0}$
          ${0} = {0}$
          GOOD
          time: 0.569000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy


          simplifyAssertAllEq({x:match(x + W(1) + W(2))}, {zero, zero})
          ${2} = {2}$
          ${0} = {0}$
          ${0} = {0}$
          ${0} = {0}$
          ${0} = {0}$
          GOOD
          time: 1.141000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy


          simplifyAssertAllEq({x:match(W(1) + x + W(2))}, {zero, zero})
          ${2} = {2}$
          ${0} = {0}$
          ${0} = {0}$
          ${0} = {0}$
          ${0} = {0}$
          GOOD
          time: 1.072000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy


          simplifyAssertAllEq({(x * y):match(W(1) + W(2))}, {x * y, zero})
          ${2} = {2}$
          ${{{x}} {{y}}} = {{{x}} {{y}}}$
          ${{{x}} {{y}}} = {{{x}} {{y}}}$
          ${0} = {0}$
          ${0} = {0}$
          GOOD
          time: 2.312000ms
          stack: size: 8
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • *:Tidy:apply
          • Tidy

          make sure within add.wildcardMatches we greedy-match any wildcards with 'atLeast' before assigning the rest to zero

          simplifyAssertAllEq({x:match(W(1) + W{2,atLeast=1} + W(3))}, {zero, x, zero})
          ${3} = {3}$
          ${0} = {0}$
          ${0} = {0}$
          ${x} = {x}$
          ${x} = {x}$
          ${0} = {0}$
          ${0} = {0}$
          GOOD
          time: 0.786000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy

          now we match wildcards left-to-right, so the cannot-depend-on will match first

          simplifyAssertAllEq({(x + y):match(W{1, cannotDependOn=x} + W{2, dependsOn=x})}, {y, x})
          ${2} = {2}$
          ${y} = {y}$
          ${y} = {y}$
          ${x} = {x}$
          ${x} = {x}$
          GOOD
          time: 0.980000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy


          simplifyAssertAllEq({(x + y):match(W{1, cannotDependOn=x, atLeast=1} + W{2, dependsOn=x})}, {y, x})
          ${2} = {2}$
          ${y} = {y}$
          ${y} = {y}$
          ${x} = {x}$
          ${x} = {x}$
          GOOD
          time: 1.431000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy


          same with mul


          simplifyAssertAllEq({(x * y):match(y * W(1))}, {x})
          ${1} = {1}$
          ${x} = {x}$
          ${x} = {x}$
          GOOD
          time: 0.386000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy


          simplifyAssertAllEq({(x * y):match(x * y * W(1))}, {one})
          ${1} = {1}$
          ${1} = {1}$
          ${1} = {1}$
          GOOD
          time: 1.004000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy


          simplifyAssertAllEq({ (x * y):match(W(1))}, {x * y})
          ${1} = {1}$
          ${{{x}} {{y}}} = {{{x}} {{y}}}$
          ${{{x}} {{y}}} = {{{x}} {{y}}}$
          GOOD
          time: 2.358000ms
          stack: size: 8
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • *:Tidy:apply
          • Tidy


          assert(not (x * y):match(W(1) * W(1)))
          GOOD time: 0.823000ms
          stack: size: 0


            simplifyAssertAllEq({(x * x):match(W(1) * W(1))}, {x})
            ${1} = {1}$
            ${x} = {x}$
            ${x} = {x}$
            GOOD
            time: 0.612000ms
            stack: size: 7
            • Init
            • Prune
            • Expand
            • Prune
            • Factor
            • Prune
            • Tidy

            verify wildcards are greedy with multiple mul matching
            the first will take all expressions, the second gets the empty set

            simplifyAssertAllEq({(x * y):match(W(1) * W(2))}, {x * y, one})
            ${2} = {2}$
            ${{{x}} {{y}}} = {{{x}} {{y}}}$
            ${{{x}} {{y}}} = {{{x}} {{y}}}$
            ${1} = {1}$
            ${1} = {1}$
            GOOD
            time: 1.898000ms
            stack: size: 7
            • Init
            • Prune
            • Expand
            • Prune
            • Factor
            • Prune
            • Tidy

            verify 'atMost' works - since both need at least 1 entry, it will only match when each gets a separate term

            simplifyAssertAllEq({(x * x):match(W{1, atMost=1} * W{2, atMost=1})}, {x, x})
            ${2} = {2}$
            ${x} = {x}$
            ${x} = {x}$
            ${x} = {x}$
            ${x} = {x}$
            GOOD
            time: 1.073000ms
            stack: size: 7
            • Init
            • Prune
            • Expand
            • Prune
            • Factor
            • Prune
            • Tidy

            verify 'atMost' cooperates with non-atMost wildcards

            simplifyAssertAllEq({(x * y):match(W(1) * W{2, atLeast=1})}, {x, y})
            ${2} = {2}$
            ${x} = {x}$
            ${x} = {x}$
            ${y} = {y}$
            ${y} = {y}$
            GOOD
            time: 0.549000ms
            stack: size: 7
            • Init
            • Prune
            • Expand
            • Prune
            • Factor
            • Prune
            • Tidy


            simplifyAssertAllEq({(x * y):match(W{1, atMost=1} * W{2, atMost=1})}, {x, y})
            ${2} = {2}$
            ${x} = {x}$
            ${x} = {x}$
            ${y} = {y}$
            ${y} = {y}$
            GOOD
            time: 0.704000ms
            stack: size: 7
            • Init
            • Prune
            • Expand
            • Prune
            • Factor
            • Prune
            • Tidy


            assert( not( Constant(0):match(x) ) )
            GOOD time: 0.038000ms
            stack: size: 0

              assert( not( Constant(0):match(x * y) ) )
              GOOD time: 0.074000ms
              stack: size: 0


                simplifyAssertEq( zero:match(W(1) * x), zero )
                ${0} = {0}$
                GOOD
                time: 0.288000ms
                stack: size: 0

                  assert( not zero:match(W{1, dependsOn=x} * x) )
                  GOOD time: 0.068000ms
                  stack: size: 0


                    simplifyAssertEq( zero:match(W(1) * x * y), zero )
                    ${0} = {0}$
                    GOOD
                    time: 0.184000ms
                    stack: size: 0


                      simplifyAssertEq( one:match(1 + W(1)), zero )
                      ${0} = {0}$
                      GOOD
                      time: 0.181000ms
                      stack: size: 0


                        simplifyAssertEq( one:match(1 + W(1) * x), zero )
                        ${0} = {0}$
                        GOOD
                        time: 0.690000ms
                        stack: size: 0


                          simplifyAssertEq( one:match(1 + W(1) * x * y), zero )
                          ${0} = {0}$
                          GOOD
                          time: 0.221000ms
                          stack: size: 0


                            how can you take x*y and match only the 'x'?


                            simplifyAssertAllEq({(x * y):match(W{index=2, cannotDependOn=x} * W{1, dependsOn=x})}, {x, y})
                            ${2} = {2}$
                            ${x} = {x}$
                            ${x} = {x}$
                            ${y} = {y}$
                            ${y} = {y}$
                            GOOD
                            time: 1.185000ms
                            stack: size: 7
                            • Init
                            • Prune
                            • Expand
                            • Prune
                            • Factor
                            • Prune
                            • Tidy


                            simplifyAssertAllEq({(x * y):match(W{1, dependsOn=x} * W{index=2, cannotDependOn=x})}, {x*y, 1})
                            ${2} = {2}$
                            ${{{x}} {{y}}} = {{{x}} {{y}}}$
                            ${{{x}} {{y}}} = {{{x}} {{y}}}$
                            ${1} = {1}$
                            ${1} = {1}$
                            GOOD
                            time: 2.505000ms
                            stack: size: 7
                            • Init
                            • Prune
                            • Expand
                            • Prune
                            • Factor
                            • Prune
                            • Tidy


                            simplifyAssertAllEq({(x * y):match(W{index=2, cannotDependOn=x} * W(1))}, {x, y})
                            ${2} = {2}$
                            ${x} = {x}$
                            ${x} = {x}$
                            ${y} = {y}$
                            ${y} = {y}$
                            GOOD
                            time: 1.029000ms
                            stack: size: 7
                            • Init
                            • Prune
                            • Expand
                            • Prune
                            • Factor
                            • Prune
                            • Tidy


                            simplifyAssertAllEq({(x * y):match(W(1) * W{index=2, cannotDependOn=x})}, {x*y, 1})
                            ${2} = {2}$
                            ${{{x}} {{y}}} = {{{x}} {{y}}}$
                            ${{{x}} {{y}}} = {{{x}} {{y}}}$
                            ${1} = {1}$
                            ${1} = {1}$
                            GOOD
                            time: 1.577000ms
                            stack: size: 7
                            • Init
                            • Prune
                            • Expand
                            • Prune
                            • Factor
                            • Prune
                            • Tidy


                            simplifyAssertAllEq({(x * y):match(W(1) * W(2))}, {x*y, 1})
                            ${2} = {2}$
                            ${{{x}} {{y}}} = {{{x}} {{y}}}$
                            ${{{x}} {{y}}} = {{{x}} {{y}}}$
                            ${1} = {1}$
                            ${1} = {1}$
                            GOOD
                            time: 2.004000ms
                            stack: size: 7
                            • Init
                            • Prune
                            • Expand
                            • Prune
                            • Factor
                            • Prune
                            • Tidy


                            combinations of add and mul


                            for this to work, add.wildcardMatches must call the wildcard-capable objects' own wildcard handlers correctly (and use push/pop match states, instead of assigning to wildcard indexes directly?)
                            also, because add.wildcardMatches assigns the extra wildcards to zero, it will be assigning (W(2) * W(3)) to zero ... which means it must (a) handle mul.wildcardMatches and (b) pick who of mul's children gets the zero and who doesn't
                            it also means that a situation like add->mul->add might have problems ... x:match(W(1) + (W(2) + W(3)) * (W(4) + W(5)))

                            do local i,j,k = x:match(W(1) + W(2) * W(3)) assertEq(i, x) assert(j == zero or k == zero) end
                            ${x} = {x}$
                            GOOD
                            time: 0.363000ms
                            stack: size: 0


                              cross over add and mul ... not yet working
                              local i = (x):match(W(1) + x) -- works

                              do local i = (x * y):match(W(1) + x * y) assertEq(i, zero) end
                              ${0} = {0}$
                              GOOD
                              time: 0.375000ms
                              stack: size: 0

                                either 1 or 2 must be zero, and either 3 or 4 must be zero

                                do local i,j,k,l = x:match(x + W(1) * W(2) + W(3) * W(4)) assert(i == zero or j == zero) assert(k == zero or l == zero) end
                                GOOD time: 0.700000ms
                                stack: size: 0


                                  do local c, f = (2 * x):match(W{1, cannotDependOn=x} * W{2, dependsOn=x}) assertEq(c, const(2)) assertEq(f, x) end
                                  ${2} = {2}$
                                  ${x} = {x}$
                                  GOOD
                                  time: 0.603000ms
                                  stack: size: 0


                                    do local c, f = (2 * x):match(W{1, cannotDependOn=x} * W{2, dependsOn=x}) assertEq(c, const(2)) assertEq(f, x) end
                                    ${2} = {2}$
                                    ${x} = {x}$
                                    GOOD
                                    time: 0.653000ms
                                    stack: size: 0

                                      Put the 'cannotDependOn' wildcard first (leftmost) in the mul for it to greedily match non-dep-on-x terms
                                      otherwise 'dependsOn' will match everything, since the mul of a non-dep and a dep itself is dep on 'x', so it will include non-dep-on-terms

                                      do local c, f = (2 * 1/x):factorDivision():match(W{index=1, cannotDependOn=x} * W{2, dependsOn=x}) assertEq(c, const(2)) assertEq(f, 1/x) end
                                      ${2} = {2}$
                                      ${\frac{1}{x}} = {\frac{1}{x}}$
                                      GOOD
                                      time: 8.940000ms
                                      stack: size: 8
                                      • Init
                                      • Prune
                                      • Expand
                                      • Prune
                                      • Factor
                                      • Prune
                                      • Tidy
                                      • /:FactorDivision:apply


                                      do local c, f = (2 * 1/x):factorDivision():match(W{1, cannotDependOn=x} * W(2)) assertEq(c, const(2)) assertEq(f, 1/x) end
                                      ${2} = {2}$
                                      ${\frac{1}{x}} = {\frac{1}{x}}$
                                      GOOD
                                      time: 6.271000ms
                                      stack: size: 8
                                      • Init
                                      • Prune
                                      • Expand
                                      • Prune
                                      • Factor
                                      • Prune
                                      • Tidy
                                      • /:FactorDivision:apply


                                      simplifyAssertAllEq({ (x + 2*y):match(W(1) + W(2) * y) }, {x,2})
                                      ${2} = {2}$
                                      ${x} = {x}$
                                      ${x} = {x}$
                                      ${2} = {2}$
                                      ${2} = {2}$
                                      GOOD
                                      time: 1.514000ms
                                      stack: size: 7
                                      • Init
                                      • Prune
                                      • Expand
                                      • Prune
                                      • Factor
                                      • Prune
                                      • Tidy


                                      simplifyAssertAllEq({ (x + 2*y):match(W(1) * x + W(2) * y) }, {1,2})
                                      ${2} = {2}$
                                      ${1} = {1}$
                                      ${1} = {1}$
                                      ${2} = {2}$
                                      ${2} = {2}$
                                      GOOD
                                      time: 1.406000ms
                                      stack: size: 7
                                      • Init
                                      • Prune
                                      • Expand
                                      • Prune
                                      • Factor
                                      • Prune
                                      • Tidy


                                      simplifyAssertAllEq( {x:match( W(1)*x + W(2))}, {1, 0})
                                      ${2} = {2}$
                                      ${1} = {1}$
                                      ${1} = {1}$
                                      ${0} = {0}$
                                      ${0} = {0}$
                                      GOOD
                                      time: 0.773000ms
                                      stack: size: 7
                                      • Init
                                      • Prune
                                      • Expand
                                      • Prune
                                      • Factor
                                      • Prune
                                      • Tidy


                                      simplifyAssertAllEq( {x:match( W(1)*x + W(2)*y)}, {1, 0})
                                      ${2} = {2}$
                                      ${1} = {1}$
                                      ${1} = {1}$
                                      ${0} = {0}$
                                      ${0} = {0}$
                                      GOOD
                                      time: 2.641000ms
                                      stack: size: 7
                                      • Init
                                      • Prune
                                      • Expand
                                      • Prune
                                      • Factor
                                      • Prune
                                      • Tidy

                                      div



                                      do local i = (1/x):match(1 / W(1)) assertEq(i, x) end
                                      ${x} = {x}$
                                      GOOD
                                      time: 0.305000ms
                                      stack: size: 0


                                        do local i = (1/x):match(1 / (W(1) * x)) assertEq(i, one) end
                                        ${1} = {1}$
                                        GOOD
                                        time: 0.636000ms
                                        stack: size: 0


                                          do local i = (1/x):match(1 / (W{1, cannotDependOn=x} * x)) assertEq(i, one) end
                                          ${1} = {1}$
                                          GOOD
                                          time: 0.391000ms
                                          stack: size: 0


                                            assert((2 * 1/x):match(2 * 1/x))
                                            GOOD time: 0.094000ms
                                            stack: size: 0


                                              do local i = (2 * 1/x):match(2 * 1/W(1)) assertEq(i, x) end
                                              ${x} = {x}$
                                              GOOD
                                              time: 0.122000ms
                                              stack: size: 0


                                                do local i = (2 * 1/x):match(2 * 1/(W(1) * x)) assertEq(i, one) end
                                                ${1} = {1}$
                                                GOOD
                                                time: 0.345000ms
                                                stack: size: 0


                                                  do local i, j = (2 * 1/x):factorDivision():match(W{1, atMost=1} * W{index=2, atMost=1}) assertEq(i, const(2)) assertEq(j, 1/x) end
                                                  ${2} = {2}$
                                                  ${\frac{1}{x}} = {\frac{1}{x}}$
                                                  GOOD
                                                  time: 4.900000ms
                                                  stack: size: 8
                                                  • Init
                                                  • Prune
                                                  • Expand
                                                  • Prune
                                                  • Factor
                                                  • Prune
                                                  • Tidy
                                                  • /:FactorDivision:apply


                                                  do local a, b = (1/(x*(3*x+4))):match(1 / (x * (W{1, cannotDependOn=x} * x + W{2, cannotDependOn=x}))) assertEq(a, const(3)) assertEq(b, const(4)) end
                                                  ${3} = {3}$
                                                  ${4} = {4}$
                                                  GOOD
                                                  time: 0.562000ms
                                                  stack: size: 0


                                                    do local a, b = (1/(x*(3*x+4))):factorDivision():match(1 / (W{1, cannotDependOn=x} * x * x + W{2, cannotDependOn=x} * x)) assertEq(a, const(3)) assertEq(b, const(4)) end
                                                    ${3} = {3}$
                                                    ${4} = {4}$
                                                    GOOD
                                                    time: 30.551000ms
                                                    stack: size: 9
                                                    • Init
                                                    • Prune
                                                    • Expand
                                                    • Prune
                                                    • Factor
                                                    • Prune
                                                    • Tidy
                                                    • *:FactorDivision:apply
                                                    • *:FactorDivision:apply

                                                    pow


                                                    simplifyAssertAllEq({(x^2):match(x^W(1))}, {const(2)})
                                                    ${1} = {1}$
                                                    ${2} = {2}$
                                                    ${2} = {2}$
                                                    GOOD
                                                    time: 0.465000ms
                                                    stack: size: 7
                                                    • Init
                                                    • Prune
                                                    • Expand
                                                    • Prune
                                                    • Factor
                                                    • Prune
                                                    • Tidy

                                                    simplifyAssertAllEq({(x^2):match(W(1)^2)}, {x})
                                                    ${1} = {1}$
                                                    ${x} = {x}$
                                                    ${x} = {x}$
                                                    GOOD
                                                    time: 0.333000ms
                                                    stack: size: 7
                                                    • Init
                                                    • Prune
                                                    • Expand
                                                    • Prune
                                                    • Factor
                                                    • Prune
                                                    • Tidy

                                                    simplifyAssertAllEq({(x^2):match(W(1)^W(2))}, {x, 2})
                                                    ${2} = {2}$
                                                    ${x} = {x}$
                                                    ${x} = {x}$
                                                    ${2} = {2}$
                                                    ${2} = {2}$
                                                    GOOD
                                                    time: 0.810000ms
                                                    stack: size: 7
                                                    • Init
                                                    • Prune
                                                    • Expand
                                                    • Prune
                                                    • Factor
                                                    • Prune
                                                    • Tidy
                                                    defaults:

                                                    simplifyAssertAllEq({(x):match(x^W(1))}, {const(1)})
                                                    ${1} = {1}$
                                                    ${1} = {1}$
                                                    ${1} = {1}$
                                                    GOOD
                                                    time: 0.587000ms
                                                    stack: size: 7
                                                    • Init
                                                    • Prune
                                                    • Expand
                                                    • Prune
                                                    • Factor
                                                    • Prune
                                                    • Tidy

                                                    simplifyAssertAllEq({(x):match(W(1)^1)}, {x})
                                                    ${1} = {1}$
                                                    ${x} = {x}$
                                                    ${x} = {x}$
                                                    GOOD
                                                    time: 0.269000ms
                                                    stack: size: 7
                                                    • Init
                                                    • Prune
                                                    • Expand
                                                    • Prune
                                                    • Factor
                                                    • Prune
                                                    • Tidy

                                                    simplifyAssertAllEq({(x):match(W(1)^W(2))}, {x, const(1)})
                                                    ${2} = {2}$
                                                    ${x} = {x}$
                                                    ${x} = {x}$
                                                    ${1} = {1}$
                                                    ${1} = {1}$
                                                    GOOD
                                                    time: 0.706000ms
                                                    stack: size: 7
                                                    • Init
                                                    • Prune
                                                    • Expand
                                                    • Prune
                                                    • Factor
                                                    • Prune
                                                    • Tidy

                                                    etc


                                                    do local expr = sin(2*x) + cos(3*x) local a,b = expr:match( sin(W(1)) + cos(W(2)) ) print(a[1], a[2] ,b) end
                                                    $2$ $x$ ${{3}} {{x}}$ GOOD time: 0.807000ms
                                                    stack: size: 0

                                                      do local expr = sin(2*x) * cos(3*x) local a,b = expr:match( sin(W(1)) * cos(W(2)) ) print(a[1], a[2] ,b) end
                                                      $2$ $x$ ${{3}} {{x}}$ GOOD time: 0.527000ms
                                                      stack: size: 0


                                                        do local expr = (3*x^2 + 1) printbr('expr', expr) local a, c = expr:match(W{1, cannotDependOn=x} * x^2 + W{2, cannotDependOn=x}) printbr('a', a) printbr('c', c) simplifyAssertAllEq({a, c}, {3, 1}) end
                                                        expr ${{{3}} {{{x}^{2}}}} + {1}$
                                                        a $3$
                                                        c $1$
                                                        ${2} = {2}$
                                                        ${3} = {3}$
                                                        ${3} = {3}$
                                                        ${1} = {1}$
                                                        ${1} = {1}$
                                                        GOOD
                                                        time: 2.055000ms
                                                        stack: size: 7
                                                        • Init
                                                        • Prune
                                                        • Expand
                                                        • Prune
                                                        • Factor
                                                        • Prune
                                                        • Tidy


                                                        do local expr = (3*x^2 + 2*x + 1) printbr('expr', expr) local a, b, c = expr:match(W{1, cannotDependOn=x} * x^2 + W{2, cannotDependOn=x} * x + W{3, cannotDependOn=x}) printbr('a', a) printbr('b', b) printbr('c', c) simplifyAssertAllEq({a, b, c}, {3, 2, 1}) end
                                                        expr ${{{3}} {{{x}^{2}}}} + {{{2}} {{x}}} + {1}$
                                                        a $3$
                                                        b $2$
                                                        c $1$
                                                        ${3} = {3}$
                                                        ${3} = {3}$
                                                        ${3} = {3}$
                                                        ${2} = {2}$
                                                        ${2} = {2}$
                                                        ${1} = {1}$
                                                        ${1} = {1}$
                                                        GOOD
                                                        time: 4.079000ms
                                                        stack: size: 7
                                                        • Init
                                                        • Prune
                                                        • Expand
                                                        • Prune
                                                        • Factor
                                                        • Prune
                                                        • Tidy


                                                        do local expr = (3*x^2 + 1):factorDivision() printbr('expr', expr) local a, b, c = expr:match(W{1, cannotDependOn=x} * x^2 + W{2, cannotDependOn=x} * x + W{3, cannotDependOn=x}) printbr('a', a) printbr('b', b) printbr('c', c) simplifyAssertAllEq({a, b, c}, {3, 0, 1}) end
                                                        expr ${1} + {{{3}} {{{x}^{2}}}}$
                                                        a false
                                                        b nil
                                                        c nil
                                                        ${1} = {3}$
                                                        expected 1 to equal 3
                                                        found $1$ vs $3$
                                                        lhs stack
                                                        Init $1$
                                                        	1	

                                                        Prune $1$
                                                        	1	

                                                        Expand $1$
                                                        	1	

                                                        Prune $1$
                                                        	1	

                                                        Factor $1$
                                                        	1	

                                                        Prune $1$
                                                        	1	

                                                        Tidy $1$
                                                        	1	

                                                        rhs stack
                                                        Init $3$
                                                        	3	

                                                        Prune $3$
                                                        	3	

                                                        Expand $3$
                                                        	3	

                                                        Prune $3$
                                                        	3	

                                                        Factor $3$
                                                        	3	

                                                        Prune $3$
                                                        	3	

                                                        Tidy $3$
                                                        	3	

                                                        lhs: 1=false
                                                        rhs: 1=3, 2=0, 3=1
                                                        BAD
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:125: failed
                                                        stack traceback:
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:181: in function
                                                        [C]: in function 'error'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:125: in function 'simplifyAssertEq'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:168: in function
                                                        [C]: in function 'xpcall'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:167: in function 'simplifyAssertAllEq'
                                                        [string "do local expr = (3*x^2 + 1):factorDivision() ..."]:1: in main chunk
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:238: in function
                                                        [C]: in function 'xpcall'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:237: in function 'exec'
                                                        match.lua:233: in function 'cb'
                                                        /home/chris/Projects/lua/ext/timer.lua:54: in function 'timer'
                                                        match.lua:6: in main chunk
                                                        [C]: at 0x5602f61ee3e0 14 BAD
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:183: failed
                                                        stack traceback:
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:246: in function
                                                        [C]: in function 'error'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:183: in function 'simplifyAssertAllEq'
                                                        [string "do local expr = (3*x^2 + 1):factorDivision() ..."]:1: in main chunk
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:238: in function
                                                        [C]: in function 'xpcall'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:237: in function 'exec'
                                                        match.lua:233: in function 'cb'
                                                        /home/chris/Projects/lua/ext/timer.lua:54: in function 'timer'
                                                        match.lua:6: in main chunk
                                                        [C]: at 0x5602f61ee3e0
                                                        time: 9.692000ms
                                                        stack: size: 7
                                                        • Init
                                                        • Prune
                                                        • Expand
                                                        • Prune
                                                        • Factor
                                                        • Prune
                                                        • Tidy

                                                        do local expr = (3*x*x + 2*x + 1):factorDivision() printbr('expr', expr) local a, b, c = expr:match(W{1, cannotDependOn=x} * x^2 + W{2, cannotDependOn=x} * x + W{3, cannotDependOn=x}) printbr('a', a) printbr('b', b) printbr('c', c) simplifyAssertAllEq({a, b, c}, {3, 2, 1}) end
                                                        expr ${1} + {{{2}} {{x}}} + {{{3}} {{{x}^{2}}}}$
                                                        a $3$
                                                        b $2$
                                                        c $1$
                                                        ${3} = {3}$
                                                        ${3} = {3}$
                                                        ${3} = {3}$
                                                        ${2} = {2}$
                                                        ${2} = {2}$
                                                        ${1} = {1}$
                                                        ${1} = {1}$
                                                        GOOD
                                                        time: 15.512000ms
                                                        stack: size: 7
                                                        • Init
                                                        • Prune
                                                        • Expand
                                                        • Prune
                                                        • Factor
                                                        • Prune
                                                        • Tidy

                                                        do local expr = (1/(3*x*x + 2*x + 1)):factorDivision() printbr('expr', expr) local a, b, c = expr:match(1 / (W{1, cannotDependOn=x} * x^2 + W{2, cannotDependOn=x} * x + W{3, cannotDependOn=x})) printbr('a', a) printbr('b', b) printbr('c', c) simplifyAssertAllEq({a, b, c}, {3, 2, 1}) end
                                                        expr $\frac{1}{{1} + {{{2}} {{x}}} + {{{3}} {{{x}^{2}}}}}$
                                                        a $3$
                                                        b $2$
                                                        c $1$
                                                        ${3} = {3}$
                                                        ${3} = {3}$
                                                        ${3} = {3}$
                                                        ${2} = {2}$
                                                        ${2} = {2}$
                                                        ${1} = {1}$
                                                        ${1} = {1}$
                                                        GOOD
                                                        time: 21.006000ms
                                                        stack: size: 7
                                                        • Init
                                                        • Prune
                                                        • Expand
                                                        • Prune
                                                        • Factor
                                                        • Prune
                                                        • Tidy

                                                        do local expr = (x/(3*x*x + 2*x + 1)):factorDivision() printbr('expr', expr) local a, b, c = expr:match(1 / (W{1, cannotDependOn=x} * x^2 + W{2, cannotDependOn=x} * x + W{3, cannotDependOn=x})) printbr('a', a) printbr('b', b) printbr('c', c) simplifyAssertAllEq({a, b, c}, {3, 2, 1}) end
                                                        expr ${{x}} {{\frac{1}{{1} + {{{2}} {{x}}} + {{{3}} {{{x}^{2}}}}}}}$
                                                        a false
                                                        b nil
                                                        c nil
                                                        ${1} = {3}$
                                                        expected 1 to equal 3
                                                        found $1$ vs $3$
                                                        lhs stack
                                                        Init $1$
                                                        	1	

                                                        Prune $1$
                                                        	1	

                                                        Expand $1$
                                                        	1	

                                                        Prune $1$
                                                        	1	

                                                        Factor $1$
                                                        	1	

                                                        Prune $1$
                                                        	1	

                                                        Tidy $1$
                                                        	1	

                                                        rhs stack
                                                        Init $3$
                                                        	3	

                                                        Prune $3$
                                                        	3	

                                                        Expand $3$
                                                        	3	

                                                        Prune $3$
                                                        	3	

                                                        Factor $3$
                                                        	3	

                                                        Prune $3$
                                                        	3	

                                                        Tidy $3$
                                                        	3	

                                                        lhs: 1=false
                                                        rhs: 1=3, 2=2, 3=1
                                                        BAD
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:125: failed
                                                        stack traceback:
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:181: in function
                                                        [C]: in function 'error'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:125: in function 'simplifyAssertEq'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:168: in function
                                                        [C]: in function 'xpcall'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:167: in function 'simplifyAssertAllEq'
                                                        [string "do local expr = (x/(3*x*x + 2*x + 1)):factorD..."]:1: in main chunk
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:238: in function
                                                        [C]: in function 'xpcall'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:237: in function 'exec'
                                                        match.lua:233: in function 'cb'
                                                        /home/chris/Projects/lua/ext/timer.lua:54: in function 'timer'
                                                        match.lua:6: in main chunk
                                                        [C]: at 0x5602f61ee3e0 14 BAD
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:183: failed
                                                        stack traceback:
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:246: in function
                                                        [C]: in function 'error'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:183: in function 'simplifyAssertAllEq'
                                                        [string "do local expr = (x/(3*x*x + 2*x + 1)):factorD..."]:1: in main chunk
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:238: in function
                                                        [C]: in function 'xpcall'
                                                        /home/chris/Projects/lua/symmath/tests/unit/unit.lua:237: in function 'exec'
                                                        match.lua:233: in function 'cb'
                                                        /home/chris/Projects/lua/ext/timer.lua:54: in function 'timer'
                                                        match.lua:6: in main chunk
                                                        [C]: at 0x5602f61ee3e0
                                                        time: 24.731000ms
                                                        stack: size: 7
                                                        • Init
                                                        • Prune
                                                        • Expand
                                                        • Prune
                                                        • Factor
                                                        • Prune
                                                        • Tidy

                                                        TensorRef


                                                        local a = x'^i':match(Tensor.Ref(x, W(1))) simplifyAssertEq(a, Tensor.Index{symbol='i', lower=false})
                                                        ${^i} = {^i}$
                                                        GOOD
                                                        time: 0.992000ms
                                                        stack: size: 7
                                                        • Init
                                                        • Prune
                                                        • Expand
                                                        • Prune
                                                        • Factor
                                                        • Prune
                                                        • Tidy