1 /************************************************************************
2 ************************************************************************
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
24 /*****************************************************************************
25 ******************************************************************************/
28 * A Node is a tagged unions of int, double, symbol and void* used in the implementation of CTrees.
29 * Nodes are completly described by the node.h file, there is no node.cpp file.
33 * Node(symbol("abcd")); : node with symbol content
34 * Node(10); : node with int content
35 * Node(3.14159); : node with double content
37 * n->type(); : kIntNode or kDoubleNode or kSymNode
39 * n->getInt(); : int content of n
40 * n->getDouble(); : double content of n
41 * n->getSym(); : symbol content of n
43 * if (isInt(n, &i)) ... : int i = int content of n
44 * if (isDouble(n, &f)) ... : double f = double content of n
45 * if (isSym(n, &s)) ... : Sym s = Sym content of n
49 /******************************************************************************
50 *****************************************************************************/
62 * Tags used to define the type of a Node
64 enum { kIntNode, kDoubleNode, kSymNode, kPointerNode };
68 * Class Node = (type x (int + double + Sym + void*))
81 // constructeurs (assume size of field f is the biggest)
82 Node (int x) : fType(kIntNode) { fData.f = 0; fData.i = x; }
83 Node (double x) : fType(kDoubleNode) { fData.f = x; }
84 Node (const char* name) : fType(kSymNode) { fData.f = 0; fData.s = symbol(name); }
85 Node (const string& name) : fType(kSymNode) { fData.f = 0; fData.s = symbol(name); }
86 Node (Sym x) : fType(kSymNode) { fData.f = 0; fData.s = x; }
87 Node (void* x) : fType(kPointerNode) { fData.f = 0; fData.p = x; }
89 Node (const Node& n) : fType(n.fType) { fData = n.fData; }
92 bool operator == (const Node& n) const { return fType == n.fType && fData.f == n.fData.f; }
93 bool operator != (const Node& n) const { return fType != n.fType || fData.f != n.fData.f; }
96 int type() const { return fType; }
98 int getInt() const { return fData.i; }
99 double getDouble() const { return fData.f; }
100 Sym getSym() const { return fData.s; }
101 void* getPointer() const { return fData.p; }
103 // conversions and promotion for numbers
104 operator int() const { return (fType == kIntNode) ? fData.i : (fType == kDoubleNode) ? int(fData.f) : 0 ; }
105 operator double() const { return (fType == kIntNode) ? double(fData.i) : (fType == kDoubleNode) ? fData.f : 0.0 ; }
107 ostream& print (ostream& fout) const; ///< print a node on a stream
111 inline ostream& operator << (ostream& s, const Node& n) { return n.print(s); }
115 //-------------------------------------------------------------------------
116 // Perdicates and pattern matching
117 //-------------------------------------------------------------------------
120 inline bool isInt (const Node& n)
122 return (n.type() == kIntNode);
125 inline bool isInt (const Node& n, int* x)
127 if (n.type() == kIntNode) {
137 inline bool isDouble (const Node& n)
139 return (n.type() == kDoubleNode);
142 inline bool isDouble (const Node& n, double* x)
144 if (n.type() == kDoubleNode) {
154 inline bool isZero (const Node& n)
156 return (n.type() == kDoubleNode) && (n.getDouble() == 0.0)
157 || (n.type() == kIntNode) && (n.getInt() == 0);
160 inline bool isGEZero (const Node& n)
162 return (n.type() == kDoubleNode) && (n.getDouble() >= 0.0)
163 || (n.type() == kIntNode) && (n.getInt() >= 0);
166 inline bool isGTZero (const Node& n)
168 return (n.type() == kDoubleNode) && (n.getDouble() > 0.0)
169 || (n.type() == kIntNode) && (n.getInt() > 0);
172 inline bool isOne (const Node& n)
174 return (n.type() == kDoubleNode) && (n.getDouble() == 1.0)
175 || (n.type() == kIntNode) && (n.getInt() == 1);
178 inline bool isMinusOne (const Node& n)
180 return (n.type() == kDoubleNode) && (n.getDouble() == -1.0)
181 || (n.type() == kIntNode) && (n.getInt() == -1);
185 // numbers in general
186 inline bool isNum (const Node& n)
188 return isInt(n)||isDouble(n);
193 inline bool isSym (const Node& n)
195 return (n.type() == kSymNode);
198 inline bool isSym (const Node& n, Sym* x)
200 if (n.type() == kSymNode) {
210 inline bool isPointer (const Node& n)
212 return (n.type() == kPointerNode);
215 inline bool isPointer (const Node& n, void** x)
217 if (n.type() == kPointerNode) {
228 //-------------------------------------------------------------------------
229 // Mathematical operations on nodes
230 //-------------------------------------------------------------------------
233 // arithmetic operations
235 inline const Node addNode (const Node& x, const Node& y)
236 { return (isDouble(x)||isDouble(y)) ? Node(double(x)+double(y)) : Node(int(x)+int(y)); }
238 inline const Node subNode (const Node& x, const Node& y)
239 { return (isDouble(x)||isDouble(y)) ? Node(double(x)-double(y)) : Node(int(x)-int(y)); }
241 inline const Node mulNode (const Node& x, const Node& y)
242 { return (isDouble(x)||isDouble(y)) ? Node(double(x)*double(y)) : Node(int(x)*int(y)); }
244 inline const Node divNode (const Node& x, const Node& y)
245 { return (isDouble(x)||isDouble(y)) ? Node(double(x)/double(y)) : Node(int(x)/int(y)); }
247 inline const Node divExtendedNode (const Node& x, const Node& y)
248 { return (isDouble(x)||isDouble(y)) ? Node(double(x)/double(y))
249 : (double(int(x)/int(y))==double(x)/double(y)) ? Node(int(x)/int(y))
250 : Node(double(x)/double(y)); }
252 inline const Node remNode (const Node& x, const Node& y)
253 { return Node(int(x)%int(y)); }
257 inline const Node minusNode (const Node& x)
258 { return subNode(0, x); }
260 inline const Node inverseNode (const Node& x)
261 { return divNode(1.0f, x); }
264 // bit shifting operations
266 inline const Node lshNode (const Node& x, const Node& y)
267 { return Node(int(x)<<int(y)); }
269 inline const Node rshNode (const Node& x, const Node& y)
270 { return Node(int(x)>>int(y)); }
273 // boolean operations on bits
275 inline const Node andNode (const Node& x, const Node& y)
276 { return Node(int(x)&int(y)); }
278 inline const Node orNode (const Node& x, const Node& y)
279 { return Node(int(x)|int(y)); }
281 inline const Node xorNode (const Node& x, const Node& y)
282 { return Node(int(x)^int(y)); }
285 // compare operations
287 inline const Node gtNode (const Node& x, const Node& y)
288 { return (isDouble(x)||isDouble(y)) ? Node(double(x)>double(y)) : Node(int(x)>int(y)); }
290 inline const Node ltNode (const Node& x, const Node& y)
291 { return (isDouble(x)||isDouble(y)) ? Node(double(x)<double(y)) : Node(int(x)<int(y)); }
293 inline const Node geNode (const Node& x, const Node& y)
294 { return (isDouble(x)||isDouble(y)) ? Node(double(x)>=double(y)) : Node(int(x)>=int(y)); }
296 inline const Node leNode (const Node& x, const Node& y)
297 { return (isDouble(x)||isDouble(y)) ? Node(double(x)<=double(y)) : Node(int(x)<=int(y)); }
299 inline const Node eqNode (const Node& x, const Node& y)
300 { return (isDouble(x)||isDouble(y)) ? Node(double(x)==double(y)) : Node(int(x)==int(y)); }
302 inline const Node neNode (const Node& x, const Node& y)
303 { return (isDouble(x)||isDouble(y)) ? Node(double(x)!=double(y)) : Node(int(x)!=int(y)); }