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:
virtual ConcreteCompilerType* getTypeAtBlockStart(const std::string& name, CFGBlock* block);
virtual ConcreteCompilerType* getTypeAtBlockEnd(const std::string& name, CFGBlock* block);
BoxedClass* speculatedExprClass(AST_expr*) override {
return NULL;
}
BoxedClass* speculatedExprClass(AST_expr*) override { return NULL; }
};
ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockStart(const std::string& name, CFGBlock* block) {
......
......@@ -38,6 +38,8 @@ llvm::StringRef getOpSymbol(int op_type) {
return "^";
case AST_TYPE::Div:
return "/";
case AST_TYPE::DivMod:
return "divmod()";
case AST_TYPE::Eq:
return "==";
case AST_TYPE::FloorDiv:
......@@ -91,10 +93,11 @@ std::string getInplaceOpSymbol(int op_type) {
}
const static std::string strAdd("__add__"), strBitAnd("__and__"), strBitOr("__or__"), strBitXor("__xor__"),
strDiv("__div__"), strTrueDiv("__truediv__"), strEq("__eq__"), strFloorDiv("__floordiv__"), strLShift("__lshift__"),
strLt("__lt__"), strLtE("__le__"), strGt("__gt__"), strGtE("__ge__"), strIn("__contains__"),
strInvert("__invert__"), strMod("__mod__"), strMult("__mul__"), strNot("__nonzero__"), strNotEq("__ne__"),
strPow("__pow__"), strRShift("__rshift__"), strSub("__sub__"), strUAdd("__pos__"), strUSub("__neg__");
strDiv("__div__"), strTrueDiv("__truediv__"), strDivMod("__divmod__"), strEq("__eq__"), strFloorDiv("__floordiv__"),
strLShift("__lshift__"), strLt("__lt__"), strLtE("__le__"), strGt("__gt__"), strGtE("__ge__"),
strIn("__contains__"), strInvert("__invert__"), strMod("__mod__"), strMult("__mul__"), strNot("__nonzero__"),
strNotEq("__ne__"), strPow("__pow__"), strRShift("__rshift__"), strSub("__sub__"), strUAdd("__pos__"),
strUSub("__neg__");
const std::string& getOpName(int op_type) {
assert(op_type != AST_TYPE::Is);
......@@ -114,6 +117,8 @@ const std::string& getOpName(int op_type) {
return strTrueDiv;
else
return strDiv;
case AST_TYPE::DivMod:
return strDivMod;
case AST_TYPE::Eq:
return strEq;
case AST_TYPE::FloorDiv:
......
......@@ -125,6 +125,10 @@ enum AST_TYPE {
Invoke = 204,
LangPrimitive = 205,
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() {
return makeAttrWrapper(m);
}
Box* divmod(Box* lhs, Box* rhs) {
return binopInternal(lhs, rhs, AST_TYPE::DivMod, false, NULL);
}
void setupBuiltins() {
builtins_module = createModule("__builtin__", "__builtin__");
......@@ -658,6 +662,8 @@ void setupBuiltins() {
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("filter", new BoxedFunction(boxRTFunction((void*)filter2, LIST, 2)));
builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2)));
......
......@@ -33,13 +33,33 @@ namespace pyston {
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) {
RELEASE_ASSERT(PyLong_Check(vv), "");
BoxedLong* l = static_cast<BoxedLong*>(vv);
// TODO Will this error on negative values?
RELEASE_ASSERT(mpz_fits_ulong_p(l->n), "");
return mpz_get_ui(l->n);
try {
return asUnsignedLong(l);
} catch (Box* e) {
abort();
}
}
extern "C" PyObject* PyLong_FromUnsignedLong(unsigned long ival) {
......@@ -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) {
if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__sub__' requires a 'long' object but received a '%s'",
......@@ -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) {
if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'",
......@@ -314,12 +398,16 @@ void setupLong() {
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("__divmod__", new BoxedFunction(boxRTFunction((void*)longDivmod, 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("__add__", new BoxedFunction(boxRTFunction((void*)longAdd, UNKNOWN, 2)));
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("__str__", new BoxedFunction(boxRTFunction((void*)longStr, STR, 1)));
......
......@@ -39,3 +39,10 @@ print filter(None, xrange(-5, 5))
print isinstance(1, int)
print isinstance(1, (float, int))
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)
print (2L).__rdiv__(-1L)
print (-2L).__rdiv__(1L)
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