diff --git a/src/sage/env.py b/src/sage/env.py
index c83b8b98b7a..d711eae6b42 100644
--- a/src/sage/env.py
+++ b/src/sage/env.py
@@ -258,8 +258,9 @@ SINGULAR_BIN = var("SINGULAR_BIN") or "Singular"
 OPENMP_CFLAGS = var("OPENMP_CFLAGS", "")
 OPENMP_CXXFLAGS = var("OPENMP_CXXFLAGS", "")
 
-# Make sure mpmath uses Sage types
-os.environ['MPMATH_SAGE'] = '1'
+# Make sure that mpmath < 1.4 does not try to use Sage types
+os.environ.pop('MPMATH_SAGE', None)
+os.environ['MPMATH_NOSAGE'] = '1'
 
 # misc
 SAGE_BANNER = var("SAGE_BANNER", "")
diff --git a/src/sage/functions/exp_integral.py b/src/sage/functions/exp_integral.py
index e074c430808..09d2bbda71b 100644
--- a/src/sage/functions/exp_integral.py
+++ b/src/sage/functions/exp_integral.py
@@ -993,7 +993,7 @@ class Function_cos_integral(BuiltinFunction):
             sage: N(cos_integral(10^-10), digits=30)                                    # needs sage.symbolic
             -22.4486352650389239795759024568
             sage: cos_integral(ComplexField(100)(I))                                    # needs sage.symbolic
-            0.83786694098020824089467857943 + 1.5707963267948966192313216916*I
+            0.83786694098020824089467857944 + 1.5707963267948966192313216916*I
         """
         return _mpmath_utils_call(_mpmath_ci, z, parent=parent)
 
diff --git a/src/sage/libs/mpmath/meson.build b/src/sage/libs/mpmath/meson.build
index a197516f9f1..feb3708524a 100644
--- a/src/sage/libs/mpmath/meson.build
+++ b/src/sage/libs/mpmath/meson.build
@@ -1,16 +1,11 @@
 py.install_sources(
   '__init__.py',
   'all.py',
-  'ext_impl.pxd',
-  'ext_main.pxd',
   'utils.pxd',
   subdir: 'sage/libs/mpmath',
 )
 
 extension_data = {
-  'ext_impl' : files('ext_impl.pyx'),
-  'ext_libmp' : files('ext_libmp.pyx'),
-  'ext_main' : files('ext_main.pyx'),
   'utils' : files('utils.pyx'),
 }
 
@@ -21,7 +16,7 @@ foreach name, pyx : extension_data
     subdir: 'sage/libs/mpmath',
     install: true,
     include_directories: [inc_cpython, inc_ext, inc_rings],
-    dependencies: [py_dep, cysignals, gmp, mpfr],
+    dependencies: [py_dep, cysignals, gmp, gmpy2, mpfr],
   )
 endforeach
 
diff --git a/src/sage/libs/mpmath/utils.pyx b/src/sage/libs/mpmath/utils.pyx
index 1acf14ea540..fd4a29c7d15 100644
--- a/src/sage/libs/mpmath/utils.pyx
+++ b/src/sage/libs/mpmath/utils.pyx
@@ -1,9 +1,9 @@
 """
 Utilities for Sage-mpmath interaction
