3 // Cassowary Incremental Constraint Solver
4 // Original Smalltalk Implementation by Alan Borning
5 // This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
6 // http://www.cs.washington.edu/homes/gjb
7 // (C) 1998, 1999 Greg J. Badros and Alan Borning
8 // See ../LICENSE for legal details regarding this software
10 // ClFDBinaryOneWayConstraint.cc
15 #define CONFIG_H_INCLUDED
18 #include <cassowary/ClFDBinaryOneWayConstraint.h>
19 #include <cassowary/ClLinearConstraint.h>
20 #include <cassowary/ClTypedefs.h>
21 #include <cassowary/ClLinearExpression.h>
25 ClFDBinaryOneWayConstraint::EnsurePreconditionsForCn(const ClConstraint &cn)
27 ClVarSet setRO = cn.ReadOnlyVars();
29 throw ExCLTooDifficultSpecial("Only 0 or 1 read only variables are allowed");
30 const ClLinearExpression &expr = cn.Expression();
31 const ClVarToNumberMap &terms = expr.Terms();
33 throw ExCLTooDifficultSpecial("Cannot have more than 2 variables");
34 if (terms.size() == 0)
35 throw ExCLTooDifficultSpecial("Must have at least 1 variable");
36 if (terms.size() == 2 && setRO.size() == 0)
37 throw ExCLTooDifficultSpecial("Both variables cannot be read-write, one must be read-only");
38 if (terms.size() == 1 && setRO.size() == 1)
39 throw ExCLTooDifficultSpecial("Single read-only variable in LinearConstraint -- must not be read-only.");
40 ClVariable clv = (*terms.begin()).first;
41 /* GJB:FIXME:: iterate over all the variables */
42 if (!clv->IsFDVariable()) {
43 throw ExCLTooDifficultSpecial("FD constraint contains non-FD variables");
48 ClFDBinaryOneWayConstraint::FCanConvertCn(const ClConstraint &cn)
51 EnsurePreconditionsForCn(cn);
59 ClFDBinaryOneWayConstraint::ClFDBinaryOneWayConstraint(const ClConstraint &cn)
60 :ClFDConstraint(cn.strength(), cn.weight())
62 EnsurePreconditionsForCn(cn);
64 /* GJB:FIXME:: varargs inteface, with sentinel as first arg? */
71 ClVarSet setRO = cn.ReadOnlyVars();
73 ClVariable clvRO = clvNil;
74 ClVariable clvROLinear = clvNil;
77 ClVariable clvRW = clvNil;
80 if (setRO.size() == 1) {
81 const ClVariable &clv = *(setRO.begin());
82 if (clv->IsFDVariable())
85 clvRO = new ClFDVariable(clv.Name(),clv.IntValue(),l);
88 const ClLinearExpression &expr = cn.Expression();
89 const ClVarToNumberMap &terms = expr.Terms();
91 for (ClVarToNumberMap::const_iterator it = terms.begin();
94 ClVariable clv = (*it).first;
95 if (clv == clvROLinear) {
96 coeffRO = (*it).second;
98 if (clv->IsFDVariable())
101 clvRW = new ClFDVariable(clv.Name(),clv.Value(),l);
102 coeffRW = (*it).second;
105 assert(!clvRW.IsNil());
107 throw ExCLTooDifficultSpecial("RW variable's coefficient must be non-zero");
110 bool fInequality = cn.IsInequality();
111 bool fStrictInequality = cn.IsStrictInequality();
112 double rhs_constant = expr.Constant();
115 // coeffRW * clvRW + coeffRO * clvRO <REL> rhs_constant
116 // where <REL> is >= if fInequality, or = if !fInequality
119 // clvRW <REL> coefficient * clvRO + constant
122 // coefficient = -coeffRO/coeffRW
123 // constant = rhs_constant/coeffRW
125 if (fStrictInequality)
127 else if (fInequality)
133 _rel = ReverseInequality(_rel);
135 _coefficient = -coeffRO/coeffRW;
136 _constant = -rhs_constant/coeffRW;