Commit e912efed authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #971 from Daetalus/test_fractions

Some improvements that let test_fractions could pass.
parents 34ab5edb c7724b5c
...@@ -39,6 +39,7 @@ addons: ...@@ -39,6 +39,7 @@ addons:
- gdb - gdb
- libbz2-dev - libbz2-dev
- libgmp3-dev - libgmp3-dev
- libmpfr-dev
- liblzma-dev - liblzma-dev
- libncurses5-dev - libncurses5-dev
- libreadline-dev - libreadline-dev
......
...@@ -281,7 +281,8 @@ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/linkdeps_dummy.c COMMAND ${CMAKE_C ...@@ -281,7 +281,8 @@ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/linkdeps_dummy.c COMMAND ${CMAKE_C
add_executable(pyston $<TARGET_OBJECTS:PYSTON_MAIN_OBJECT> $<TARGET_OBJECTS:PYSTON_OBJECTS> $<TARGET_OBJECTS:FROM_CPYTHON> linkdeps_dummy.c) add_executable(pyston $<TARGET_OBJECTS:PYSTON_MAIN_OBJECT> $<TARGET_OBJECTS:PYSTON_OBJECTS> $<TARGET_OBJECTS:FROM_CPYTHON> linkdeps_dummy.c)
# Wrap the stdlib in --whole-archive to force all the symbols to be included and eventually exported # Wrap the stdlib in --whole-archive to force all the symbols to be included and eventually exported
target_link_libraries(pyston -Wl,--whole-archive stdlib -Wl,--no-whole-archive pthread m z readline sqlite3 gmp ssl crypto unwind pypa liblz4 double-conversion util ${LLVM_LIBS} ${LIBLZMA_LIBRARIES} ${OPTIONAL_LIBRARIES} ${CMAKE_BINARY_DIR}/jemalloc/lib/libjemalloc.a)
target_link_libraries(pyston -Wl,--whole-archive stdlib -Wl,--no-whole-archive pthread m z readline sqlite3 gmp mpfr ssl crypto unwind pypa liblz4 double-conversion util ${LLVM_LIBS} ${LIBLZMA_LIBRARIES} ${OPTIONAL_LIBRARIES} ${CMAKE_BINARY_DIR}/jemalloc/lib/libjemalloc.a)
add_dependencies(pyston libjemalloc) add_dependencies(pyston libjemalloc)
# copy src/codegen/parse_ast.py to the build directory # copy src/codegen/parse_ast.py to the build directory
......
...@@ -14,18 +14,18 @@ sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test ...@@ -14,18 +14,18 @@ sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
sudo add-apt-repository --yes ppa:kubuntu-ppa/backports sudo add-apt-repository --yes ppa:kubuntu-ppa/backports
sudo apt-get -qq update sudo apt-get -qq update
sudo apt-get install -yq git cmake ninja-build ccache libncurses5-dev liblzma-dev libreadline-dev libgmp3-dev autoconf libtool python-dev texlive-extra-utils clang-3.4 libstdc++-4.8-dev libssl-dev libsqlite3-dev pkg-config libbz2-dev sudo apt-get install -yq git cmake ninja-build ccache libncurses5-dev liblzma-dev libreadline-dev libgmp3-dev libmpfr-dev autoconf libtool python-dev texlive-extra-utils clang-3.4 libstdc++-4.8-dev libssl-dev libsqlite3-dev pkg-config libbz2-dev
``` ```
**Ubuntu 14.04/14.10/15.04** **Ubuntu 14.04/14.10/15.04**
``` ```
sudo apt-get install -yq git cmake ninja-build ccache libncurses5-dev liblzma-dev libreadline-dev libgmp3-dev autoconf libtool python-dev texlive-extra-utils clang libssl-dev libsqlite3-dev pkg-config libbz2-dev sudo apt-get install -yq git cmake ninja-build ccache libncurses5-dev liblzma-dev libreadline-dev libgmp3-dev libmpfr-dev autoconf libtool python-dev texlive-extra-utils clang libssl-dev libsqlite3-dev pkg-config libbz2-dev
``` ```
**Fedora 21** **Fedora 21**
``` ```
sudo yum install git make cmake clang gcc gcc-c++ ccache ninja-build xz-devel automake libtool gmp-devel readline-devel openssl-devel sqlite-devel python-devel zlib-devel bzip2-devel ncurses-devel texlive-latex2man libffi-devel sudo yum install git make cmake clang gcc gcc-c++ ccache ninja-build xz-devel automake libtool gmp-devel mpfr-devel readline-devel openssl-devel sqlite-devel python-devel zlib-devel bzip2-devel ncurses-devel texlive-latex2man libffi-devel
``` ```
### Building and testing ### Building and testing
......
# expected: fail
"""Tests for Lib/fractions.py.""" """Tests for Lib/fractions.py."""
from decimal import Decimal from decimal import Decimal
......
# expected: fail
import unittest import unittest
import sys import sys
...@@ -17,7 +16,10 @@ class Frm(object): ...@@ -17,7 +16,10 @@ class Frm(object):
return self.format % self.args return self.format % self.args
# SHIFT should match the value in longintrepr.h for best testing. # SHIFT should match the value in longintrepr.h for best testing.
SHIFT = sys.long_info.bits_per_digit SHIFT = 64
# Pyston changes: Pyston long implementation not based on digits.
# disable it for now.
# SHIFT = sys.long_info.bits_per_digit
BASE = 2 ** SHIFT BASE = 2 ** SHIFT
MASK = BASE - 1 MASK = BASE - 1
KARATSUBA_CUTOFF = 70 # from longobject.c KARATSUBA_CUTOFF = 70 # from longobject.c
......
...@@ -1281,7 +1281,9 @@ loghelper(PyObject* arg, double (*func)(double), char *funcname) ...@@ -1281,7 +1281,9 @@ loghelper(PyObject* arg, double (*func)(double), char *funcname)
Py_ssize_t e; Py_ssize_t e;
/* Negative or zero inputs give a ValueError. */ /* Negative or zero inputs give a ValueError. */
if (Py_SIZE(arg) <= 0) { // Pyston change: use _PyLong_Sign instead of Py_SIZE to check
// the sign of long object.
if (_PyLong_Sign(arg) <= 0) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"math domain error"); "math domain error");
return NULL; return NULL;
......
...@@ -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) {
......
...@@ -101,7 +101,6 @@ test_file_eintr not sure ...@@ -101,7 +101,6 @@ test_file_eintr not sure
test_fileio [unknown] test_fileio [unknown]
test_file wontfix: we don't destruct file objects when the test wants test_file wontfix: we don't destruct file objects when the test wants
test_fork1 [unknown] test_fork1 [unknown]
test_fractions [unknown]
test_frozen [unknown] test_frozen [unknown]
test_ftplib [unknown] test_ftplib [unknown]
test_funcattrs we don't allow changing numing of function defaults test_funcattrs we don't allow changing numing of function defaults
...@@ -141,7 +140,6 @@ test__locale No module named _locale ...@@ -141,7 +140,6 @@ test__locale No module named _locale
test_locale [unknown] test_locale [unknown]
test_longexp [unknown] test_longexp [unknown]
test_long_future [unknown] test_long_future [unknown]
test_long sys.long_info
test_macos Not really a failure, but it tries to skip itself and we don't support that test_macos Not really a failure, but it tries to skip itself and we don't support that
test_macostools Not really a failure, but it tries to skip itself and we don't support that test_macostools Not really a failure, but it tries to skip itself and we don't support that
test_mailbox [unknown] test_mailbox [unknown]
...@@ -187,7 +185,6 @@ test_runpy [unknown] ...@@ -187,7 +185,6 @@ test_runpy [unknown]
test_sax [unknown] test_sax [unknown]
test_scope eval of code object from existing function (not currently supported) test_scope eval of code object from existing function (not currently supported)
test_scriptpackages [unknown] test_scriptpackages [unknown]
test_set lots of set issues
test_shelve [unknown] test_shelve [unknown]
test_shlex [unknown] test_shlex [unknown]
test_signal [unknown] test_signal [unknown]
......
import sys
import os
import subprocess
me = sys.executable
file_path = os.path.dirname(__file__)
with open('/dev/null')as ignore:
def run(args):
process = subprocess.Popen([me] + args,
stdout=subprocess.PIPE,
stderr=ignore)
out, err = process.communicate()
sys.stdout.flush()
print(out)
sys.stdout.flush()
run(["".join([file_path, "/no_main_directory"])])
run(["".join([file_path, "/no_main_directory/sub_dir"])])
...@@ -146,3 +146,19 @@ print(long(unicode("-3"))) ...@@ -146,3 +146,19 @@ print(long(unicode("-3")))
print(long(x=10)) print(long(x=10))
print(long(x="10", base=10)) print(long(x="10", base=10))
try:
print(long('hek2mgl', 22))
except Exception as e:
print(e.message)
print(long('hek2mgl', 23))
print(long('hek2mgl', 24))
for i in range(-10, 10):
print(hash((-1 << 63) + i))
print(hash((1 << 63) + i))
for i in xrange(100):
for j in xrange(100):
print i, j, hash((1 << i) - (1 << j))
...@@ -9,7 +9,7 @@ add_custom_target(unittests) ...@@ -9,7 +9,7 @@ add_custom_target(unittests)
macro(add_unittest unittest) macro(add_unittest unittest)
add_executable(${unittest}_unittest EXCLUDE_FROM_ALL ${unittest}.cpp $<TARGET_OBJECTS:PYSTON_OBJECTS> $<TARGET_OBJECTS:FROM_CPYTHON>) add_executable(${unittest}_unittest EXCLUDE_FROM_ALL ${unittest}.cpp $<TARGET_OBJECTS:PYSTON_OBJECTS> $<TARGET_OBJECTS:FROM_CPYTHON>)
target_link_libraries(${unittest}_unittest stdlib z sqlite3 gmp ssl crypto readline pypa liblz4 double-conversion unwind gtest gtest_main util ${LLVM_LIBS} ${LIBLZMA_LIBRARIES}) target_link_libraries(${unittest}_unittest stdlib z sqlite3 gmp mpfr ssl crypto readline pypa liblz4 double-conversion unwind gtest gtest_main util ${LLVM_LIBS} ${LIBLZMA_LIBRARIES})
add_dependencies(unittests ${unittest}_unittest) add_dependencies(unittests ${unittest}_unittest)
endmacro() endmacro()
......
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