-
-Also patches some mpmath functions for speed
 """
 
+cimport gmpy2
+
 from sage.ext.stdsage cimport PY_NEW
 
 from sage.rings.integer cimport Integer
@@ -16,145 +16,7 @@ from sage.libs.gmp.all cimport *
 
 from sage.rings.real_mpfr cimport RealField
 
-cpdef int bitcount(n) noexcept:
-    """
-    Bitcount of a Sage Integer or Python int/long.
-
-    EXAMPLES::
-
-        sage: from mpmath.libmp import bitcount
-        sage: bitcount(0)
-        0
-        sage: bitcount(1)
-        1
-        sage: bitcount(100)
-        7
-        sage: bitcount(-100)
-        7
-        sage: bitcount(2r)
-        2
-        sage: bitcount(2L)
-        2
-    """
-    cdef Integer m
-    if isinstance(n, Integer):
-        m = <Integer>n
-    else:
-        m = Integer(n)
-    if mpz_sgn(m.value) == 0:
-        return 0
-    return mpz_sizeinbase(m.value, 2)
-
-cpdef isqrt(n):
-    """
-    Square root (rounded to floor) of a Sage Integer or Python int/long.
-    The result is a Sage Integer.
-
-    EXAMPLES::
-
-        sage: from mpmath.libmp import isqrt
-        sage: isqrt(0)
-        0
-        sage: isqrt(100)
-        10
-        sage: isqrt(10)
-        3
-        sage: isqrt(10r)
-        3
-        sage: isqrt(10L)
-        3
-    """
-    cdef Integer m, y
-    if isinstance(n, Integer):
-        m = <Integer>n
-    else:
-        m = Integer(n)
-    if mpz_sgn(m.value) < 0:
-        raise ValueError("square root of negative integer not defined.")
-    y = PY_NEW(Integer)
-    mpz_sqrt(y.value, m.value)
-    return y
-
-cpdef from_man_exp(man, exp, long prec=0, str rnd='d'):
-    """
-    Create normalized mpf value tuple from mantissa and exponent.
-
-    With prec > 0, rounds the result in the desired direction
-    if necessary.
-
-    EXAMPLES::
-
-        sage: from mpmath.libmp import from_man_exp
-        sage: from_man_exp(-6, -1)
-        (1, 3, 0, 2)
-        sage: from_man_exp(-6, -1, 1, 'd')
-        (1, 1, 1, 1)
-        sage: from_man_exp(-6, -1, 1, 'u')
-        (1, 1, 2, 1)
-    """
-    cdef Integer res
-    cdef long bc
-    res = Integer(man)
-    bc = mpz_sizeinbase(res.value, 2)
-    if not prec:
-        prec = bc
-    if mpz_sgn(res.value) < 0:
-        mpz_neg(res.value, res.value)
-        return normalize(1, res, exp, bc, prec, rnd)
-    else:
-        return normalize(0, res, exp, bc, prec, rnd)
-
-cpdef normalize(long sign, Integer man, exp, long bc, long prec, str rnd):
-    """
-    Create normalized mpf value tuple from full list of components.
-
-    EXAMPLES::
-
-        sage: from mpmath.libmp import normalize
-        sage: normalize(0, 4, 5, 3, 53, 'n')
-        (0, 1, 7, 1)
-    """
-    cdef long shift
-    cdef Integer res
-    cdef unsigned long trail
-    if mpz_sgn(man.value) == 0:
-        from mpmath.libmp import fzero
-        return fzero
-    if bc <= prec and mpz_odd_p(man.value):
-        return (sign, man, exp, bc)
-    shift = bc - prec
-    res = PY_NEW(Integer)
-    if shift > 0:
-        if rnd == 'n':
-            if mpz_tstbit(man.value, shift-1) and (mpz_tstbit(man.value, shift)
-                or (mpz_scan1(man.value, 0) < (shift-1))):
-                mpz_cdiv_q_2exp(res.value, man.value, shift)
-            else:
-                mpz_fdiv_q_2exp(res.value, man.value, shift)
-        elif rnd == 'd':
-            mpz_fdiv_q_2exp(res.value, man.value, shift)
-        elif rnd == 'f':
-            if sign:
-                mpz_cdiv_q_2exp(res.value, man.value, shift)
-            else:
-                mpz_fdiv_q_2exp(res.value, man.value, shift)
-        elif rnd == 'c':
-            if sign:
-                mpz_fdiv_q_2exp(res.value, man.value, shift)
-            else:
-                mpz_cdiv_q_2exp(res.value, man.value, shift)
-        elif rnd == 'u':
-            mpz_cdiv_q_2exp(res.value, man.value, shift)
-        exp += shift
-    else:
-        mpz_set(res.value, man.value)
-    # Strip trailing bits
-    trail = mpz_scan1(res.value, 0)
-    if 0 < trail < bc:
-        mpz_tdiv_q_2exp(res.value, res.value, trail)
-        exp += trail
-    bc = mpz_sizeinbase(res.value, 2)
-    return (sign, res, int(exp), bc)
+gmpy2.import_gmpy2()
 
 cdef mpfr_from_mpfval(mpfr_t res, tuple x):
     """
@@ -162,11 +24,11 @@ cdef mpfr_from_mpfval(mpfr_t res, tuple x):
     data tuple.
     """
     cdef int sign
-    cdef Integer man
     cdef long exp
+    cdef gmpy2.mpz man
     sign, man, exp, _ = x
     if man:
-        mpfr_set_z(res, man.value, MPFR_RNDZ)
+        mpfr_set_z(res, man.z, MPFR_RNDZ)
         if sign:
             mpfr_neg(res, res, MPFR_RNDZ)
         mpfr_mul_2si(res, res, exp, MPFR_RNDZ)
@@ -210,7 +72,7 @@ cdef mpfr_to_mpfval(mpfr_t value):
         mpz_tdiv_q_2exp(man.value, man.value, trailing)
         exp += trailing
     bc = mpz_sizeinbase(man.value, 2)
-    return (sign, man, int(exp), bc)
+    return (sign, man.__mpz__(), int(exp), bc)
 
 
 def mpmath_to_sage(x, prec):
@@ -305,7 +167,7 @@ def sage_to_mpmath(x, prec):
         sage: print(a.sage_to_mpmath(1+pi, 53))
         4.14159265358979
         sage: a.sage_to_mpmath(infinity, 53)
-        mpf('+inf')
+        mpf('inf')
         sage: a.sage_to_mpmath(-infinity, 53)
         mpf('-inf')
         sage: a.sage_to_mpmath(NaN, 53)
@@ -414,7 +276,7 @@ def call(func, *args, **kwargs):
     Check that :issue:`11885` is fixed::
 
         sage: a.call(a.ei, 1.0r, parent=float)
-        1.8951178163559366
+        1.8951178163559368
 
     Check that :issue:`14984` is fixed::
 
diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx
index 9fc1bedea8f..1c915ebb3d2 100644
--- a/src/sage/rings/real_mpfr.pyx
+++ b/src/sage/rings/real_mpfr.pyx
@@ -150,8 +150,6 @@ from sage.structure.richcmp cimport rich_to_bool_sgn
 cdef bin_op
 from sage.structure.element import bin_op
 
-from sage.libs.mpmath.utils cimport mpfr_to_mpfval
-
 from sage.rings.integer cimport Integer
 from sage.rings.rational cimport Rational
 from sage.rings.real_double cimport RealDoubleElement
diff --git a/src/sage/structure/coerce.pyx b/src/sage/structure/coerce.pyx
index a2fbaac2042..5e9c2383299 100644
--- a/src/sage/structure/coerce.pyx
+++ b/src/sage/structure/coerce.pyx
@@ -144,6 +144,13 @@ cpdef py_scalar_parent(py_type):
         Real Double Field
         sage: py_scalar_parent(gmpy2.mpc)                                               # needs sage.rings.complex_double
         Complex Double Field
+
+        sage: # needs mpmath
+        sage: import mpmath
+        sage: py_scalar_parent(mpmath.mpf)
+        Real Double Field
+        sage: py_scalar_parent(mpmath.mpc)                                              # needs sage.rings.complex_double
+        Complex Double Field
     """
     if issubclass(py_type, int):
         import sage.rings.integer_ring
