[pypy-commit] pypy decimal-libmpdec: More context methods, will be able to start test_decimal.
amauryfa
noreply at buildbot.pypy.org
Sun May 11 00:27:38 CEST 2014
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: decimal-libmpdec
Changeset: r71450:2ea4370d6126
Date: 2014-05-02 21:03 +0200
http://bitbucket.org/pypy/pypy/changeset/2ea4370d6126/
Log: More context methods, will be able to start test_decimal.
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -37,7 +37,7 @@
"binascii", "_multiprocessing", '_warnings', "_collections",
"_multibytecodec", "_continuation", "_cffi_backend",
"_csv", "_pypyjson", "_posixsubprocess", # "cppyy", "micronumpy"
- "faulthandler",
+ "faulthandler", "_decimal",
])
translation_modules = default_modules.copy()
diff --git a/pypy/module/_decimal/__init__.py b/pypy/module/_decimal/__init__.py
--- a/pypy/module/_decimal/__init__.py
+++ b/pypy/module/_decimal/__init__.py
@@ -12,10 +12,10 @@
'setcontext': 'interp_context.setcontext',
'IEEE_CONTEXT_MAX_BITS': 'space.wrap(interp_decimal.IEEE_CONTEXT_MAX_BITS)',
+ 'MAX_PREC': 'space.wrap(interp_decimal.MAX_PREC)',
}
for name in rmpdec.ROUND_CONSTANTS:
- interpleveldefs[name] = 'space.wrap(%r)' % (
- getattr(rmpdec, 'MPD_' + name),)
+ interpleveldefs[name] = 'space.wrap(%r)' % name
for name in ('DecimalException', 'Clamped', 'Rounded', 'Inexact',
'Subnormal', 'Underflow', 'Overflow', 'DivisionByZero',
'InvalidOperation', 'FloatOperation'):
diff --git a/pypy/module/_decimal/interp_context.py b/pypy/module/_decimal/interp_context.py
--- a/pypy/module/_decimal/interp_context.py
+++ b/pypy/module/_decimal/interp_context.py
@@ -1,7 +1,11 @@
from rpython.rlib import rmpdec
+from rpython.rlib.unroll import unrolling_iterable
+from rpython.rtyper.lltypesystem import rffi, lltype
+from pypy.interpreter.error import oefmt
from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.typedef import (TypeDef, interp_attrproperty_w)
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import (
+ TypeDef, GetSetProperty, interp_attrproperty_w)
from pypy.interpreter.executioncontext import ExecutionContext
@@ -40,16 +44,80 @@
def state_get(space):
return space.fromcache(State)
+ROUND_CONSTANTS = unrolling_iterable([
+ (name, getattr(rmpdec, 'MPD_' + name))
+ for name in rmpdec.ROUND_CONSTANTS])
class W_Context(W_Root):
def __init__(self, space):
+ self.ctx = lltype.malloc(rmpdec.MPD_CONTEXT_PTR.TO, 1, flavor='raw',
+ track_allocation=False)
self.w_flags = space.call_function(state_get(space).W_SignalDict)
+ def __del__(self):
+ if self.ctx:
+ lltype.free(self.ctx, flavor='raw')
+
def copy_w(self, space):
w_copy = W_Context(space)
# XXX incomplete
return w_copy
+ def get_prec(self, space):
+ return space.wrap(rmpdec.mpd_getprec(self.ctx))
+
+ def set_prec(self, space, w_prec):
+ prec = space.int_w(w_prec)
+ if not rmpdec.mpd_qsetprec(self.ctx, prec):
+ raise oefmt(space.w_ValueError,
+ "valid range for prec is [1, MAX_PREC]")
+
+ def get_rounding(self, space):
+ return space.wrap(rmpdec.mpd_getround(self.ctx))
+
+ def set_rounding(self, space, w_rounding):
+ rounding = space.str_w(w_rounding)
+ for name, value in ROUND_CONSTANTS:
+ if name == rounding:
+ break
+ else:
+ raise oefmt(space.w_TypeError,
+ "valid values for rounding are: "
+ "[ROUND_CEILING, ROUND_FLOOR, ROUND_UP, ROUND_DOWN,"
+ "ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,"
+ "ROUND_05UP]")
+ if not rmpdec.mpd_qsetround(self.ctx, value):
+ raise oefmt(space.w_RuntimeError,
+ "internal error in context.set_rounding")
+
+ def get_emin(self, space):
+ return space.wrap(rmpdec.mpd_getemin(self.ctx))
+
+ def set_emin(self, space, w_emin):
+ emin = space.int_w(w_emin)
+ if not rmpdec.mpd_qsetemin(self.ctx, emin):
+ raise oefmt(space.w_ValueError,
+ "valid range for Emin is [MIN_EMIN, 0]")
+
+ def get_emax(self, space):
+ return space.wrap(rmpdec.mpd_getemax(self.ctx))
+
+ def set_emax(self, space, w_emax):
+ emax = space.int_w(w_emax)
+ if not rmpdec.mpd_qsetemax(self.ctx, emax):
+ raise oefmt(space.w_ValueError,
+ "valid range for Emax is [0, MAX_EMAX]")
+
+ def get_clamp(self, space):
+ return space.wrap(rmpdec.mpd_getclamp(self.ctx))
+
+ def set_clamp(self, space, w_clamp):
+ clamp = space.c_int_w(w_clamp)
+ if not rmpdec.mpd_qsetclamp(self.ctx, clamp):
+ raise oefmt(space.w_ValueError,
+ "valid values for clamp are 0 or 1")
+
+
def descr_new_context(space, w_subtype, __args__):
w_result = space.allocate_instance(W_Context, w_subtype)
W_Context.__init__(w_result, space)
@@ -59,6 +127,11 @@
'Context',
copy=interp2app(W_Context.copy_w),
flags=interp_attrproperty_w('w_flags', W_Context),
+ prec=GetSetProperty(W_Context.get_prec, W_Context.set_prec),
+ rounding=GetSetProperty(W_Context.get_rounding, W_Context.set_rounding),
+ Emin=GetSetProperty(W_Context.get_emin, W_Context.set_emin),
+ Emax=GetSetProperty(W_Context.get_emax, W_Context.set_emax),
+ clamp=GetSetProperty(W_Context.get_clamp, W_Context.set_clamp),
__new__ = interp2app(descr_new_context),
)
diff --git a/pypy/module/_decimal/interp_decimal.py b/pypy/module/_decimal/interp_decimal.py
--- a/pypy/module/_decimal/interp_decimal.py
+++ b/pypy/module/_decimal/interp_decimal.py
@@ -5,6 +5,7 @@
IEEE_CONTEXT_MAX_BITS = rmpdec.MPD_IEEE_CONTEXT_MAX_BITS
+MAX_PREC = rmpdec.MPD_MAX_PREC
class W_Decimal(W_Root):
pass
diff --git a/pypy/module/_decimal/test/test_module.py b/pypy/module/_decimal/test/test_module.py
--- a/pypy/module/_decimal/test/test_module.py
+++ b/pypy/module/_decimal/test/test_module.py
@@ -25,6 +25,20 @@
bases = type(flags).__bases__
assert bases[1] is MutableMapping
+ def test_context_changes(self):
+ import _decimal
+ context = _decimal.getcontext()
+ context.prec
+ context.prec = 30
+ context.rounding
+ context.rounding = _decimal.ROUND_HALF_UP
+ context.Emin
+ context.Emin = -100
+ context.Emax
+ context.Emax = 100
+ context.clamp
+ context.clamp = 1
+
def test_exceptions(self):
import _decimal
for name in ('Clamped', 'Rounded', 'Inexact', 'Subnormal',
diff --git a/rpython/rlib/rmpdec.py b/rpython/rlib/rmpdec.py
--- a/rpython/rlib/rmpdec.py
+++ b/rpython/rlib/rmpdec.py
@@ -2,6 +2,7 @@
import sys
from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rtyper.lltypesystem import rffi
from rpython.rtyper.tool import rffi_platform as platform
from rpython.conftest import cdir
@@ -10,8 +11,11 @@
compile_extra = []
if sys.maxsize > 1<<32:
compile_extra.append("-DCONFIG_64")
+ # This suppose a x64 platform with gcc inline assembler.
+ compile_extra.append("-DASM")
else:
compile_extra.append("-DCONFIG_32")
+ compile_extra.append("-DANSI")
eci = ExternalCompilationInfo(
includes=['src/libmpdec/mpdecimal.h'],
@@ -30,6 +34,12 @@
libdir.join('crt.c'),
libdir.join('memory.c'),
],
+ export_symbols=[
+ "mpd_getprec", "mpd_getemin", "mpd_getemax", "mpd_getround",
+ "mpd_getclamp",
+ "mpd_qsetprec", "mpd_qsetemin", "mpd_qsetemax", "mpd_qsetround",
+ "mpd_qsetclamp",
+ ],
compile_extra=compile_extra,
libraries=['m'],
)
@@ -45,10 +55,42 @@
MPD_IEEE_CONTEXT_MAX_BITS = platform.ConstantInteger(
'MPD_IEEE_CONTEXT_MAX_BITS')
+ MPD_MAX_PREC = platform.ConstantInteger('MPD_MAX_PREC')
for name in ROUND_CONSTANTS:
name = 'MPD_' + name
locals()[name] = platform.ConstantInteger(name)
+ MPD_CONTEXT_T = platform.Struct('mpd_context_t',
+ [])
globals().update(platform.configure(CConfig))
+
+
+def external(name, args, result, **kwds):
+ return rffi.llexternal(name, args, result, compilation_info=eci, **kwds)
+
+MPD_CONTEXT_PTR = rffi.CArrayPtr(MPD_CONTEXT_T)
+
+mpd_getprec = external(
+ 'mpd_getprec', [MPD_CONTEXT_PTR], rffi.SSIZE_T)
+mpd_getemin = external(
+ 'mpd_getemin', [MPD_CONTEXT_PTR], rffi.SSIZE_T)
+mpd_getemax = external(
+ 'mpd_getemax', [MPD_CONTEXT_PTR], rffi.SSIZE_T)
+mpd_getround = external(
+ 'mpd_getround', [MPD_CONTEXT_PTR], rffi.INT)
+mpd_getclamp = external(
+ 'mpd_getclamp', [MPD_CONTEXT_PTR], rffi.INT)
+
+mpd_qsetprec = external(
+ 'mpd_qsetprec', [MPD_CONTEXT_PTR, rffi.SSIZE_T], rffi.INT)
+mpd_qsetemin = external(
+ 'mpd_qsetemin', [MPD_CONTEXT_PTR, rffi.SSIZE_T], rffi.INT)
+mpd_qsetemax = external(
+ 'mpd_qsetemax', [MPD_CONTEXT_PTR, rffi.SSIZE_T], rffi.INT)
+mpd_qsetround = external(
+ 'mpd_qsetround', [MPD_CONTEXT_PTR, rffi.INT], rffi.INT)
+mpd_qsetclamp = external(
+ 'mpd_qsetclamp', [MPD_CONTEXT_PTR, rffi.INT], rffi.INT)
+
diff --git a/rpython/translator/c/src/libmpdec/README-pypy.txt b/rpython/translator/c/src/libmpdec/README-pypy.txt
--- a/rpython/translator/c/src/libmpdec/README-pypy.txt
+++ b/rpython/translator/c/src/libmpdec/README-pypy.txt
@@ -1,3 +1,5 @@
This libmpdec directory was directly copied from CPython.
-pyconfig.h was added, with a default configuration which works on Linux.
+- pyconfig.h was added, with a default configuration which works on Linux.
+
+- in mpdecimal.h the "MPD_HIDE_SYMBOLS" pragmas have been disabled.
diff --git a/rpython/translator/c/src/libmpdec/mpdecimal.h b/rpython/translator/c/src/libmpdec/mpdecimal.h
--- a/rpython/translator/c/src/libmpdec/mpdecimal.h
+++ b/rpython/translator/c/src/libmpdec/mpdecimal.h
@@ -86,7 +86,8 @@
/* This header file is internal for the purpose of building _decimal.so.
* All symbols should have local scope in the DSO. */
-MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
+/* Removed for PyPy */
+// MPD_PRAGMA(MPD_HIDE_SYMBOLS_START)
#if !defined(LEGACY_COMPILER)
@@ -807,7 +808,8 @@
int mpd_resize_zero(mpd_t *result, mpd_ssize_t size, mpd_context_t *ctx);
-MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
+/* Removed for PyPy */
+// MPD_PRAGMA(MPD_HIDE_SYMBOLS_END) /* restore previous scope rules */
#ifdef __cplusplus
More information about the pypy-commit
mailing list