returns the "most basic" dtype which represents `x` properly, which
    provides at least the same value range as the specified dtype.
6315
def minimum_dtype(x, dtype=np.bool_):
    """"""

    def check_type(x, dtype):
        try:
            converted = dtype.type(x)
        except (ValueError, OverflowError):
            return False
        # False if some overflow has happened
        return converted == x or np.isnan(x)

    def type_loop(x, dtype, dtype_dict, default=None):
        while True:
            try:
                dtype = np.dtype(dtype_dict[dtype.name])
                if check_type(x, dtype):
                    return np.dtype(dtype)
            except KeyError:
                if default is not None:
                    return np.dtype(default)
                raise ValueError("Can not determine dtype of %r" % x)

    dtype = np.dtype(dtype)
    if check_type(x, dtype):
        return dtype

    if np.issubdtype(dtype, np.inexact):
        return type_loop(x, dtype, _next_float_dtype)
    else:
        return type_loop(x, dtype, _next_int_dtype, default=np.float32)
646043
def is_numeric_dtype(dtype):
    """"""
    dtype = np.dtype(dtype)
    return np.issubsctype(getattr(dtype, 'base', None), np.number)
170541
def _get_fill_value(dtype, fill_value=None, fill_value_typ=None):
    
    if fill_value is not None:
        return fill_value
    if _na_ok_dtype(dtype):
        if fill_value_typ is None:
            return np.nan
        else:
            if fill_value_typ == '+inf':
                return np.inf
            else:
                return -np.inf
    else:
        if fill_value_typ is None:
            return tslibs.iNaT
        else:
            if fill_value_typ == '+inf':
                # need the max int here
                return _int64_max
            else:
                return tslibs.iNaT
348202
def _str(self, i, x):
        
        FMT = {
            'a':self._fmt_auto,
            'i':self._fmt_int,
            'f':self._fmt_float,
            'e':self._fmt_exp,
            't':self._fmt_text,
            }

        n = self._precision
        dtype = self._dtype[i]
        try:
            if callable(dtype):
                return dtype(x)
            else:
                return FMT[dtype](x, n=n)
        except FallbackToText:
            return self._fmt_text(x)
185909
def _validate_dtype(self, dtype):
        

        if dtype is not None:
            dtype = pandas_dtype(dtype)

            # a compound dtype
            if dtype.kind == 'V':
                raise NotImplementedError("compound dtypes are not implemented"
                                          " in the {0} constructor"
                                          .format(self.__class__.__name__))

        return dtype
33681
def _choose_float_dtype(dtype, has_offset):
    """"""
    # Keep float32 as-is.  Upcast half-precision to single-precision,
    # because float16 is "intended for storage but not computation"
    if dtype.itemsize <= 4 and np.issubdtype(dtype, np.floating):
        return np.float32
    # float32 can exactly represent all integers up to 24 bits
    if dtype.itemsize <= 2 and np.issubdtype(dtype, np.integer):
        # A scale factor is entirely safe (vanishing into the mantissa),
        # but a large integer offset could lead to loss of precision.
        # Sensitivity analysis can be tricky, so we just use a float64
        # if there's any offset at all - better unoptimised than wrong!
        if not has_offset:
            return np.float32
    # For all other types and circumstances, we just use float64.
    # (safe because eg. complex numbers are not supported in NetCDF)
    return np.float64
954385
def get_X0(X):
    
    if pandas_available and isinstance(X, pd.DataFrame):
        assert len(X) == 1
        x = np.array(X.iloc[0])
    else:
        x, = X
    return x
429843
def _copy_with_dtype(data, dtype):
    
    result = np.empty(data.shape, dtype)
    result[...] = data
    return result
1357131
def _get_atomic_dtype(data_type):
    """"""
    atomic_type = getattr(data_type, 'type', None)
    if atomic_type is not None:
        return atomic_type

    return _PREDEFINED_ATOMIC_NUMPY_TYPES[_find_base_type(data_type)]
971906
def real_dtype(self):
        """"""
        base = self.base_dtype
        if base == complex64:
            return float32
        elif base == complex128:
            return float64
        else:
            return self
713407
def _check_2d_shape(X):
    
    if X.dtype.names is None and len(X.shape) != 2:
        raise ValueError('X needs to be 2-dimensional, not '
                         '{}-dimensional.'.format(len(X.shape)))
986549
def is_dtype_equal(self, other):
        

        try:
            return hash(self.dtype) == hash(other.dtype)
        except (AttributeError, TypeError):
            return False
557599
def data_x_range(self):
        
        try:
            lower = min([min(self._filter_none(s))
                         for type, s in self.annotated_data()
                         if type == 'x'])
            upper = max([max(self._filter_none(s))
                         for type, s in self.annotated_data()
                         if type == 'x'])
            return (lower, upper)
        except ValueError:
            return None
596840
def _coerce_to_type(x):
    
    dtype = None

    if is_datetime64tz_dtype(x):
        dtype = x.dtype
    elif is_datetime64_dtype(x):
        x = to_datetime(x)
        dtype = np.dtype('datetime64[ns]')
    elif is_timedelta64_dtype(x):
        x = to_timedelta(x)
        dtype = np.dtype('timedelta64[ns]')

    if dtype is not None:
        # GH 19768: force NaT to NaN during integer conversion
        x = np.where(x.notna(), x.view(np.int64), np.nan)

    return x, dtype
1211065
def suits_with_dtype(mn, mx, dtype):
    
    type_info = np.iinfo(dtype)
    if mx <= type_info.max and mn >= type_info.min:
        return True
    else:
        return False
1193173
def _infer_dtype(array, name=None):
    
    if array.dtype.kind != 'O':
        raise TypeError('infer_type must be called on a dtype=object array')

    if array.size == 0:
        return np.dtype(float)

    element = array[(0,) * array.ndim]
    if isinstance(element, (bytes, str)):
        return strings.create_vlen_dtype(type(element))

    dtype = np.array(element).dtype
    if dtype.kind != 'O':
        return dtype

    raise ValueError('unable to infer dtype on variable {!r}; xarray '
                     'cannot serialize arbitrary Python objects'
                     .format(name))
1339615
def _can_use_numexpr(op, op_str, a, b, dtype_check):
    
    if op_str is not None:

        # required min elements (otherwise we are adding overhead)
        if np.prod(a.shape) > _MIN_ELEMENTS:

            # check for dtype compatibility
            dtypes = set()
            for o in [a, b]:
                if hasattr(o, 'get_dtype_counts'):
                    s = o.get_dtype_counts()
                    if len(s) > 1:
                        return False
                    dtypes |= set(s.index)
                elif isinstance(o, np.ndarray):
                    dtypes |= {o.dtype.name}

            # allowed are a superset
            if not len(dtypes) or _ALLOWED_DTYPES[dtype_check] >= dtypes:
                return True

    return False