@@ -151,39 +158,46 @@ cpdef py_scalar_parent(py_type):
     if py_type is FractionType:
         import sage.rings.rational_field
         return sage.rings.rational_field.QQ
-    elif issubclass(py_type, float):
+    if issubclass(py_type, float):
         import sage.rings.real_double
         return sage.rings.real_double.RDF
-    elif issubclass(py_type, complex):
+    if issubclass(py_type, complex):
         import sage.rings.complex_double
         return sage.rings.complex_double.CDF
-    elif is_numpy_type(py_type):
+    if is_numpy_type(py_type):
         import numpy
         if issubclass(py_type, numpy.integer):
             import sage.rings.integer_ring
             return sage.rings.integer_ring.ZZ
-        elif issubclass(py_type, numpy.floating):
+        if issubclass(py_type, numpy.floating):
             import sage.rings.real_double
             return sage.rings.real_double.RDF
-        elif issubclass(py_type, numpy.complexfloating):
+        if issubclass(py_type, numpy.complexfloating):
             import sage.rings.complex_double
             return sage.rings.complex_double.CDF
-        else:
-            return None
-    elif issubclass(py_type, gmpy2.mpz):
+        return None
+    if issubclass(py_type, gmpy2.mpz):
         import sage.rings.integer_ring
         return sage.rings.integer_ring.ZZ
-    elif issubclass(py_type, gmpy2.mpq):
+    if issubclass(py_type, gmpy2.mpq):
         import sage.rings.rational_field
         return sage.rings.rational_field.QQ
-    elif issubclass(py_type, gmpy2.mpfr):
+    if issubclass(py_type, gmpy2.mpfr):
         import sage.rings.real_double
         return sage.rings.real_double.RDF
-    elif issubclass(py_type, gmpy2.mpc):
+    if issubclass(py_type, gmpy2.mpc):
         import sage.rings.complex_double
         return sage.rings.complex_double.CDF
-    else:
+    if is_mpmath_type(py_type):
+        import mpmath
+        if issubclass(py_type, mpmath.mpf):
+            from sage.rings.real_double import RDF
+            return RDF
+        if issubclass(py_type, mpmath.mpc):
+            from sage.rings.complex_double import CDF
+            return CDF
         return None
+    return None
 
 cpdef py_scalar_to_element(x):
     """
@@ -469,10 +483,10 @@ cpdef bint is_numpy_type(t) noexcept:
         return True
     return False
 
+
 cpdef bint is_mpmath_type(t) noexcept:
     r"""
-    Check whether the type ``t`` is a type whose name starts with either
-    ``mpmath.`` or ``sage.libs.mpmath.``.
+    Check whether the type ``t`` is a type whose name starts with ``mpmath.``
 
     EXAMPLES::
 
@@ -489,7 +503,7 @@ cpdef bint is_mpmath_type(t) noexcept:
         True
     """
     return isinstance(t, type) and \
-           strncmp((<PyTypeObject*>t).tp_name, "sage.libs.mpmath.", 17) == 0
+           t.__module__.startswith("mpmath.")
 
 
 cdef class CoercionModel:
diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/integration_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/integration_doctest.py
index f8b5ca511b2..30959f2919f 100644
--- a/src/sage/tests/books/computational-mathematics-with-sagemath/integration_doctest.py
+++ b/src/sage/tests/books/computational-mathematics-with-sagemath/integration_doctest.py
@@ -151,7 +151,7 @@ Sage example in ./integration.tex, line 846::
   sage: mpmath.quad(f, [0, 1])
   Traceback (most recent call last):
   ...
-  TypeError: no canonical coercion from <class 'sage.libs.mpmath.ext_main.mpf'> to ...
+  TypeError: no canonical coercion from <class '...mpf'> to ...
 
 Sage example in ./integration.tex, line 866::
 
