1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
#include "xtended.hh"
#include "Text.hh"
#include <math.h>
#include "sigtyperules.hh"
#include "floats.hh"
class MaxPrim : public xtended
{
public:
MaxPrim() : xtended("max") {}
virtual unsigned int arity () { return 2; }
virtual bool needCache () { return true; }
virtual Type infereSigType (const vector<Type>& types)
{
assert (types.size() == arity());
interval i = types[0]->getInterval();
interval j = types[1]->getInterval();
return castInterval(types[0]|types[1], max(i,j));
}
virtual void sigVisit (Tree sig, sigvisitor* visitor) {}
virtual int infereSigOrder (const vector<int>& args)
{
assert (args.size() == arity());
return max(args[0], args[1]);
}
virtual Tree computeSigOutput (const vector<Tree>& args)
{
double f,g; int i,j;
assert (args.size() == arity());
if (isDouble(args[0]->node(),&f)) {
if (isDouble(args[1]->node(), &g)) {
return tree(max(f, g));
} else if (isInt(args[1]->node(),&j)) {
return tree(max(f, double(j)));
} else {
return tree(symbol(), args[0], args[1]);
}
} else if (isInt(args[0]->node(),&i)) {
if (isDouble(args[1]->node(), &g)) {
return tree(max(double(i), g));
} else if (isInt(args[1]->node(),&j)) {
return tree(max(i, j));
} else {
return tree(symbol(), args[0], args[1]);
}
} else {
return tree(symbol(), args[0], args[1]);
}
}
virtual string generateCode (Klass* klass, const vector<string>& args, const vector<Type>& types)
{
assert (args.size() == arity());
assert (types.size() == arity());
// generates code compatible with overloaded max
int n0 = types[0]->nature();
int n1 = types[1]->nature();
if (n0==kReal) {
if (n1==kReal) {
// both are floats, no need to cast
return subst("max($0, $1)", args[0], args[1]);
} else {
assert(n1==kInt); // second argument is not float, cast it to float
return subst("max($0, $2$1)", args[0], args[1], icast());
}
} else if (n1==kReal) {
assert(n0==kInt); // first not float but second is, cast first to float
return subst("max($2$0, $1)", args[0], args[1], icast());
} else {
assert(n0==kInt); assert(n1==kInt); // both are integers, check for booleans
int b0 = types[0]->boolean();
int b1 = types[1]->boolean();
if (b0==kNum) {
if (b1==kNum) {
// both are integers, no need to cast
return subst("max($0, $1)", args[0], args[1]);
} else {
assert(b1==kBool); // second is boolean, cast to int
return subst("max($0, (int)$1)", args[0], args[1]);
}
} else if (b1==kNum) {
assert(b0==kBool); // first is boolean, cast to int
return subst("max((int)$0, $1)", args[0], args[1], icast());
} else {
// both are booleans, theoratically no need to cast, but we still do it to be sure 'true' is actually '1'
// and 'false' is actually '0' (which is not the case if compiled in SSE mode)
assert(b0==kBool); assert(b1==kBool);
return subst("max((int)$0, (int)$1)", args[0], args[1]);
}
}
}
virtual string generateLateq (Lateq* lateq, const vector<string>& args, const vector<Type>& types)
{
assert (args.size() == arity());
assert (types.size() == arity());
Type t = infereSigType(types);
return subst("\\max\\left( $0, $1 \\right)", args[0], args[1]);
}
};
xtended* gMaxPrim = new MaxPrim();
|