func (cs *CS) equalConstant(c *Constraint, constant big.Int) error {
	if c.outputWire.isUserInput() {
		return fmt.Errorf("%w: %q", ErrInconsistantConstraint, "(user input == VALUE) is invalid")
	}
	c.expressions = append(c.expressions, &eqConstantExpression{v: constant})
	return nil
}
equalConstant Equal a constraint to a constant
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)
}
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)
}
func (cs *CS) addConstant(c *Constraint, constant big.Int) *Constraint {
	expression := &linearExpression{
		term{Wire: c.outputWire, Coeff: bigOne()},
		term{Wire: cs.Constraints[0].outputWire, Coeff: constant},
	}
	return newConstraint(cs, expression)
}
func (cs *CS) sub(c1 *Constraint, c2 *Constraint) *Constraint {
	var minusOne big.Int
	one := bigOne()
	minusOne.Neg(&one)
	expression := &linearExpression{
		term{Wire: c1.outputWire, Coeff: one},
		term{Wire: c2.outputWire, Coeff: minusOne},
	}
	return newConstraint(cs, expression)
}
func (cs *CS) subConstant(c *Constraint, constant big.Int) *Constraint {
	var minusOne big.Int
	one := bigOne()
	minusOne.Neg((&constant))
	expression := &linearExpression{
		term{Wire: c.outputWire, Coeff: one},
		term{Wire: cs.Constraints[0].outputWire, Coeff: minusOne},
	}
	return newConstraint(cs, expression)
}
func (cs *CS) subConstraint(constant big.Int, c *Constraint) *Constraint {
	var minusOne big.Int
	one := bigOne()
	minusOne.Neg((&one))
	expression := &linearExpression{
		term{Wire: cs.Constraints[0].outputWire, Coeff: constant},
		term{Wire: c.outputWire, Coeff: minusOne},
	}
	return newConstraint(cs, expression)
}
func (cs *CS) divlc(num, den LinearCombination) *Constraint {
	var left, right linearExpression
	for _, t := range den {
		left = append(left, term{Wire: t.Constraint.outputWire, Coeff: t.Coeff, Operation: mul})
	}
	for _, t := range num {
		right = append(right, term{Wire: t.Constraint.outputWire, Coeff: t.Coeff, Operation: mul})
	}
	expression := &quadraticExpression{
		left:      left,
		right:     right,
		operation: div,
	}
	return newConstraint(cs, expression)
}
func (cs *CS) mullc(l1, l2 LinearCombination) *Constraint {
	var left, right linearExpression
	for _, t := range l1 {
		left = append(left, term{Wire: t.Constraint.outputWire, Coeff: t.Coeff, Operation: mul})
	}
	for _, t := range l2 {
		right = append(right, term{Wire: t.Constraint.outputWire, Coeff: t.Coeff, Operation: mul})
	}
	expression := &quadraticExpression{
		left:  left,
		right: right,
	}
	return newConstraint(cs, expression)
}
func (cs *CS) equal(c1, c2 *Constraint) error {
	if c1 == c2 {
		return fmt.Errorf("%w: %q", ErrInconsistantConstraint, "(user input 1 == user input 1) is invalid")
	}
	if c1.outputWire != nil && c2.outputWire != nil {
		if c1.outputWire.isUserInput() && c2.outputWire.isUserInput() {
			return fmt.Errorf("%w: %q", ErrInconsistantConstraint, "(user input 1 == user input 2) is invalid")
		}
	}
	if c2.outputWire != nil && c1.outputWire != nil {
		if c1.outputWire.isUserInput() {
			c2, c1 = c1, c2
		}
	}
	c1.expressions = append(c1.expressions, c2.expressions...)
	if c2.outputWire != nil && c1.outputWire != nil {
		wireToReplace := c1.outputWire
		c2.outputWire.Tags = append(c2.outputWire.Tags, c1.outputWire.Tags...)
		c1.outputWire = c2.outputWire
		for _, c := range cs.Constraints {
			for _, e := range c.expressions {
				e.replaceWire(wireToReplace, c2.outputWire)
			}
		}
		for _, moe := range cs.MOConstraints {
			moe.replaceWire(wireToReplace, c2.outputWire)
		}
		for _, noe := range cs.NOConstraints {
			noe.replaceWire(wireToReplace, c2.outputWire)
		}
	}
	delete(cs.Constraints, c2.constraintID)
	*c2 = *c1
	cs.Constraints[c1.constraintID] = c1
	return nil
}