@@ -2011,6 +2011,100 @@ get_round_mode(PyObject *rndstr)
20112011 return rnd ;
20122012}
20132013
2014+ static zz_err
2015+ zz_mpmath_normalize (zz_bitcnt_t prec , zz_rnd rnd , bool * negative ,
2016+ zz_t * man , zz_t * exp , zz_bitcnt_t * bc )
2017+ {
2018+ /* If the mantissa is 0, return the normalized representation. */
2019+ if (zz_iszero (man )) {
2020+ * negative = false;
2021+ * bc = 0 ;
2022+ return zz_from_i32 (0 , exp );
2023+ }
2024+ /* if size <= prec and the number is odd return it */
2025+ if (* bc <= prec && zz_isodd (man )) {
2026+ return ZZ_OK ;
2027+ }
2028+ if (* bc > prec ) {
2029+ zz_bitcnt_t shift = * bc - prec ;
2030+
2031+ do_rnd :
2032+ switch (rnd ) {
2033+ case ZZ_RNDD :
2034+ rnd = * negative ? ZZ_RNDA : ZZ_RNDZ ;
2035+ goto do_rnd ;
2036+ case ZZ_RNDU :
2037+ rnd = * negative ? ZZ_RNDZ : ZZ_RNDA ;
2038+ goto do_rnd ;
2039+ case ZZ_RNDZ :
2040+ zz_quo_2exp (man , shift , man );
2041+ break ;
2042+ case ZZ_RNDA :
2043+ zz_neg (man , man );
2044+ zz_quo_2exp (man , shift , man );
2045+ zz_abs (man , man );
2046+ break ;
2047+ case ZZ_RNDN :
2048+ default :
2049+ {
2050+ bool t = zz_lsbpos (man ) + 2 <= shift ;
2051+
2052+ if (zz_quo_2exp (man , shift - 1 , man )) {
2053+ return ZZ_MEM ; /* LCOV_EXCL_LINE */
2054+ }
2055+ t = zz_isodd (man ) && (man -> digits [0 ]& 2 || t );
2056+ if (zz_quo_2exp (man , 1 , man )) {
2057+ return ZZ_MEM ; /* LCOV_EXCL_LINE */
2058+ }
2059+ if (t && zz_add_i32 (man , 1 , man )) {
2060+ return ZZ_MEM ; /* LCOV_EXCL_LINE */
2061+ }
2062+ }
2063+ }
2064+
2065+ zz_t tmp ;
2066+
2067+ if (zz_init (& tmp ) || shift > INT64_MAX
2068+ || zz_from_i64 ((int64_t )shift , & tmp )
2069+ || zz_add (exp , & tmp , exp ))
2070+ {
2071+ /* LCOV_EXCL_START */
2072+ zz_clear (& tmp );
2073+ return ZZ_MEM ;
2074+ /* LCOV_EXCL_STOP */
2075+ }
2076+ zz_clear (& tmp );
2077+ * bc = prec ;
2078+ }
2079+
2080+ zz_bitcnt_t zbits = 0 ;
2081+
2082+ /* Strip trailing 0 bits. */
2083+ if (!zz_iszero (man ) && (zbits = zz_lsbpos (man ))) {
2084+ if (zz_quo_2exp (man , zbits , man )) {
2085+ return ZZ_MEM ; /* LCOV_EXCL_LINE */
2086+ }
2087+ }
2088+
2089+ zz_t tmp ;
2090+
2091+ if (zz_init (& tmp ) || zbits > INT64_MAX
2092+ || zz_from_i64 ((int64_t )zbits , & tmp )
2093+ || zz_add (exp , & tmp , exp ))
2094+ {
2095+ /* LCOV_EXCL_START */
2096+ zz_clear (& tmp );
2097+ return ZZ_MEM ;
2098+ /* LCOV_EXCL_STOP */
2099+ }
2100+ zz_clear (& tmp );
2101+ * bc -= zbits ;
2102+ /* Check if one less than a power of 2 was rounded up. */
2103+ if (zz_cmp_i32 (man , 1 ) == ZZ_EQ ) {
2104+ * bc = 1 ;
2105+ }
2106+ return ZZ_OK ;
2107+ }
20142108static PyObject *
20152109gmp__mpmath_normalize (PyObject * self , PyObject * const * args , Py_ssize_t nargs )
20162110{
@@ -2041,8 +2135,8 @@ gmp__mpmath_normalize(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
20412135 MPZ_Object * man = (MPZ_Object * )plus (args [1 ]);
20422136 MPZ_Object * exp = MPZ_from_int (args [2 ]);
20432137
2044- if (!exp || !man || _zz_mpmath_normalize (prec , rnd , & negative ,
2045- & man -> z , & exp -> z , & bc ))
2138+ if (!exp || !man || zz_mpmath_normalize (prec , rnd , & negative ,
2139+ & man -> z , & exp -> z , & bc ))
20462140 {
20472141 /* LCOV_EXCL_START */
20482142 Py_XDECREF (man );
@@ -2124,8 +2218,8 @@ gmp__mpmath_create(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
21242218
21252219 MPZ_Object * exp = MPZ_from_int (args [1 ]);
21262220
2127- if (!exp || _zz_mpmath_normalize (prec , rnd , & negative ,
2128- & man -> z , & exp -> z , & bc ))
2221+ if (!exp || zz_mpmath_normalize (prec , rnd , & negative ,
2222+ & man -> z , & exp -> z , & bc ))
21292223 {
21302224 /* LCOV_EXCL_START */
21312225 Py_DECREF (man );
0 commit comments