Commit e6ba3768 authored by Boxiang Sun's avatar Boxiang Sun

some improvements that let test_fractions could pass

parent 48b9a874
...@@ -1528,8 +1528,13 @@ Box* instanceLong(Box* _inst) { ...@@ -1528,8 +1528,13 @@ Box* instanceLong(Box* _inst) {
BoxedInstance* inst = static_cast<BoxedInstance*>(_inst); BoxedInstance* inst = static_cast<BoxedInstance*>(_inst);
static BoxedString* long_str = internStringImmortal("__long__"); static BoxedString* long_str = internStringImmortal("__long__");
Box* long_func = _instanceGetattribute(inst, long_str, true); if (PyObject_HasAttr((PyObject*)inst, long_str)) {
return runtimeCall(long_func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); Box* long_func = _instanceGetattribute(inst, long_str, true);
return runtimeCall(long_func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
}
Box* res = instanceInt(inst);
return res;
} }
Box* instanceFloat(Box* _inst) { Box* instanceFloat(Box* _inst) {
......
...@@ -541,6 +541,23 @@ Box* complexPow(BoxedComplex* lhs, Box* _rhs, Box* mod) { ...@@ -541,6 +541,23 @@ Box* complexPow(BoxedComplex* lhs, Box* _rhs, Box* mod) {
return boxComplex(p.real, p.imag); return boxComplex(p.real, p.imag);
} }
Box* complexRpow(BoxedComplex* _lhs, Box* _rhs) {
if (!PyComplex_Check(_lhs))
raiseExcHelper(TypeError, "descriptor '__rpow__' requires a 'complex' object but received a '%s'",
getTypeName(_lhs));
BoxedComplex* lhs = new BoxedComplex(0.0, 0.0);
if (PyInt_Check(_rhs)) {
lhs->real = (static_cast<BoxedInt*>(_rhs))->n;
} else if (_rhs->cls == float_cls) {
lhs->real = (static_cast<BoxedFloat*>(_rhs))->d;
} else if (_rhs->cls == complex_cls) {
lhs = static_cast<BoxedComplex*>(_rhs);
} else {
return NotImplemented;
}
return complexPow(lhs, _lhs, None);
}
Box* complexHash(BoxedComplex* self) { Box* complexHash(BoxedComplex* self) {
if (!PyComplex_Check(self)) if (!PyComplex_Check(self))
raiseExcHelper(TypeError, "descriptor '__hash__' requires a 'complex' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__hash__' requires a 'complex' object but received a '%s'",
...@@ -1254,6 +1271,8 @@ void setupComplex() { ...@@ -1254,6 +1271,8 @@ void setupComplex() {
complex_cls->giveAttr("__rdiv__", new BoxedFunction(FunctionMetadata::create((void*)complexRDiv, UNKNOWN, 2))); complex_cls->giveAttr("__rdiv__", new BoxedFunction(FunctionMetadata::create((void*)complexRDiv, UNKNOWN, 2)));
complex_cls->giveAttr( complex_cls->giveAttr(
"__pow__", new BoxedFunction(FunctionMetadata::create((void*)complexPow, UNKNOWN, 3, false, false), { None })); "__pow__", new BoxedFunction(FunctionMetadata::create((void*)complexPow, UNKNOWN, 3, false, false), { None }));
complex_cls->giveAttr("__rpow__", new BoxedFunction(FunctionMetadata::create((void*)complexRpow, UNKNOWN, 2)));
complex_cls->giveAttr("__mod__", new BoxedFunction(FunctionMetadata::create((void*)complexMod, UNKNOWN, 2))); complex_cls->giveAttr("__mod__", new BoxedFunction(FunctionMetadata::create((void*)complexMod, UNKNOWN, 2)));
complex_cls->giveAttr("__divmod__", complex_cls->giveAttr("__divmod__",
new BoxedFunction(FunctionMetadata::create((void*)complexDivmod, BOXED_TUPLE, 2))); new BoxedFunction(FunctionMetadata::create((void*)complexDivmod, BOXED_TUPLE, 2)));
......
...@@ -54,8 +54,13 @@ extern "C" double PyFloat_AsDouble(PyObject* o) noexcept { ...@@ -54,8 +54,13 @@ extern "C" double PyFloat_AsDouble(PyObject* o) noexcept {
if (o->cls == int_cls || o->cls == bool_cls) if (o->cls == int_cls || o->cls == bool_cls)
return (double)static_cast<BoxedInt*>(o)->n; return (double)static_cast<BoxedInt*>(o)->n;
// special case: long // special case: long
if (o->cls == long_cls) if (o->cls == long_cls) {
return mpz_get_d(static_cast<BoxedLong*>(o)->n); double result = PyLong_AsDouble(static_cast<BoxedLong*>(o));
if (result == -1.0 && PyErr_Occurred())
return -1.0;
return result;
}
// implementation from cpython: // implementation from cpython:
PyNumberMethods* nb; PyNumberMethods* nb;
...@@ -125,7 +130,11 @@ extern "C" Box* floatAdd(BoxedFloat* lhs, Box* rhs) { ...@@ -125,7 +130,11 @@ extern "C" Box* floatAdd(BoxedFloat* lhs, Box* rhs) {
} else if (rhs->cls == float_cls) { } else if (rhs->cls == float_cls) {
return floatAddFloat(lhs, static_cast<BoxedFloat*>(rhs)); return floatAddFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == long_cls) { } else if (rhs->cls == long_cls) {
return boxFloat(lhs->d + PyLong_AsDouble(rhs)); double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return boxFloat(lhs->d + rhs_f);
} else { } else {
return NotImplemented; return NotImplemented;
} }
...@@ -152,7 +161,11 @@ extern "C" Box* floatDiv(BoxedFloat* lhs, Box* rhs) { ...@@ -152,7 +161,11 @@ extern "C" Box* floatDiv(BoxedFloat* lhs, Box* rhs) {
} else if (rhs->cls == float_cls) { } else if (rhs->cls == float_cls) {
return floatDivFloat(lhs, static_cast<BoxedFloat*>(rhs)); return floatDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == long_cls) { } else if (rhs->cls == long_cls) {
return boxFloat(lhs->d / PyLong_AsDouble(rhs)); double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return boxFloat(lhs->d / rhs_f);
} else { } else {
return NotImplemented; return NotImplemented;
} }
...@@ -165,7 +178,11 @@ extern "C" Box* floatTruediv(BoxedFloat* lhs, Box* rhs) { ...@@ -165,7 +178,11 @@ extern "C" Box* floatTruediv(BoxedFloat* lhs, Box* rhs) {
} else if (rhs->cls == float_cls) { } else if (rhs->cls == float_cls) {
return floatDivFloat(lhs, static_cast<BoxedFloat*>(rhs)); return floatDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == long_cls) { } else if (rhs->cls == long_cls) {
return boxFloat(lhs->d / PyLong_AsDouble(rhs)); double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return boxFloat(lhs->d / rhs_f);
} else { } else {
return NotImplemented; return NotImplemented;
} }
...@@ -192,7 +209,11 @@ extern "C" Box* floatRDiv(BoxedFloat* lhs, Box* rhs) { ...@@ -192,7 +209,11 @@ extern "C" Box* floatRDiv(BoxedFloat* lhs, Box* rhs) {
} else if (rhs->cls == float_cls) { } else if (rhs->cls == float_cls) {
return floatRDivFloat(lhs, static_cast<BoxedFloat*>(rhs)); return floatRDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == long_cls) { } else if (rhs->cls == long_cls) {
return boxFloat(PyLong_AsDouble(rhs) / lhs->d); double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return boxFloat(rhs_f / lhs->d);
} else { } else {
return NotImplemented; return NotImplemented;
} }
...@@ -218,6 +239,33 @@ extern "C" Box* floatFloorDiv(BoxedFloat* lhs, Box* rhs) { ...@@ -218,6 +239,33 @@ extern "C" Box* floatFloorDiv(BoxedFloat* lhs, Box* rhs) {
return floatFloorDivInt(lhs, static_cast<BoxedInt*>(rhs)); return floatFloorDivInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) { } else if (rhs->cls == float_cls) {
return floatFloorDivFloat(lhs, static_cast<BoxedFloat*>(rhs)); return floatFloorDivFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == long_cls) {
double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return floatFloorDivFloat(lhs, new BoxedFloat(rhs_f));
} else {
return NotImplemented;
}
}
extern "C" Box* floatRFloorDiv(BoxedFloat* lhs, Box* _rhs) {
assert(lhs->cls == float_cls);
if (PyInt_Check(_rhs)) {
BoxedInt* rhs = (BoxedInt*)_rhs;
raiseDivZeroExcIfZero(lhs->d);
return boxFloat(floor(rhs->n / lhs->d));
} else if (_rhs->cls == float_cls) {
BoxedFloat* rhs = (BoxedFloat*)_rhs;
raiseDivZeroExcIfZero(lhs->d);
return boxFloat(floor(rhs->d / lhs->d));
} else if (_rhs->cls == long_cls) {
double rhs_f = PyLong_AsDouble(_rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return floatFloorDivFloat(new BoxedFloat(rhs_f), lhs);
} else { } else {
return NotImplemented; return NotImplemented;
} }
...@@ -544,7 +592,11 @@ extern "C" Box* floatMod(BoxedFloat* lhs, Box* rhs) { ...@@ -544,7 +592,11 @@ extern "C" Box* floatMod(BoxedFloat* lhs, Box* rhs) {
} else if (rhs->cls == float_cls) { } else if (rhs->cls == float_cls) {
return floatModFloat(lhs, static_cast<BoxedFloat*>(rhs)); return floatModFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == long_cls) { } else if (rhs->cls == long_cls) {
return boxFloat(mod_float_float(lhs->d, PyLong_AsDouble(rhs))); double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return boxFloat(mod_float_float(lhs->d, rhs_f));
} else { } else {
return NotImplemented; return NotImplemented;
} }
...@@ -569,7 +621,11 @@ extern "C" Box* floatRMod(BoxedFloat* lhs, Box* rhs) { ...@@ -569,7 +621,11 @@ extern "C" Box* floatRMod(BoxedFloat* lhs, Box* rhs) {
} else if (rhs->cls == float_cls) { } else if (rhs->cls == float_cls) {
return floatRModFloat(lhs, static_cast<BoxedFloat*>(rhs)); return floatRModFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == long_cls) { } else if (rhs->cls == long_cls) {
return boxFloat(mod_float_float(PyLong_AsDouble(rhs), lhs->d)); double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return boxFloat(mod_float_float(rhs_f, lhs->d));
} else { } else {
return NotImplemented; return NotImplemented;
} }
...@@ -626,7 +682,11 @@ extern "C" Box* floatMul(BoxedFloat* lhs, Box* rhs) { ...@@ -626,7 +682,11 @@ extern "C" Box* floatMul(BoxedFloat* lhs, Box* rhs) {
} else if (rhs->cls == float_cls) { } else if (rhs->cls == float_cls) {
return floatMulFloat(lhs, static_cast<BoxedFloat*>(rhs)); return floatMulFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == long_cls) { } else if (rhs->cls == long_cls) {
return boxFloat(lhs->d * PyLong_AsDouble(rhs)); double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return boxFloat(lhs->d * rhs_f);
} else { } else {
return NotImplemented; return NotImplemented;
} }
...@@ -651,7 +711,11 @@ extern "C" Box* floatSub(BoxedFloat* lhs, Box* rhs) { ...@@ -651,7 +711,11 @@ extern "C" Box* floatSub(BoxedFloat* lhs, Box* rhs) {
} else if (rhs->cls == float_cls) { } else if (rhs->cls == float_cls) {
return floatSubFloat(lhs, static_cast<BoxedFloat*>(rhs)); return floatSubFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == long_cls) { } else if (rhs->cls == long_cls) {
return boxFloat(lhs->d - PyLong_AsDouble(rhs)); double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return boxFloat(lhs->d - rhs_f);
} else { } else {
return NotImplemented; return NotImplemented;
} }
...@@ -676,7 +740,11 @@ extern "C" Box* floatRSub(BoxedFloat* lhs, Box* rhs) { ...@@ -676,7 +740,11 @@ extern "C" Box* floatRSub(BoxedFloat* lhs, Box* rhs) {
} else if (rhs->cls == float_cls) { } else if (rhs->cls == float_cls) {
return floatRSubFloat(lhs, static_cast<BoxedFloat*>(rhs)); return floatRSubFloat(lhs, static_cast<BoxedFloat*>(rhs));
} else if (rhs->cls == long_cls) { } else if (rhs->cls == long_cls) {
return boxFloat(PyLong_AsDouble(rhs) - lhs->d); double rhs_f = PyLong_AsDouble(rhs);
if (rhs_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return boxFloat(rhs_f - lhs->d);
} else { } else {
return NotImplemented; return NotImplemented;
} }
...@@ -782,6 +850,13 @@ template <ExceptionStyle S> static BoxedFloat* _floatNew(Box* a) noexcept(S == C ...@@ -782,6 +850,13 @@ template <ExceptionStyle S> static BoxedFloat* _floatNew(Box* a) noexcept(S == C
return static_cast<BoxedFloat*>(a); return static_cast<BoxedFloat*>(a);
} else if (PyInt_Check(a)) { } else if (PyInt_Check(a)) {
return new BoxedFloat(static_cast<BoxedInt*>(a)->n); return new BoxedFloat(static_cast<BoxedInt*>(a)->n);
} else if (PyLong_Check(a)) {
double a_f = PyLong_AsDouble(a);
if (a_f == -1.0 && PyErr_Occurred()) {
throwCAPIException();
}
return new BoxedFloat(a_f);
} else if (a->cls == str_cls || a->cls == unicode_cls) { } else if (a->cls == str_cls || a->cls == unicode_cls) {
BoxedFloat* res = (BoxedFloat*)PyFloat_FromString(a, NULL); BoxedFloat* res = (BoxedFloat*)PyFloat_FromString(a, NULL);
...@@ -1652,6 +1727,8 @@ void setupFloat() { ...@@ -1652,6 +1727,8 @@ void setupFloat() {
_addFunc("__div__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatDiv); _addFunc("__div__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatDiv);
_addFunc("__rdiv__", BOXED_FLOAT, (void*)floatRDivFloat, (void*)floatRDivInt, (void*)floatRDiv); _addFunc("__rdiv__", BOXED_FLOAT, (void*)floatRDivFloat, (void*)floatRDivInt, (void*)floatRDiv);
_addFunc("__floordiv__", BOXED_FLOAT, (void*)floatFloorDivFloat, (void*)floatFloorDivInt, (void*)floatFloorDiv); _addFunc("__floordiv__", BOXED_FLOAT, (void*)floatFloorDivFloat, (void*)floatFloorDivInt, (void*)floatFloorDiv);
float_cls->giveAttr("__rfloordiv__",
new BoxedFunction(FunctionMetadata::create((void*)floatRFloorDiv, BOXED_FLOAT, 2)));
_addFunc("__truediv__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatTruediv); _addFunc("__truediv__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatTruediv);
_addFunc("__mod__", BOXED_FLOAT, (void*)floatModFloat, (void*)floatModInt, (void*)floatMod); _addFunc("__mod__", BOXED_FLOAT, (void*)floatModFloat, (void*)floatModInt, (void*)floatMod);
......
...@@ -15,7 +15,9 @@ ...@@ -15,7 +15,9 @@
#include "runtime/long.h" #include "runtime/long.h"
#include <cmath> #include <cmath>
#include <float.h>
#include <gmp.h> #include <gmp.h>
#include <mpfr.h>
#include <sstream> #include <sstream>
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
...@@ -212,17 +214,18 @@ extern "C" PyObject* PyLong_FromString(const char* str, char** pend, int base) n ...@@ -212,17 +214,18 @@ extern "C" PyObject* PyLong_FromString(const char* str, char** pend, int base) n
BoxedLong* rtn = new BoxedLong(); BoxedLong* rtn = new BoxedLong();
int r = 0; int r = 0;
if (str[strlen(str) - 1] == 'L' || str[strlen(str) - 1] == 'l') { if ((str[strlen(str) - 1] == 'L' || str[strlen(str) - 1] == 'l') && base < 22) {
std::string without_l(str, strlen(str) - 1); std::string without_l(str, strlen(str) - 1);
r = mpz_init_set_str(rtn->n, without_l.c_str(), base); r = mpz_init_set_str(rtn->n, without_l.c_str(), base);
} else { } else {
// if base great than 22, 'l' or 'L' should count as a digit.
r = mpz_init_set_str(rtn->n, str, base); r = mpz_init_set_str(rtn->n, str, base);
} }
if (pend) if (pend)
*pend = const_cast<char*>(str) + strlen(str); *pend = const_cast<char*>(str) + strlen(str);
if (r != 0) { if (r != 0) {
PyErr_Format(PyExc_ValueError, "invalid literal for long() with base %d: %s", base, str); PyErr_Format(PyExc_ValueError, "invalid literal for long() with base %d: '%s'", base, str);
return NULL; return NULL;
} }
...@@ -347,15 +350,17 @@ extern "C" long PyLong_AsLongAndOverflow(Box* vv, int* overflow) noexcept { ...@@ -347,15 +350,17 @@ extern "C" long PyLong_AsLongAndOverflow(Box* vv, int* overflow) noexcept {
extern "C" double PyLong_AsDouble(PyObject* vv) noexcept { extern "C" double PyLong_AsDouble(PyObject* vv) noexcept {
RELEASE_ASSERT(PyLong_Check(vv), ""); RELEASE_ASSERT(PyLong_Check(vv), "");
BoxedLong* l = static_cast<BoxedLong*>(vv); BoxedLong* l = static_cast<BoxedLong*>(vv);
mpfr_t result;
mpfr_init(result);
mpfr_init_set_z(result, l->n, MPFR_RNDN);
double result = mpz_get_d(l->n); double result_f = mpfr_get_d(result, MPFR_RNDN);
if (isinf(result_f)) {
if (std::isinf(result)) {
PyErr_SetString(PyExc_OverflowError, "long int too large to convert to float"); PyErr_SetString(PyExc_OverflowError, "long int too large to convert to float");
return -1; return -1;
} }
return result; return result_f;
} }
/* Convert the long to a string object with given base, /* Convert the long to a string object with given base,
...@@ -463,7 +468,10 @@ extern "C" PyObject* PyLong_FromSize_t(size_t ival) noexcept { ...@@ -463,7 +468,10 @@ extern "C" PyObject* PyLong_FromSize_t(size_t ival) noexcept {
#undef IS_LITTLE_ENDIAN #undef IS_LITTLE_ENDIAN
extern "C" double _PyLong_Frexp(PyLongObject* a, Py_ssize_t* e) noexcept { extern "C" double _PyLong_Frexp(PyLongObject* a, Py_ssize_t* e) noexcept {
Py_FatalError("unimplemented"); BoxedLong* v = (BoxedLong*)a;
double result = mpz_get_d_2exp(e, v->n);
static_assert(sizeof(Py_ssize_t) == 8, "need to add overflow checking");
return result;
} }
/* Create a new long (or int) object from a C pointer */ /* Create a new long (or int) object from a C pointer */
...@@ -698,11 +706,11 @@ template <ExceptionStyle S> Box* _longNew(Box* val, Box* _base) noexcept(S == CA ...@@ -698,11 +706,11 @@ template <ExceptionStyle S> Box* _longNew(Box* val, Box* _base) noexcept(S == CA
if (s->size() != strlen(s->data())) { if (s->size() != strlen(s->data())) {
Box* srepr = PyObject_Repr(val); Box* srepr = PyObject_Repr(val);
if (S == CAPI) { if (S == CAPI) {
PyErr_Format(PyExc_ValueError, "invalid literal for long() with base %d: %s", base, PyErr_Format(PyExc_ValueError, "invalid literal for long() with base %d: '%s'", base,
PyString_AS_STRING(srepr)); PyString_AS_STRING(srepr));
return NULL; return NULL;
} else { } else {
raiseExcHelper(ValueError, "invalid literal for long() with base %d: %s", base, raiseExcHelper(ValueError, "invalid literal for long() with base %d: '%s'", base,
PyString_AS_STRING(srepr)); PyString_AS_STRING(srepr));
} }
} }
...@@ -780,8 +788,8 @@ Box* longFloat(BoxedLong* v) { ...@@ -780,8 +788,8 @@ Box* longFloat(BoxedLong* v) {
double result = PyLong_AsDouble(v); double result = PyLong_AsDouble(v);
if (result == -1) if (result == -1.0 && PyErr_Occurred())
checkAndThrowCAPIException(); throwCAPIException();
return new BoxedFloat(result); return new BoxedFloat(result);
} }
...@@ -1241,18 +1249,32 @@ Box* longTrueDiv(BoxedLong* v1, Box* _v2) { ...@@ -1241,18 +1249,32 @@ Box* longTrueDiv(BoxedLong* v1, Box* _v2) {
raiseExcHelper(TypeError, "descriptor '__truediv__' requires a 'long' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__truediv__' requires a 'long' object but received a '%s'",
getTypeName(v1)); getTypeName(v1));
// We only support args which fit into an int for now... BoxedLong* v2;
int overflow = 0; if (PyInt_Check(_v2) || PyLong_Check(_v2)) {
long lhs = PyLong_AsLongAndOverflow(v1, &overflow); v2 = (BoxedLong*)PyNumber_Long(_v2);
if (overflow) if (!v2) {
return NotImplemented; throwCAPIException();
long rhs = PyLong_AsLongAndOverflow(_v2, &overflow); }
if (overflow) } else {
return NotImplemented; return NotImplemented;
}
if (rhs == 0) if (mpz_sgn(v2->n) == 0) {
raiseExcHelper(ZeroDivisionError, "division by zero"); raiseExcHelper(ZeroDivisionError, "division by zero");
return boxFloat(lhs / (double)rhs); }
mpfr_t lhs_f, rhs_f, result;
mpfr_init(result);
mpfr_init_set_z(lhs_f, v1->n, MPFR_RNDN);
mpfr_init_set_z(rhs_f, v2->n, MPFR_RNDZ);
mpfr_div(result, lhs_f, rhs_f, MPFR_RNDN);
double result_f = mpfr_get_d(result, MPFR_RNDN);
if (isinf(result_f)) {
raiseExcHelper(OverflowError, "integer division result too large for a float");
}
return boxFloat(result_f);
} }
Box* longRTrueDiv(BoxedLong* v1, Box* _v2) { Box* longRTrueDiv(BoxedLong* v1, Box* _v2) {
...@@ -1260,18 +1282,27 @@ Box* longRTrueDiv(BoxedLong* v1, Box* _v2) { ...@@ -1260,18 +1282,27 @@ Box* longRTrueDiv(BoxedLong* v1, Box* _v2) {
raiseExcHelper(TypeError, "descriptor '__rtruediv__' requires a 'long' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__rtruediv__' requires a 'long' object but received a '%s'",
getTypeName(v1)); getTypeName(v1));
// We only support args which fit into an int for now... BoxedLong* v2;
int overflow = 0; if (PyInt_Check(_v2) || PyLong_Check(_v2)) {
long lhs = PyLong_AsLongAndOverflow(_v2, &overflow); v2 = (BoxedLong*)PyNumber_Long(_v2);
if (overflow) } else {
return NotImplemented;
long rhs = PyLong_AsLongAndOverflow(v1, &overflow);
if (overflow)
return NotImplemented; return NotImplemented;
}
if (rhs == 0) if (mpz_sgn(v2->n) == 0) {
raiseExcHelper(ZeroDivisionError, "division by zero"); raiseExcHelper(ZeroDivisionError, "division by zero");
return boxFloat(lhs / (double)rhs); }
mpfr_t lhs_f, rhs_f, result;
mpfr_init(result);
mpfr_init_set_z(lhs_f, v2->n, MPFR_RNDN);
mpfr_init_set_z(rhs_f, v1->n, MPFR_RNDZ);
mpfr_div(result, lhs_f, rhs_f, MPFR_RNDN);
double result_f = mpfr_get_d(result, MPFR_RNDZ);
if (isinf(result_f)) {
raiseExcHelper(OverflowError, "integer division result too large for a float");
}
return boxFloat(result_f);
} }
static void _addFuncPow(const char* name, ConcreteCompilerType* rtn_type, void* float_func, void* long_func) { static void _addFuncPow(const char* name, ConcreteCompilerType* rtn_type, void* float_func, void* long_func) {
...@@ -1393,14 +1424,17 @@ Box* longHash(BoxedLong* self) { ...@@ -1393,14 +1424,17 @@ Box* longHash(BoxedLong* self) {
if (mpz_fits_slong_p(self->n)) if (mpz_fits_slong_p(self->n))
return boxInt(mpz_get_si(self->n)); return boxInt(mpz_get_si(self->n));
// Not sure if this is a good hash function or not; // CPython use the absolute value of self mod ULONG_MAX.
// simple, but only includes top bits: unsigned long remainder = mpz_tdiv_ui(self->n, ULONG_MAX);
union { if (remainder == 0)
uint64_t n; remainder = -1; // CPython compatibility -- ULONG_MAX mod ULONG_MAX is ULONG_MAX to them.
double d;
}; remainder *= mpz_sgn(self->n);
d = mpz_get_d(self->n);
return boxInt(n); if (remainder == -1)
remainder = -2;
return boxInt(remainder);
} }
extern "C" Box* longTrunc(BoxedLong* self) { extern "C" Box* longTrunc(BoxedLong* self) {
......
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