[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