1c0339c887f145dd87d1fabbbb0dca91f747be11
[ardour.git] / libs / cassowary / cassowary / ClSymbolicWeight.h
1 // $Id$
2 //
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
9 //
10 // ClSymbolicWeight.h
11
12 #ifndef ClSymbolicWeight_H
13 #define ClSymbolicWeight_H
14
15 #if defined(HAVE_CONFIG_H) && !defined(CONFIG_H_INCLUDED) && !defined(CONFIG_INLINE_H_INCLUDED)
16 #include <cassowary/config-inline.h>
17 #define CONFIG_INLINE_H_INCLUDED
18 #endif
19
20 #include "Cassowary.h"
21 #include "ClErrors.h"
22 #include <vector>
23 #include <iostream>
24
25 using std::vector;
26 using std::ostream;
27
28 class ClSymbolicWeight {
29  public:
30   ClSymbolicWeight(unsigned int CLevels = 3, Number value = 0.0);
31
32   ClSymbolicWeight(Number w1, Number w2, Number w3);
33
34   ClSymbolicWeight(const vector<Number> &weights);
35
36   static ClSymbolicWeight &Zero();
37
38   ClSymbolicWeight &negated();
39
40   ClSymbolicWeight &MultiplyMe(Number n);
41
42   ClSymbolicWeight Times(Number n) const
43     { ClSymbolicWeight cl = *this; cl.MultiplyMe(n); return cl; }
44
45   ClSymbolicWeight DivideBy(Number n) const;
46
47   ClSymbolicWeight &addtoMe(const ClSymbolicWeight &cl);
48
49   ClSymbolicWeight Add(const ClSymbolicWeight &cl) const
50     { ClSymbolicWeight clRet = *this; clRet.addtoMe(cl); return clRet; }
51
52   ClSymbolicWeight Subtract(const ClSymbolicWeight &cl) const;
53
54   ClSymbolicWeight operator*(const Number &n) const
55     { return Times(n); }
56
57   ClSymbolicWeight operator/(const Number &n) const
58     { return DivideBy(n); }
59
60   // FIXGJB: can we express this statically?
61   ClSymbolicWeight operator*(ClSymbolicWeight &w) const
62     { throw ExCLInternalError("Multiplication of symbolic weights encountered"); 
63       return w; }
64   ClSymbolicWeight &operator*=(ClSymbolicWeight &w)
65     { throw ExCLInternalError("Multiplicative assignment of symbolic weights encountered"); 
66       return w; }
67
68   // FIXGJB: can we express this statically?
69   ClSymbolicWeight operator-() const
70     { throw ExCLInternalError("Can not negate a symbolic weight");
71       return ClSymbolicWeight::Zero(); }
72
73   friend ClSymbolicWeight ReciprocalOf(const ClSymbolicWeight &);
74
75   ClSymbolicWeight &operator*=(const Number &n)
76     { return MultiplyMe(n); }
77
78   ClSymbolicWeight operator+(const ClSymbolicWeight &cl) const
79     { return Add(cl); }
80
81   ClSymbolicWeight operator+=(const ClSymbolicWeight &cl)
82     { return addtoMe(cl); }
83
84   ClSymbolicWeight operator*(const Number &n)
85     { ClSymbolicWeight answer(*this);
86       answer *= n;
87       return answer; }
88
89   bool lessThan(const ClSymbolicWeight &cl) const;
90   bool lessThanOrEqual(const ClSymbolicWeight &cl) const;
91   bool equal(const ClSymbolicWeight &cl) const;
92   bool greaterThan(const ClSymbolicWeight &cl) const;
93   bool greaterThanOrEqual(const ClSymbolicWeight &cl) const;
94   bool isNegative() const;
95
96   friend bool operator==(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2)
97     { return cl1.equal(cl2); }
98
99   friend bool operator!=(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2)
100     { return !(cl1 == cl2); }
101
102   friend bool operator<(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2)
103     { return cl1.lessThan(cl2); }
104
105   friend bool operator>(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2)
106   { return (cl2 < cl1); }
107
108   // function.h provides operator>, >=, <= from operator<
109
110   double AsDouble() const
111     {
112     vector<Number>::const_reverse_iterator i = _values.rbegin();
113     Number sum  = 0;
114     Number factor = 1;
115     // A. Beurive' Wed Jul  7 11:07:47 CEST 1999
116     Number multiplier = 1000000;
117     for ( ; i != _values.rend(); ++i) 
118       {
119       sum += *i * factor;
120       factor *= multiplier;
121       }
122     return sum;
123     }
124
125 #ifndef CL_NO_IO
126   ostream &PrintOn(ostream &xo) const
127     { 
128     vector<Number>::const_iterator i = _values.begin();
129     if (i == _values.end())
130       return xo;
131
132     xo << *i;
133     for (++i; i != _values.end(); ++i) 
134       {
135       xo << "," << *i;
136       }
137     return xo;
138     }
139
140   // FIXGJB: use a template function to generate these automatically
141   friend ostream& operator<<(ostream &xos, const ClSymbolicWeight &clsw)
142     { clsw.PrintOn(xos); return xos; }
143 #endif
144
145   int CLevels() const
146     { return _values.size(); }
147
148   friend bool ClApprox(const ClSymbolicWeight &cl, Number n);
149   friend bool ClApprox(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2);
150
151  private:
152   vector<Number> _values;
153
154   void push_back(Number d) 
155     { _values.push_back(d); }
156
157 };
158
159 inline bool ClApprox(const ClSymbolicWeight &cl, Number n)
160 {
161   vector<Number>::const_iterator it = cl._values.begin();
162   if (!ClApprox(*it,n))
163     return false;
164
165   ++it;
166   for (; it != cl._values.end(); ++it)
167     {
168     if (!ClApprox(*it,0))
169       return false;
170     }
171
172   return true;
173 }
174
175 inline bool ClApprox(const ClSymbolicWeight &cl1, const ClSymbolicWeight &cl2)
176 {
177   vector<Number>::const_iterator it1 = cl1._values.begin();
178   vector<Number>::const_iterator it2 = cl2._values.begin();
179
180   for (; it1 != cl1._values.end() && it2 != cl2._values.end(); 
181        ++it1, ++it2)
182     {
183     if (!ClApprox(*it1,*it2))
184       return false;
185     }
186
187   if (it1 == cl1._values.end() && it2 == cl2._values.end())
188     return true;
189
190   return false;
191 }
192
193 inline ClSymbolicWeight ReciprocalOf(const ClSymbolicWeight &)
194 { throw(ExCLInternalError("Cannot take ReciprocalOf symbolic weight"));
195   return ClSymbolicWeight::Zero(); }
196
197 #endif