/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "pgl/pgl.h"
#include "xstd/h/math.h"
#include <limits.h>
#include "pgl/PglBoolSym.h"
#include "pgl/PglNumSym.h"
#include "pgl/PglTimeSym.h"
#include "pgl/PglSizeSym.h"
#include "pgl/PglRateSym.h"
#include "pgl/PglBwidthSym.h"
#include "pgl/PglDistrSym.h"
#include "pgl/PglArraySym.h"
#include "pgl/PglIntSym.h"
#include "xstd/gadgets.h"
String IntSym::TheType = "int";
IntSym::IntSym(int aVal = -1): ExpressionSym(TheType), theVal(aVal) {
}
bool IntSym::isA(const String &type) const {
return ExpressionSym::isA(type) || type == TheType;
}
SynSym *IntSym::dupe(const String &type) const {
if (isA(type))
return new IntSym(theVal);
if (type == "float")
return new NumSym(theVal);
if (type == BoolSym::TheType)
return new BoolSym(theVal != 0);
// zero is zero regardless of strScale
if (!theVal) {
if (type == TimeSym::TheType)
return new TimeSym(Time(0,0));
if (type == SizeSym::TheType)
return new SizeSym(BigSize(0));
if (type == RateSym::TheType)
return new RateSym(0);
if (type == BwidthSym::TheType)
return new BwidthSym(0);
if (type.str("_distr"))
return new DistrSym(type, 0);
}
return ExpressionSym::dupe(type);
}
ExpressionSym *IntSym::unOper(const Oper &op) const {
if (op.plus())
return new IntSym(+theVal);
if (op.minus())
return new IntSym(-theVal);
if (op.boolNot())
return new BoolSym(!theVal);
return ExpressionSym::unOper(op);
}
ExpressionSym *IntSym::bnOper(const Oper &op, const SynSym &s) const {
double otherVal = 0;
if (s.isA(TheType)) {
otherVal = ((const IntSym&)s.cast(TheType)).val();
} else
if (IntSym *is = (IntSym*)s.clone(TheType)) {
otherVal = is->val();
delete is;
} else
return ExpressionSym::bnOper(op, s);
if (op.div()) {
checkDenom(otherVal);
return fit(op, theVal / otherVal);
}
if (op.range())
return operRange((int)otherVal);
if (op.same())
return new BoolSym(theVal == otherVal);
if (op.diff())
return new BoolSym(theVal != otherVal);
if (op.lessTrue())
return new BoolSym(theVal < otherVal);
if (op.lessOrEq())
return new BoolSym(theVal <= otherVal);
if (op.greaterTrue())
return new BoolSym(theVal > otherVal);
if (op.greaterOrEq())
return new BoolSym(theVal >= otherVal);
if (op.plus())
return fit(op, theVal + otherVal);
if (op.minus())
return fit(op, theVal - otherVal);
if (op.mult())
return fit(op, theVal * otherVal);
if (op.power())
return fit(op, pow(theVal, otherVal));
return ExpressionSym::bnOper(op, s);
}
IntSym *IntSym::fit(const Oper &op, double d) const {
return Fit(op, d, theLoc);
}
ExpressionSym *IntSym::operRange(int otherEnd) const {
ArraySym *arr = new ArraySym(TheType);
const int step = theVal <= otherEnd ? +1 : -1;
// not optimized; could use IntRangeArrayItem instead
for (int i = theVal; step*i <= step*otherEnd; i += step) {
arr->add(IntSym(i));
}
Assert(arr->count()); // empty ranges are probably impossible
return arr;
}
ostream &IntSym::print(ostream &os, const String &) const {
return os << theVal;
}
IntSym *IntSym::Fit(const Oper &op, double d, const TokenLoc &loc) {
if (fabs(d) > INT_MAX)
cerr << loc << "integer overflow as a result of `"
<< op.image() << "' (|" << d << "| > " << INT_MAX << ")"
<< endl << xexit;
return new IntSym((int)d);
}
syntax highlighted by Code2HTML, v. 0.9.1