summaryrefslogtreecommitdiff
path: root/libs/cassowary/cassowary/ClLinearExpression.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cassowary/cassowary/ClLinearExpression.h')
-rw-r--r--libs/cassowary/cassowary/ClLinearExpression.h298
1 files changed, 298 insertions, 0 deletions
diff --git a/libs/cassowary/cassowary/ClLinearExpression.h b/libs/cassowary/cassowary/ClLinearExpression.h
new file mode 100644
index 0000000000..0a1df9c243
--- /dev/null
+++ b/libs/cassowary/cassowary/ClLinearExpression.h
@@ -0,0 +1,298 @@
+// $Id$
+//
+// Cassowary Incremental Constraint Solver
+// Original Smalltalk Implementation by Alan Borning
+// This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
+// http://www.cs.washington.edu/homes/gjb
+// (C) 1998, 1999 Greg J. Badros and Alan Borning
+// See ../LICENSE for legal details regarding this software
+//
+// ClLinearExpression.h
+
+#ifndef ClLinearExpression_H
+#define ClLinearExpression_H
+
+#if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
+#include <cassowary/config-inline.h>
+#define CONFIG_INLINE_H_INCLUDED
+#endif
+
+#include "Cassowary.h"
+#include "debug.h"
+#include "ClVariable.h"
+#include "ClLinearExpression_fwd.h"
+
+class ClSimplexSolver;
+class ClTableau;
+class ClSymbolicWeight;
+
+ClLinearExpression &cleNil();
+
+template <class T>
+class ClGenericLinearExpression {
+ public:
+ typedef std::map<ClVariable,T> ClVarToCoeffMap;
+
+ // convert Number-s into ClLinearExpression-s
+ ClGenericLinearExpression(T num = 0.0);
+
+ // Convert from ClVariable to a ClLinearExpression
+ // this replaces ClVariable::asLinearExpression
+ ClGenericLinearExpression(ClVariable clv, T value = 1.0, T constant = 0.0);
+
+ // copy ctr
+ ClGenericLinearExpression(const ClGenericLinearExpression<T> &expr) :
+ _constant(expr._constant),
+ _terms(expr._terms)
+ { }
+
+ virtual ~ClGenericLinearExpression();
+
+ // Return a new linear expression formed by multiplying self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> Times(Number x) const;
+
+ // Return a new linear expression formed by multiplying self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> Times(const ClGenericLinearExpression<T> &expr) const;
+
+ // Return a new linear expression formed by adding x to self.
+ ClGenericLinearExpression<T> Plus(const ClGenericLinearExpression<T> &expr) const;
+
+ // Return a new linear expression formed by subtracting x from self.
+ ClGenericLinearExpression<T> Minus(const ClGenericLinearExpression<T> &expr) const;
+
+ // Return a new linear expression formed by dividing self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> Divide(Number x) const;
+
+
+
+ // Return a new linear expression formed by multiplying self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> *P_times(Number x) const
+ { return new ClGenericLinearExpression<T>(Times(x)); }
+
+ // Return a new linear expression formed by adding x to self.
+ ClGenericLinearExpression<T> *P_plus(const ClGenericLinearExpression<T> &expr) const
+ { return new ClGenericLinearExpression<T>(Plus(expr)); }
+
+ // Return a new linear expression formed by subtracting x from self.
+ ClGenericLinearExpression<T> *P_minus(const ClGenericLinearExpression<T> &expr) const
+ { return new ClGenericLinearExpression<T>(Minus(expr)); }
+
+ // Return a new linear expression formed by dividing self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> *P_divide(Number x) const
+ { return new ClGenericLinearExpression<T>(Divide(x)); }
+
+ // Return a new linear expression formed by dividing self by x.
+ // (Note that this result must be linear.)
+ ClGenericLinearExpression<T> Divide(const ClGenericLinearExpression<T> &expr) const;
+
+ // Return a new linear expression (aNumber/this). Since the result
+ // must be linear, this is permissible only if 'this' is a constant.
+ ClGenericLinearExpression<T> DivFrom(const ClGenericLinearExpression<T> &expr) const;
+
+ // Return a new linear expression (aNumber-this).
+ ClGenericLinearExpression<T> SubtractFrom(const ClGenericLinearExpression<T> &expr) const
+ { return expr.Minus(*this); }
+
+ // Add n*expr to this expression from another expression expr.
+ ClGenericLinearExpression<T> &AddExpression(const ClGenericLinearExpression<T> &expr,
+ Number n = 1.0);
+
+ // Add n*expr to this expression from another expression expr.
+ // Notify the solver if a variable is added or deleted from this
+ // expression.
+ ClGenericLinearExpression<T> &AddExpression(const ClGenericLinearExpression<T> &expr, Number n,
+ ClVariable subject,
+ ClTableau &solver);
+
+ // Add a term c*v to this expression. If the expression already
+ // contains a term involving v, Add c to the existing coefficient.
+ // If the new coefficient is approximately 0, delete v.
+ ClGenericLinearExpression<T> &AddVariable(ClVariable v, T c = 1.0);
+
+ // Add a term c*v to this expression. If the expression already
+ // contains a term involving v, Add c to the existing coefficient.
+ // If the new coefficient is approximately 0, delete v.
+ ClGenericLinearExpression<T> &setVariable(ClVariable v, T c)
+ {assert(c != 0.0); _terms[v] = c; return *this; }
+
+ // Add a term c*v to this expression. If the expression already
+ // contains a term involving v, Add c to the existing coefficient.
+ // If the new coefficient is approximately 0, delete v. Notify the
+ // solver if v appears or disappears from this expression.
+ ClGenericLinearExpression<T> &AddVariable(ClVariable v, T c,
+ ClVariable subject,
+ ClTableau &solver);
+
+ // Return a pivotable variable in this expression. (It is an error
+ // if this expression is constant -- signal ExCLInternalError in
+ // that case). Return NULL if no pivotable variables
+ ClVariable AnyPivotableVariable() const;
+
+ // Replace var with a symbolic expression expr that is equal to it.
+ // If a variable has been added to this expression that wasn't there
+ // before, or if a variable has been dropped from this expression
+ // because it now has a coefficient of 0, inform the solver.
+ // PRECONDITIONS:
+ // var occurs with a non-Zero coefficient in this expression.
+ void SubstituteOut(ClVariable v,
+ const ClGenericLinearExpression<T> &expr,
+ ClVariable subject,
+ ClTableau &solver);
+
+ // This linear expression currently represents the equation
+ // oldSubject=self. Destructively modify it so that it represents
+ // the equation NewSubject=self.
+ //
+ // Precondition: NewSubject currently has a nonzero coefficient in
+ // this expression.
+ //
+ // NOTES
+ // Suppose this expression is c + a*NewSubject + a1*v1 + ... + an*vn.
+ //
+ // Then the current equation is
+ // oldSubject = c + a*NewSubject + a1*v1 + ... + an*vn.
+ // The new equation will be
+ // NewSubject = -c/a + oldSubject/a - (a1/a)*v1 - ... - (an/a)*vn.
+ // Note that the term involving NewSubject has been dropped.
+ void ChangeSubject(ClVariable old_subject,
+ ClVariable new_subject);
+
+ // This linear expression currently represents the equation self=0. Destructively modify it so
+ // that subject=self represents an equivalent equation.
+ //
+ // Precondition: subject must be one of the variables in this expression.
+ // NOTES
+ // Suppose this expression is
+ // c + a*subject + a1*v1 + ... + an*vn
+ // representing
+ // c + a*subject + a1*v1 + ... + an*vn = 0
+ // The modified expression will be
+ // subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn
+ // representing
+ // subject = -c/a - (a1/a)*v1 - ... - (an/a)*vn
+ //
+ // Note that the term involving subject has been dropped.
+ // Returns the reciprocal, so ChangeSubject can use it, too
+ T NewSubject(ClVariable subject);
+
+ // Return the value of the linear expression
+ // given the current assignments of values to contained variables
+ T Evaluate() const;
+
+ // Return the coefficient corresponding to variable var, i.e.,
+ // the 'ci' corresponding to the 'vi' that var is:
+ // v1*c1 + v2*c2 + .. + vn*cn + c
+ T CoefficientFor(ClVariable var) const
+ {
+ typename ClVarToCoeffMap::const_iterator it = _terms.find(var);
+ if (it != _terms.end())
+ return (*it).second;
+ return 0.0;
+ }
+
+ T Constant() const
+ { return _constant; }
+
+ void Set_constant(T c)
+ { _constant = c; }
+
+ const ClVarToCoeffMap &Terms() const
+ { return _terms; }
+
+ ClVarToCoeffMap &Terms()
+ { return _terms; }
+
+ void IncrementConstant(T c)
+ { _constant += c; }
+
+ bool IsConstant() const
+ { return _terms.size() == 0; }
+
+#ifndef CL_NO_IO
+ virtual ostream &PrintOn(ostream &xo) const;
+
+ friend ostream &operator<<(ostream &xo,const ClGenericLinearExpression<T> &cle)
+ { return cle.PrintOn(xo); }
+#endif
+
+ friend ClGenericLinearExpression<T> operator+(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Plus(e2); }
+
+ friend ClGenericLinearExpression<T> operator-(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Minus(e2); }
+
+ friend ClGenericLinearExpression<T> operator*(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Times(e2); }
+
+
+ friend ClGenericLinearExpression<T> operator/(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Divide(e2); }
+
+ // FIXGJB -- this may be wrong -- should test underlying expression for equality
+ friend bool operator==(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return &e1 == &e2; }
+
+ /// Named versions of the operator functions for ease of
+ /// wrapping, or expressing using prefix notation
+
+ friend ClGenericLinearExpression<T> Plus(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Plus(e2); }
+
+ friend ClGenericLinearExpression<T> Minus(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Minus(e2); }
+
+ friend ClGenericLinearExpression<T> Times(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return e1.Times(e2); }
+
+
+ friend ClGenericLinearExpression<T> *Divide(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return new ClGenericLinearExpression<T>(e1.Divide(e2)); }
+
+ friend ClGenericLinearExpression<T> *p_Plus(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return new ClGenericLinearExpression<T>(e1.Plus(e2)); }
+
+ friend ClGenericLinearExpression<T> *p_Minus(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return new ClGenericLinearExpression<T>(e1.Minus(e2)); }
+
+ friend ClGenericLinearExpression<T> *p_Times(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return new ClGenericLinearExpression<T>(e1.Times(e2)); }
+
+ friend ClGenericLinearExpression<T> *p_Divide(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return new ClGenericLinearExpression<T>(e1.Divide(e2)); }
+
+
+ // FIXGJB -- this may be wrong -- should test underlying expression for equality
+ friend bool FEquals(const ClGenericLinearExpression<T> &e1,
+ const ClGenericLinearExpression<T> &e2)
+ { return &e1 == &e2; }
+
+ ClGenericLinearExpression<T> &MultiplyMe(T x);
+
+ private:
+
+ T _constant;
+ ClVarToCoeffMap _terms;
+
+};
+
+typedef ClGenericLinearExpression<Number>::ClVarToCoeffMap ClVarToNumberMap;
+
+#endif