code: def type_info(np_type):
      """Return dict with min, max, nexp, nmant, width for numpy type `np_type`
  
      Type can be integer in which case nexp and nmant are None.
  
      Parameters
      ----------
      np_type : numpy type specifier
          Any specifier for a numpy dtype
  
      Returns
      -------
      info : dict
          with fields ``min`` (minimum value), ``max`` (maximum value), ``nexp``
          (exponent width), ``nmant`` (significand precision not including
          implicit first digit), ``minexp`` (minimum exponent), ``maxexp``
          (maximum exponent), ``width`` (width in bytes). (``nexp``, ``nmant``,
          ``minexp``, ``maxexp``) are None for integer types. Both ``min`` and
          ``max`` are of type `np_type`.
  
      Raises
      ------
      FloatingError
          for floating point types we don't recognize
  
      Notes
      -----
      You might be thinking that ``np.finfo`` does this job, and it does, except
      for PPC long doubles (https://github.com/numpy/numpy/issues/2669) and
      float96 on Windows compiled with Mingw. This routine protects against such
      errors in ``np.finfo`` by only accepting values that we know are likely to
      be correct.
      """
      dt = np.dtype(np_type)
      np_type = dt.type
      width = dt.itemsize
      try:  # integer type
          info = np.iinfo(dt)
      except ValueError:
          pass
      else:
          return dict(
              min=np_type(info.min),
              max=np_type(info.max),
              minexp=None,
              maxexp=None,
              nmant=None,
              nexp=None,
              width=width,
          )
      info = np.finfo(dt)
      # Trust the standard IEEE types
      nmant, nexp = info.nmant, info.nexp
      ret = dict(
          min=np_type(info.min),
          max=np_type(info.max),
          nmant=nmant,
          nexp=nexp,
          minexp=info.minexp,
          maxexp=info.maxexp,
          width=width,
      )
      if np_type in (
          np.float16,
          np.float32,
          np.float64,
          np.complex64,
          np.complex128,
      ):
          return ret
      info_64 = np.finfo(np.float64)
      if dt.kind == "c":
          assert np_type is np.clongdouble
          vals = (nmant, nexp, width / 2)
      else:
          assert np_type is np.longdouble
          vals = (nmant, nexp, width)
      if vals in (
          (112, 15, 16),  # binary128
          (info_64.nmant, info_64.nexp, 8),  # float64
          (63, 15, 12),  # Intel extended 80
          (63, 15, 16),  # Intel extended 80
      ):
          return ret  # these are OK without modification
      # The remaining types are longdoubles with bad finfo values.  Some we
      # correct, others we wait to hear of errors.
      # We start with float64 as basis
      ret = type_info(np.float64)
      if vals in (
          (52, 15, 12),
          (52, 15, 16),
      ):  # windows float96 / windows float128?
          # On windows 32 bit at least, float96 is Intel 80 storage but operating
          # at float64 precision. The finfo values give nexp == 15 (as for intel
          # 80) but in calculations nexp in fact appears to be 11 as for float64
          ret.update(dict(width=width))
          return ret
      if vals == (105, 11, 16):  # correctly detected double double
          ret.update(dict(nmant=nmant, nexp=nexp, width=width))
          return ret
      # Oh dear, we don't recognize the type information.  Try some known types
      # and then give up. At this stage we're expecting exotic longdouble or
      # their complex equivalent.
      if np_type not in (
          np.longdouble,
          np.clongdouble,
      ) or width not in (16, 32):
          raise FloatingError(f"We had not expected type {np_type}")
      if (
          vals == (1, 1, 16)
          and on_powerpc()
          and _check_maxexp(np.longdouble, 1024)
      ):
          # double pair on PPC.  The _check_nmant routine does not work for this
          # type, hence the powerpc platform check instead
          ret.update(dict(nmant=106, width=width))
      elif _check_nmant(np.longdouble, 52) and _check_maxexp(
          np.longdouble, 11
      ):
          # Got float64 despite everything
          pass
      elif _check_nmant(np.longdouble, 112) and _check_maxexp(
          np.longdouble, 16384
      ):
          # binary 128, but with some busted type information. np.clongdouble
          # seems to break here too, so we need to use np.longdouble and
          # complexify
          two = np.longdouble(2)
          # See: https://matthew-brett.github.io/pydagogue/floating_point.html
          max_val = (two**113 - 1) / (two**112) * two**16383
          if np_type is np.clongdouble:
              max_val += 0j
          ret = dict(
              min=-max_val,
              max=max_val,
              nmant=112,
              nexp=15,
              minexp=-16382,
              maxexp=16384,
              width=width,
          )
      else:  # don't recognize the type
          raise FloatingError(
              f"We had not expected long double type {np_type} with info {info}"
          )
      return ret
  
imports: from __future__ import annotations
  import warnings
  from platform import machine, processor
  import numpy
  from .deprecated import deprecate_with_version
label_desc: Use image node_id 4 for calling a global function with example usage: type_info(np_type) and returns: ret, dict, ret, ret, ret, ret