func (cs *CS) add(c1 *Constraint, c2 *Constraint) *Constraint {
	expression := &linearExpression{
		term{Wire: c1.outputWire, Coeff: bigOne()},
		term{Wire: c2.outputWire, Coeff: bigOne()},
	}
	return newConstraint(cs, expression)
}
ADD generic version for adding 2 constraints
package frontend
import (
	"errors"
	"fmt"
	"math/big"
	"strconv"
	"github.com/consensys/gnark/backend"
	"github.com/consensys/gnark/internal/utils/debug"
)
var (
	ErrInconsistantConstraint = errors.New("inconsistant constraint")
)
type CS struct {
	Constraints map[uint64]*Constraint
	MOConstraints []moExpression
	NOConstraints []expression
	nbConstraints uint64
}
func New() CS {
	cs := CS{
		Constraints: make(map[uint64]*Constraint),
	}
	oneConstraint := &Constraint{
		outputWire: &wire{
			Name:         backend.OneWire,
			WireID:       -1,
			ConstraintID: -1,
			IsConsumed:   true,  
			Tags:         []string{},
		},
	}
	cs.addConstraint(oneConstraint)
	return cs
}
func (cs *CS) addConstraint(c *Constraint) {
	debug.Assert(c.constraintID == 0)
	c.constraintID = cs.nbConstraints
	cs.Constraints[c.constraintID] = c
	cs.nbConstraints++
}
func (cs *CS) mul(c1, c2 *Constraint) *Constraint {
	expression := &quadraticExpression{
		left:      linearExpression{term{Wire: c1.outputWire, Coeff: bigOne()}},
		right:     linearExpression{term{Wire: c2.outputWire, Coeff: bigOne()}},
		operation: mul,
	}
	return newConstraint(cs, expression)
}
func (cs *CS) mulConstant(c *Constraint, constant big.Int) *Constraint {
	expression := &term{
		Wire:      c.outputWire,
		Coeff:     constant,
		Operation: mul,
	}
	return newConstraint(cs, expression)
}
func (cs *CS) div(c1, c2 *Constraint) *Constraint {
	expression := quadraticExpression{
		left:      linearExpression{term{Wire: c2.outputWire, Coeff: bigOne()}},
		right:     linearExpression{term{Wire: c1.outputWire, Coeff: bigOne()}},
		operation: div,
	}
	return newConstraint(cs, &expression)
}
func (cs *CS) divConstantRight(c1 *Constraint, c2 big.Int) *Constraint {
	expression := quadraticExpression{
		left:      linearExpression{term{Wire: cs.Constraints[0].outputWire, Coeff: c2}},
		right:     linearExpression{term{Wire: c1.outputWire, Coeff: bigOne()}},
		operation: div,
	}
	return newConstraint(cs, &expression)
}
func (cs *CS) divConstantLeft(c1 big.Int, c2 *Constraint) *Constraint {
	expression := quadraticExpression{
		left:      linearExpression{term{Wire: c2.outputWire, Coeff: bigOne()}},
		right:     linearExpression{term{Wire: cs.Constraints[0].outputWire, Coeff: c1}},
		operation: div,
	}
	return newConstraint(cs, &expression)
}
func (cs *CS) inv(c1 *Constraint, e big.Int) *Constraint {
	expression := &term{
		Wire:      c1.outputWire,
		Coeff:     e,
		Operation: div,
	}
	return newConstraint(cs, expression)
}