Commit 15f24443 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add pidigits benchmark and some functions to make it work

The benchmark runs but crashes due to OOM, I think because we
never release the underlying long memory (due to lack of finalizers)
parent 62f28b99
# From https://github.com/Wilfred/the_end_times
from sys import argv
try:
N = int(argv[1])
except:
N = 100
i = k = ns = 0
k1 = 1
n,a,d,t,u = (1,0,1,0,0)
while(1):
k += 1
t = n<<1
n *= k
a += t
k1 += 2
a *= k1
d *= k1
if a >= n:
t,u = divmod(n*3 +a,d)
u += n
if d > u:
ns = ns*10 + t
i += 1
if i % 10 == 0:
print ('%010d\t:%d' % (ns, i))
ns = 0
if i >= N:
break
a -= d*t
a *= 10
n *= 10
...@@ -36,9 +36,7 @@ public: ...@@ -36,9 +36,7 @@ public:
virtual ConcreteCompilerType* getTypeAtBlockStart(const std::string& name, CFGBlock* block); virtual ConcreteCompilerType* getTypeAtBlockStart(const std::string& name, CFGBlock* block);
virtual ConcreteCompilerType* getTypeAtBlockEnd(const std::string& name, CFGBlock* block); virtual ConcreteCompilerType* getTypeAtBlockEnd(const std::string& name, CFGBlock* block);
BoxedClass* speculatedExprClass(AST_expr*) override { BoxedClass* speculatedExprClass(AST_expr*) override { return NULL; }
return NULL;
}
}; };
ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockStart(const std::string& name, CFGBlock* block) { ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockStart(const std::string& name, CFGBlock* block) {
......
...@@ -38,6 +38,8 @@ llvm::StringRef getOpSymbol(int op_type) { ...@@ -38,6 +38,8 @@ llvm::StringRef getOpSymbol(int op_type) {
return "^"; return "^";
case AST_TYPE::Div: case AST_TYPE::Div:
return "/"; return "/";
case AST_TYPE::DivMod:
return "divmod()";
case AST_TYPE::Eq: case AST_TYPE::Eq:
return "=="; return "==";
case AST_TYPE::FloorDiv: case AST_TYPE::FloorDiv:
...@@ -91,10 +93,11 @@ std::string getInplaceOpSymbol(int op_type) { ...@@ -91,10 +93,11 @@ std::string getInplaceOpSymbol(int op_type) {
} }
const static std::string strAdd("__add__"), strBitAnd("__and__"), strBitOr("__or__"), strBitXor("__xor__"), const static std::string strAdd("__add__"), strBitAnd("__and__"), strBitOr("__or__"), strBitXor("__xor__"),
strDiv("__div__"), strTrueDiv("__truediv__"), strEq("__eq__"), strFloorDiv("__floordiv__"), strLShift("__lshift__"), strDiv("__div__"), strTrueDiv("__truediv__"), strDivMod("__divmod__"), strEq("__eq__"), strFloorDiv("__floordiv__"),
strLt("__lt__"), strLtE("__le__"), strGt("__gt__"), strGtE("__ge__"), strIn("__contains__"), strLShift("__lshift__"), strLt("__lt__"), strLtE("__le__"), strGt("__gt__"), strGtE("__ge__"),
strInvert("__invert__"), strMod("__mod__"), strMult("__mul__"), strNot("__nonzero__"), strNotEq("__ne__"), strIn("__contains__"), strInvert("__invert__"), strMod("__mod__"), strMult("__mul__"), strNot("__nonzero__"),
strPow("__pow__"), strRShift("__rshift__"), strSub("__sub__"), strUAdd("__pos__"), strUSub("__neg__"); strNotEq("__ne__"), strPow("__pow__"), strRShift("__rshift__"), strSub("__sub__"), strUAdd("__pos__"),
strUSub("__neg__");
const std::string& getOpName(int op_type) { const std::string& getOpName(int op_type) {
assert(op_type != AST_TYPE::Is); assert(op_type != AST_TYPE::Is);
...@@ -114,6 +117,8 @@ const std::string& getOpName(int op_type) { ...@@ -114,6 +117,8 @@ const std::string& getOpName(int op_type) {
return strTrueDiv; return strTrueDiv;
else else
return strDiv; return strDiv;
case AST_TYPE::DivMod:
return strDivMod;
case AST_TYPE::Eq: case AST_TYPE::Eq:
return strEq; return strEq;
case AST_TYPE::FloorDiv: case AST_TYPE::FloorDiv:
......
...@@ -125,6 +125,10 @@ enum AST_TYPE { ...@@ -125,6 +125,10 @@ enum AST_TYPE {
Invoke = 204, Invoke = 204,
LangPrimitive = 205, LangPrimitive = 205,
Unreachable = 206, Unreachable = 206,
// This isn't a real AST type, but since we use AST types to represent binexp types
// and divmod is essentially a type of binop, we add it here (at least for now):
DivMod = 250,
}; };
}; };
......
...@@ -535,6 +535,10 @@ Box* globals() { ...@@ -535,6 +535,10 @@ Box* globals() {
return makeAttrWrapper(m); return makeAttrWrapper(m);
} }
Box* divmod(Box* lhs, Box* rhs) {
return binopInternal(lhs, rhs, AST_TYPE::DivMod, false, NULL);
}
void setupBuiltins() { void setupBuiltins() {
builtins_module = createModule("__builtin__", "__builtin__"); builtins_module = createModule("__builtin__", "__builtin__");
...@@ -658,6 +662,8 @@ void setupBuiltins() { ...@@ -658,6 +662,8 @@ void setupBuiltins() {
builtins_module->giveAttr("iter", new BoxedFunction(boxRTFunction((void*)getiter, UNKNOWN, 1, 0, false, false))); builtins_module->giveAttr("iter", new BoxedFunction(boxRTFunction((void*)getiter, UNKNOWN, 1, 0, false, false)));
builtins_module->giveAttr("divmod", new BoxedFunction(boxRTFunction((void*)divmod, UNKNOWN, 2)));
builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2))); builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2)));
builtins_module->giveAttr("filter", new BoxedFunction(boxRTFunction((void*)filter2, LIST, 2))); builtins_module->giveAttr("filter", new BoxedFunction(boxRTFunction((void*)filter2, LIST, 2)));
builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2))); builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2)));
......
...@@ -33,13 +33,33 @@ namespace pyston { ...@@ -33,13 +33,33 @@ namespace pyston {
BoxedClass* long_cls; BoxedClass* long_cls;
static int64_t asSignedLong(BoxedLong* self) {
assert(self->cls == long_cls);
if (!mpz_fits_slong_p(self->n))
raiseExcHelper(OverflowError, "long int too large to convert to int");
return mpz_get_si(self->n);
}
static uint64_t asUnsignedLong(BoxedLong* self) {
assert(self->cls == long_cls);
// if this is ever true, we should raise a Python error, but I don't think we should hit it?
assert(mpz_cmp_si(self->n, 0) >= 0);
if (!mpz_fits_ulong_p(self->n))
raiseExcHelper(OverflowError, "long int too large to convert to int");
return mpz_get_ui(self->n);
}
extern "C" unsigned long PyLong_AsUnsignedLong(PyObject* vv) { extern "C" unsigned long PyLong_AsUnsignedLong(PyObject* vv) {
RELEASE_ASSERT(PyLong_Check(vv), ""); RELEASE_ASSERT(PyLong_Check(vv), "");
BoxedLong* l = static_cast<BoxedLong*>(vv); BoxedLong* l = static_cast<BoxedLong*>(vv);
// TODO Will this error on negative values? try {
RELEASE_ASSERT(mpz_fits_ulong_p(l->n), ""); return asUnsignedLong(l);
return mpz_get_ui(l->n); } catch (Box* e) {
abort();
}
} }
extern "C" PyObject* PyLong_FromUnsignedLong(unsigned long ival) { extern "C" PyObject* PyLong_FromUnsignedLong(unsigned long ival) {
...@@ -156,6 +176,36 @@ Box* longAdd(BoxedLong* v1, Box* _v2) { ...@@ -156,6 +176,36 @@ Box* longAdd(BoxedLong* v1, Box* _v2) {
} }
} }
Box* longLshift(BoxedLong* v1, Box* _v2) {
if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__lshift__' requires a 'long' object but received a '%s'",
getTypeName(v1)->c_str());
if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
if (mpz_cmp_si(v2->n, 0) < 0)
raiseExcHelper(ValueError, "negative shift count");
uint64_t n = asUnsignedLong(v2);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_mul_2exp(r->n, v1->n, n);
return r;
} else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
if (v2->n < 0)
raiseExcHelper(ValueError, "negative shift count");
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_mul_2exp(r->n, v1->n, v2->n);
return r;
} else {
return NotImplemented;
}
}
Box* longSub(BoxedLong* v1, Box* _v2) { Box* longSub(BoxedLong* v1, Box* _v2) {
if (!isSubclass(v1->cls, long_cls)) if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__sub__' requires a 'long' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__sub__' requires a 'long' object but received a '%s'",
...@@ -245,6 +295,40 @@ Box* longDiv(BoxedLong* v1, Box* _v2) { ...@@ -245,6 +295,40 @@ Box* longDiv(BoxedLong* v1, Box* _v2) {
} }
} }
extern "C" Box* longDivmod(BoxedLong* lhs, Box* _rhs) {
if (!isSubclass(lhs->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'",
getTypeName(lhs)->c_str());
if (isSubclass(_rhs->cls, long_cls)) {
BoxedLong* rhs = static_cast<BoxedLong*>(_rhs);
if (mpz_cmp_si(rhs->n, 0) == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* q = new BoxedLong(long_cls);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(q->n);
mpz_init(r->n);
mpz_fdiv_qr(q->n, r->n, lhs->n, rhs->n);
return new BoxedTuple({ q, r });
} else if (isSubclass(_rhs->cls, int_cls)) {
BoxedInt* rhs = static_cast<BoxedInt*>(_rhs);
if (rhs->n == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* q = new BoxedLong(long_cls);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(q->n);
mpz_init_set_si(r->n, rhs->n);
mpz_fdiv_qr(q->n, r->n, lhs->n, r->n);
return new BoxedTuple({ q, r });
} else {
return NotImplemented;
}
}
Box* longRdiv(BoxedLong* v1, Box* _v2) { Box* longRdiv(BoxedLong* v1, Box* _v2) {
if (!isSubclass(v1->cls, long_cls)) if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'",
...@@ -314,12 +398,16 @@ void setupLong() { ...@@ -314,12 +398,16 @@ void setupLong() {
long_cls->giveAttr("__div__", new BoxedFunction(boxRTFunction((void*)longDiv, UNKNOWN, 2))); long_cls->giveAttr("__div__", new BoxedFunction(boxRTFunction((void*)longDiv, UNKNOWN, 2)));
long_cls->giveAttr("__rdiv__", new BoxedFunction(boxRTFunction((void*)longRdiv, UNKNOWN, 2))); long_cls->giveAttr("__rdiv__", new BoxedFunction(boxRTFunction((void*)longRdiv, UNKNOWN, 2)));
long_cls->giveAttr("__divmod__", new BoxedFunction(boxRTFunction((void*)longDivmod, UNKNOWN, 2)));
long_cls->giveAttr("__sub__", new BoxedFunction(boxRTFunction((void*)longSub, UNKNOWN, 2))); long_cls->giveAttr("__sub__", new BoxedFunction(boxRTFunction((void*)longSub, UNKNOWN, 2)));
long_cls->giveAttr("__rsub__", new BoxedFunction(boxRTFunction((void*)longRsub, UNKNOWN, 2))); long_cls->giveAttr("__rsub__", new BoxedFunction(boxRTFunction((void*)longRsub, UNKNOWN, 2)));
long_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)longAdd, UNKNOWN, 2))); long_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)longAdd, UNKNOWN, 2)));
long_cls->giveAttr("__radd__", long_cls->getattr("__add__")); long_cls->giveAttr("__radd__", long_cls->getattr("__add__"));
long_cls->giveAttr("__lshift__", new BoxedFunction(boxRTFunction((void*)longLshift, UNKNOWN, 2)));
long_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)longRepr, STR, 1))); long_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)longRepr, STR, 1)));
long_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)longStr, STR, 1))); long_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)longStr, STR, 1)));
......
...@@ -39,3 +39,10 @@ print filter(None, xrange(-5, 5)) ...@@ -39,3 +39,10 @@ print filter(None, xrange(-5, 5))
print isinstance(1, int) print isinstance(1, int)
print isinstance(1, (float, int)) print isinstance(1, (float, int))
print isinstance(1, (float, (), (int, 3), 4)) print isinstance(1, (float, (), (int, 3), 4))
print divmod(5, 2)
print divmod(5L, -2)
try:
divmod(1, "")
except TypeError, e:
print e
...@@ -28,3 +28,14 @@ print (2L).__rdiv__(-1) ...@@ -28,3 +28,14 @@ print (2L).__rdiv__(-1)
print (2L).__rdiv__(-1L) print (2L).__rdiv__(-1L)
print (-2L).__rdiv__(1L) print (-2L).__rdiv__(1L)
print (-2L).__rdiv__(1) print (-2L).__rdiv__(1)
print (1L) << (2L)
print (1L) << (2)
try:
print (1L) << (-1L)
except ValueError, e:
print e
try:
print (1L) << (-1)
except ValueError, e:
print e
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment