#include #include #include #include "ClassDecl.h" #include "CfHeader.h" #include "CfSource.h" #include "CtGlobal.h" #include "CtLocal.h" #include "CtPointInstance.h" #include "PrimitiveDecl.h" #include "code.h" #include "compiler.h" #include "domain-decls.h" #include "utils.h" ClassDecl *PointUtilsDecl; #define P(digits) MANGLE_TI_DOMAINS_POINT_ARG(+, digits) #define M(name, arity, args) MANGLE_TI_DOMAINS_POINT_DISPATCH(<<, name, arity, args) /* Define Pn_construct() and Pn_empty(). */ static void createPointConstruct(ostream &hFile, int arity, const string digits) { hFile << "#define " << MANGLE_TI_DOMAINS_POINT_CONSTRUCT(<<, digits) << "p"; for (int i = 0; i < arity; i++) hFile << ", v" << i; hFile << ") \\\n"; hFile << "do { \\\n"; for (int i = 0; i < arity; i++) hFile << " p.x" << i << " = v" << i << "; \\\n"; hFile << "} while (0)\n\n"; hFile << "#define " << MANGLE_TI_DOMAINS_POINT_EMPTY(<<, digits) << " " << M("all", digits, MANGLE_INT_ARG(<<)) << "(0)\n\n"; } /* Point op Point. */ static void createPointOp(ostream &hFile, int arity, const string digits, const char *op, const char *name) { hFile << "INLINE_MODIFIER " << P(digits) << " " << M(name, digits, P(digits)) << "(" << P(digits) << " p1, " << P(digits) << " p2)\n{\n"; hFile << " " << P(digits) << " ret;\n"; for (int i = 0; i < arity; i++) hFile << " ret.x" << i << " = p1.x" << i << ' ' << op << " p2.x" << i << ";\n"; hFile << " return ret;\n}\n"; } /* Point op int. */ static void createPointOpI(ostream &hFile, int arity, const string digits, const char *op, const char *name) { hFile << "INLINE_MODIFIER " << P(digits) << " " << M(name, digits, MANGLE_INT_ARG(<<)) << "(" << P(digits) << " p1, " << "jint v)\n{\n"; hFile << " " << P(digits) << " ret;\n"; for (int i = 0; i < arity; i++) hFile << " ret.x" << i << " = p1.x" << i << ' ' << op << " v;\n"; hFile << " return ret;\n}\n"; } static void createPointOpPrefix(ostream &hFile, int arity, const string digits, const char *op, const char *name) { hFile << "INLINE_MODIFIER " << P(digits) << " " << M(name, digits, P(digits)) << "(" << P(digits) << " p1, " << P(digits) << " p2)\n{\n"; hFile << " " << P(digits) << " ret;\n"; for (int i = 0; i < arity; i++) hFile << " ret.x" << i << " = " << op << "(p1.x" << i << ", p2.x" << i << ");\n"; hFile << " return ret;\n}\n"; } /* ... is to createPointOpPrefix as createPointOpI is to createPointOp. */ static void createPointOpIPrefix(ostream &hFile, int arity, const string digits, const char *op, const char *name) { hFile << "INLINE_MODIFIER " << P(digits) << " " << M(name, digits, MANGLE_INT_ARG(<<)) << "(" << P(digits) << " p1, " << "jint v)\n{\n"; hFile << " " << P(digits) << " ret;\n"; for (int i = 0; i < arity; i++) hFile << " ret.x" << i << " = " << op << "(p1.x" << i << ", v);\n"; hFile << " return ret;\n}\n"; } static void createPointComparison(ostream &hFile, int arity, const string digits, const char *op, const char *name) { hFile << "INLINE_MODIFIER jboolean " << M(name, digits, P(digits)) << "(" << P(digits) << " p1, " << P(digits) << " p2)\n{\n"; hFile << " return "; for (int i = 0; i < arity; i++) { if (i) hFile << " && "; hFile << "p1.x" << i << ' ' << op << " p2.x" << i; } hFile << ";\n}\n"; } static void createPointIsNotEqual(ostream &hFile, int arity, const string digits) { hFile << "#define " << M("isNotEqual", digits, P(digits)) << "(x, y) " "(!" << M("isEqual", digits, P(digits)) << "((x), (y)))\n"; } static void createPointAll(ostream &hFile, int arity, const string digits) { hFile << "INLINE_MODIFIER " << P(digits) << " " << M("all", digits, MANGLE_INT_ARG(<<)) << "(jint x)\n{\n" << " " << P(digits) << " ret;\n" << " " << MANGLE_TI_DOMAINS_POINT_CONSTRUCT(<<, digits) << "ret"; for (int i = 0; i < arity; i++) hFile << ", x"; hFile << ");\n return ret;\n}\n"; hFile << "#define " << M("setAllThis", digits, MANGLE_INT_ARG(<<)) << " " << M("all", digits, MANGLE_INT_ARG(<<)) << "\n"; } static void createPointDirection(ostream &hFile, int arity, const string digits) { hFile << "INLINE_MODIFIER " << P(digits) << " " << M("direction", digits, MANGLE_INT_ARG(<<) << MANGLE_INT_ARG(<<)) << "(jint dir, jint val)\n{\n"; hFile << " if (dir < 0) { val = -val; dir = -dir; }\n"; hFile << " return " << M("set", digits, MANGLE_INT_ARG(<<) << MANGLE_INT_ARG(<<)) << "(" << M("all", digits, MANGLE_INT_ARG(<<)) << "(0), dir-1, val);\n}\n"; hFile << "#define " << M("direction", digits, MANGLE_INT_ARG(<<)) << "(dir) " << M("direction", digits, MANGLE_INT_ARG(<<) << MANGLE_INT_ARG(<<)) << "((dir), 1)\n"; hFile << "#define " << M("setDirection", digits, MANGLE_INT_ARG(<<)) << " " << M("direction", digits, MANGLE_INT_ARG(<<)) << "\n"; hFile << "#define " << M("setDirection", digits, MANGLE_INT_ARG(<<) << MANGLE_INT_ARG(<<)) << " " << M("direction", digits, MANGLE_INT_ARG(<<) << MANGLE_INT_ARG(<<)) << "\n"; } static void createPointArity(ostream &hFile, int arity, const string digits) { hFile << "#define " << M("arity", digits, "") << "() (" << digits << ")\n"; } static void createPointGet(ostream &hFile, int arity, const string digits) { hFile << "INLINE_MODIFIER jint " << M("get", digits, MANGLE_INT_ARG(<<)) << "(" << P(digits) << " p, jint dim)\n{\n" << " switch (dim) {\n"; for (int dimension = 0; dimension < arity; ++dimension) hFile << " case " << dimension << ": return p.x" << dimension << ";\n"; hFile << " default: \n" << " pointAssert(\"Point<" << digits << "> accessed with out of range index\", 0);\n" << " return 0;\n" << " }\n}\n" << "#define " << M("getPrevious", digits, MANGLE_INT_ARG(<<)) << "(p, x) " << M("get", digits, MANGLE_INT_ARG(<<)) << "((p), ((x) - 1))\n"; } static void createPointSetThis(ostream &hFile, int arity, const string digits) { hFile << "#define " << M("setThis", digits, MANGLE_INT_ARG(<<) << MANGLE_INT_ARG(<<)) << " " << M("set", digits, MANGLE_INT_ARG(<<) << MANGLE_INT_ARG(<<)) << "\n"; } static void createPointSet(ostream &hFile, int arity, const string digits) { hFile << "INLINE_MODIFIER " << P(digits) << ' ' << M("set", digits, MANGLE_INT_ARG(<<) << MANGLE_INT_ARG(<<)) << "(" << P(digits) << " p, jint dim, jint val)\n{\n" << " switch (dim) {\n"; for (int dimension = 0; dimension < arity; ++dimension) hFile << " case " << dimension << ": p.x" << dimension << " = val; break;\n"; hFile << " default: \n" << " pointAssert(\"Point<" << digits << "> accessed with out of range index\", 0);\n" << " }\n" << " return p;\n" << "}\n\n"; } static void createPointMaxOrMin(ostream &hFile, int arity, const string digits, const char *name, const char *op) { hFile << "INLINE_MODIFIER " << P(digits) << " " << M(name, digits, P(digits)) << "(" << P(digits) << " p1, " << P(digits) << " p2)\n{\n"; hFile << " " << P(digits) << " ret;\n"; for (int i = 0; i < arity; i++) hFile << " ret.x" << i << " = (p1.x" << i << ' ' << op << " p2.x" << i << " ? p1.x" << i << " : p2.x" << i << ");\n"; hFile << " return ret;\n}\n"; } static void createPointMaxMin(ostream &hFile, int arity, const string digits) { createPointMaxOrMin(hFile, arity, digits, "getUpperBound", ">"); createPointMaxOrMin(hFile, arity, digits, "getLowerBound", "<"); } static void createPointPermute(ostream &hFile, int arity, const string digits) { /* Permute checker */ hFile << "INLINE_MODIFIER jboolean " << M("checkPermute", digits, "") << "(" << P(digits) << " p)\n{\n"; if (arity < 31) { /* if arity is less than 31, use a bit field to do sort */ hFile << " jint bitFlags = 0;\n" << " int err = 0;\n" << " int i;\n" << " for (i = 0; (i < " << digits << ") && (!err); i++) {\n" << " jint p_i = " << M("get", digits, MANGLE_INT_ARG(<<)) << "(p, i);\n" << " if ((p_i <= 0) || (p_i > " << digits << ")) {\n" << " err = 1;\n" << " } else {\n" << " jint mask = ((jint) 1) << (p_i-1);\n" << " if (bitFlags & mask) {\n" << " err = 1;\n" << " } else {\n" << " bitFlags = bitFlags | mask;\n" << " }\n" << " }\n" << " }\n" << " return ((bitFlags == ((((jint) 1) << " << digits << ") - ((jint) 1))) && (!err));\n"; } else { /* else use an array to do O(n) sort */ hFile << " int flags[" << digits << "];\n" << " int count = 0;\n" << " int err = 0;\n" << " int i;\n" << " for (i = 0; i < " << digits << "; i++) flags[i] = 0;\n" << " for (i = 0; (i < " << digits << ") && (!err); i++) {\n" << " jint p_i = " << M("get", digits, MANGLE_INT_ARG(<<)) << "(p, i);\n" << " if ((p_i <= 0) || (p_i > " << digits << ")) {\n" << " err = 1;\n" << " } else {\n" << " if (flags[p_i-1] == 0) {\n" << " flags[p_i-1] = 1;\n" << " count++;\n" << " } else {\n" << " err = 1;\n" << " }\n" << " }\n" << " }\n" << " return ((count == " << digits << ") && (!err));\n"; } hFile << "}\n"; /* Permute routine */ hFile << "INLINE_MODIFIER " << P(digits) << " " << M("permute", digits, P(digits)) << "(" << P(digits) << " p1, " << P(digits) << " p2)\n{\n"; hFile << " " << P(digits) << " ret;\n"; hFile << "#if POINTS_BOUNDS_CHECKING\n"; hFile << " if (!" << M("checkPermute", digits, "") << "(p2)) " << "pointAssert(\"Point<" << digits << "> does not result in a valid permute operation\", 0);\n"; hFile << "#endif /* POINTS_BOUNDS_CHECKING */\n"; for (int i = 0; i < arity; i++) hFile << " ret.x" << i << " = " << M("getPrevious", digits, MANGLE_INT_ARG(<<)) << "(p1, " << M("get", digits, MANGLE_INT_ARG(<<)) << "(p2, " << i << "));\n"; hFile << " return ret;\n}\n"; } static void createUtils(ostream &hFile) { hFile << "\n\ #include \n\ \n\ #ifndef POINTS_BOUNDS_CHECKING\n\ #if BOUNDS_CHECKING\n\ #define POINTS_BOUNDS_CHECKING 1\n\ #else\n\ #define POINTS_BOUNDS_CHECKING 0\n\ #endif\n\ #endif\n\ #if POINTS_BOUNDS_CHECKING\n\ # include \n\ # define pointAssert(context, fact) assert(((context),(fact)))\n\ #else /* no bounds checking */\n\ # define pointAssert(context, fact) ((void) 0)\n\ #endif /* no bounds checking */\n\ INLINE_MODIFIER jint ti_gcd(jint a, jint b)\n\ {\n\ return (b == 0) ? a : ti_gcd(b, a % b);\n\ }\n\ INLINE_MODIFIER jint ti_lcm(jint a, jint b)\n\ {\n\ return ((a == 0) || (b == 0)) ? 0 : (a * b / ti_gcd(a, b));\n\ }\n\ INLINE_MODIFIER jint ti_div_round_to_minus_inf(jint a, jint b)\n\ {\n\ if ((a > 0) == (b > 0)) return a / b;\n\ else if (b > 0) return (a - (b - 1)) / b;\n\ else return (a - (b + 1)) / b;\n\ }\n\ "; } static void createPointToString(ostream &hFile, ostream &cFile, int arity, const string digits) { hFile << "extern " << MANGLE_LOCAL_JAVA_LANG_STRING << " " << M("toString", digits, "") << "(" << P(digits) << " var_p);\n"; cFile << "\n" << MANGLE_LOCAL_JAVA_LANG_STRING << " " << M("toString", digits, "") << "(" << P(digits) << " var_p)\n\ {\n\ return " << MANGLE_TI_DOMAINS_POINTUTILS_TOSTRING(<<, digits) << "(var_p);\n\ }\n\ "; } void createPointMethods(CfHeader &hFile, CfSource &cFile, int arity) { static bool inited = false; if (!inited) { createUtils(hFile); inited = true; } static const CtGlobal globalString( StringDecl->cType() ); static const CtGlobal globalStringBuffer( StringBufferDecl->cType() ); static const CtGlobal globalVoid( PrimitiveDecl::VoidDecl.cType() ); static const CtLocal localString( StringDecl->cType() ); static const CtLocal localStringBuffer( StringBufferDecl->cType() ); static const CtLocal localVoid( PrimitiveDecl::VoidDecl.cType() ); PointUtilsDecl->includeSelf( cFile ); StringBufferDecl->includeSelf( cFile ); StringBufferDecl->cType().define( cFile ); StringDecl->cType().define( cFile ); globalString.define( cFile ); globalStringBuffer.define( cFile ); globalVoid.define( cFile ); localString.define( cFile ); localStringBuffer.define( cFile ); localVoid.define( cFile ); (new CtPointInstance( arity ))->define( hFile ); cFile << "#include \n"; const string digits(int2string(arity)); createPointConstruct(hFile, arity, digits); createPointOp(hFile, arity, digits, "+", "add"); createPointOp(hFile, arity, digits, "-", "sub"); createPointOp(hFile, arity, digits, "*", "mul"); createPointOpPrefix(hFile, arity, digits, "ti_div_round_to_minus_inf", "div"); createPointOpI(hFile, arity, digits, "*", "mul"); createPointOpIPrefix(hFile, arity, digits, "ti_div_round_to_minus_inf", "div"); createPointOpPrefix(hFile, arity, digits, "ti_lcm", "getLcm"); createPointComparison(hFile, arity, digits, "==", "isEqual"); createPointComparison(hFile, arity, digits, ">=", "isGreaterThanEqual"); createPointComparison(hFile, arity, digits, "<=", "isLessThanEqual"); createPointComparison(hFile, arity, digits, ">", "isGreaterThan"); createPointComparison(hFile, arity, digits, "<", "isLessThan"); createPointIsNotEqual(hFile, arity, digits); createPointAll(hFile, arity, digits); createPointArity(hFile, arity, digits); createPointGet(hFile, arity, digits); createPointSetThis(hFile, arity, digits); createPointSet(hFile, arity, digits); createPointMaxMin(hFile, arity, digits); createPointPermute(hFile, arity, digits); createPointDirection(hFile, arity, digits); createPointToString(hFile, cFile, arity, digits); }