Commits

mattip committed db399f9

add more stubbed functions, copy and modify numerictypes

  • Participants
  • Parent commits 6cf873d
  • Branches python-numpy

Comments (0)

Files changed (3)

File lib_pypy/numpypy/__init__.py

 
 import _numpypy as umath
 import multiarray
-import numerictypes
 sys.modules['numpy.core.multiarray'] = multiarray
 sys.modules['numpy.core.umath'] = umath
 
+import numerictypes
 sys.modules['numerictypes'] = numerictypes
 sys.modules['numpy.core.numerictypes'] = numerictypes
 

File lib_pypy/numpypy/multiarray/__init__.py

 def datetime_as_string(*args, **kwargs):
     raise ValueError('not implemented yet')
 
+def busday_offset(dates, offsets, roll='raise', weekmask='1111100', holidays=None, busdaycal=None, out=None):
+    raise ValueError('not implemented yet')
+
+def busday_count(begindates, enddates, weekmask='1111100', holidays=[], busdaycal=None, out=None):
+    raise ValueError('not implemented yet')
+
+def is_busday(dates, weekmask='1111100', holidays=None, busdaycal=None, out=None):
+    raise ValueError('not implemented yet')
+
+def busdaycalendar(weekmask='1111100', holidays=None):
+    raise ValueError('not implemented yet')
+
+
+

File lib_pypy/numpypy/numerictypes.py

-sctypeDict = {}
-
-def sctype2char(sctype):
-    raise ValueError('not implemented yet')
-
-complex_ = None
+"""
+numerictypes: Define the numeric type objects
+
+This module is designed so "from numerictypes import \\*" is safe.
+Exported symbols include:
+
+  Dictionary with all registered number types (including aliases):
+    typeDict
+
+  Type objects (not all will be available, depends on platform):
+      see variable sctypes for which ones you have
+
+    Bit-width names
+
+    int8 int16 int32 int64 int128
+    uint8 uint16 uint32 uint64 uint128
+    float16 float32 float64 float96 float128 float256
+    complex32 complex64 complex128 complex192 complex256 complex512
+    datetime64 timedelta64
+
+    c-based names
+
+    bool_
+
+    object_
+
+    void, str_, unicode_
+
+    byte, ubyte,
+    short, ushort
+    intc, uintc,
+    intp, uintp,
+    int_, uint,
+    longlong, ulonglong,
+
+    single, csingle,
+    float_, complex_,
+    longfloat, clongfloat,
+
+   As part of the type-hierarchy:    xx -- is bit-width
+
+   generic
+     +-> bool_                                  (kind=b)
+     +-> number                                 (kind=i)
+     |     integer
+     |     signedinteger   (intxx)
+     |     byte
+     |     short
+     |     intc
+     |     intp           int0
+     |     int_
+     |     longlong
+     +-> unsignedinteger  (uintxx)              (kind=u)
+     |     ubyte
+     |     ushort
+     |     uintc
+     |     uintp          uint0
+     |     uint_
+     |     ulonglong
+     +-> inexact
+     |   +-> floating           (floatxx)       (kind=f)
+     |   |     half
+     |   |     single
+     |   |     float_  (double)
+     |   |     longfloat
+     |   \\-> complexfloating    (complexxx)     (kind=c)
+     |         csingle  (singlecomplex)
+     |         complex_ (cfloat, cdouble)
+     |         clongfloat (longcomplex)
+     +-> flexible
+     |     character
+     |     void                                 (kind=V)
+     |
+     |     str_     (string_, bytes_)           (kind=S)    [Python 2]
+     |     unicode_                             (kind=U)    [Python 2]
+     |
+     |     bytes_   (string_)                   (kind=S)    [Python 3]
+     |     str_     (unicode_)                  (kind=U)    [Python 3]
+     |
+     \\-> object_ (not used much)                (kind=O)
+
+"""
+
+# we add more at the bottom
+__all__ = ['sctypeDict', 'sctypeNA', 'typeDict', 'typeNA', 'sctypes',
+           'ScalarType', 'obj2sctype', 'cast', 'nbytes', 'sctype2char',
+           'maximum_sctype', 'issctype', 'typecodes', 'find_common_type',
+           'issubdtype', 'datetime_data','datetime_as_string',
+           'busday_offset', 'busday_count', 'is_busday', 'busdaycalendar',
+           ]
+
+#from numpy.core.multiarray import typeinfo, ndarray, array, \
+from multiarray import typeinfo, ndarray, array, \
+                      empty, dtype, datetime_data, datetime_as_string, \
+                      busday_offset, busday_count, is_busday, busdaycalendar
+import types as _types
+import sys
+
+# we don't export these for import *, but we do want them accessible
+# as numerictypes.bool, etc.
+from __builtin__ import bool, int, long, float, complex, object, unicode, str
+from numpy.compat import bytes
+
+if sys.version_info[0] >= 3:
+    # Py3K
+    class long(int):
+        # Placeholder class -- this will not escape outside numerictypes.py
+        pass
+
+# String-handling utilities to avoid locale-dependence.
+
+# "import string" is costly to import!
+# Construct the translation tables directly
+#   "A" = chr(65), "a" = chr(97)
+_all_chars = map(chr, range(256))
+_ascii_upper = _all_chars[65:65+26]
+_ascii_lower = _all_chars[97:97+26]
+LOWER_TABLE="".join(_all_chars[:65] + _ascii_lower + _all_chars[65+26:])
+UPPER_TABLE="".join(_all_chars[:97] + _ascii_upper + _all_chars[97+26:])
+
+#import string
+# assert (string.maketrans(string.ascii_uppercase, string.ascii_lowercase) == \
+#          LOWER_TABLE)
+# assert (string.maketrnas(string_ascii_lowercase, string.ascii_uppercase) == \
+#          UPPER_TABLE)
+#LOWER_TABLE = string.maketrans(string.ascii_uppercase, string.ascii_lowercase)
+#UPPER_TABLE = string.maketrans(string.ascii_lowercase, string.ascii_uppercase)
+
+def english_lower(s):
+    """ Apply English case rules to convert ASCII strings to all lower case.
+
+    This is an internal utility function to replace calls to str.lower() such
+    that we can avoid changing behavior with changing locales. In particular,
+    Turkish has distinct dotted and dotless variants of the Latin letter "I" in
+    both lowercase and uppercase. Thus, "I".lower() != "i" in a "tr" locale.
+
+    Parameters
+    ----------
+    s : str
+
+    Returns
+    -------
+    lowered : str
+
+    Examples
+    --------
+    >>> from numpy.core.numerictypes import english_lower
+    >>> english_lower('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_')
+    'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789_'
+    >>> english_lower('')
+    ''
+    """
+    lowered = s.translate(LOWER_TABLE)
+    return lowered
+
+def english_upper(s):
+    """ Apply English case rules to convert ASCII strings to all upper case.
+
+    This is an internal utility function to replace calls to str.upper() such
+    that we can avoid changing behavior with changing locales. In particular,
+    Turkish has distinct dotted and dotless variants of the Latin letter "I" in
+    both lowercase and uppercase. Thus, "i".upper() != "I" in a "tr" locale.
+
+    Parameters
+    ----------
+    s : str
+
+    Returns
+    -------
+    uppered : str
+
+    Examples
+    --------
+    >>> from numpy.core.numerictypes import english_upper
+    >>> english_upper('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_')
+    'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
+    >>> english_upper('')
+    ''
+    """
+    uppered = s.translate(UPPER_TABLE)
+    return uppered
+
+def english_capitalize(s):
+    """ Apply English case rules to convert the first character of an ASCII
+    string to upper case.
+
+    This is an internal utility function to replace calls to str.capitalize()
+    such that we can avoid changing behavior with changing locales.
+
+    Parameters
+    ----------
+    s : str
+
+    Returns
+    -------
+    capitalized : str
+
+    Examples
+    --------
+    >>> from numpy.core.numerictypes import english_capitalize
+    >>> english_capitalize('int8')
+    'Int8'
+    >>> english_capitalize('Int8')
+    'Int8'
+    >>> english_capitalize('')
+    ''
+    """
+    if s:
+        return english_upper(s[0]) + s[1:]
+    else:
+        return s
+
+
+sctypeDict = {}      # Contains all leaf-node scalar types with aliases
+sctypeNA = {}        # Contails all leaf-node types -> numarray type equivalences
+allTypes = {}      # Collect the types we will add to the module here
+
+def _evalname(name):
+    k = 0
+    for ch in name:
+        if ch in '0123456789':
+            break
+        k += 1
+    try:
+        bits = int(name[k:])
+    except ValueError:
+        bits = 0
+    base = name[:k]
+    return base, bits
+
+def bitname(obj):
+    """Return a bit-width name for a given type object"""
+    name = obj.__name__
+    base = ''
+    char = ''
+    try:
+        if name[-1] == '_':
+            newname = name[:-1]
+        else:
+            newname = name
+        info = typeinfo[english_upper(newname)]
+        assert(info[-1] == obj)  # sanity check
+        bits = info[2]
+
+    except KeyError:     # bit-width name
+        base, bits = _evalname(name)
+        char = base[0]
+
+    if name == 'bool_':
+        char = 'b'
+        base = 'bool'
+    elif name=='void':
+        char = 'V'
+        base = 'void'
+    elif name=='object_':
+        char = 'O'
+        base = 'object'
+        bits = 0
+    elif name=='datetime64':
+        char = 'M'
+    elif name=='timedelta64':
+        char = 'm'
+
+    if sys.version_info[0] >= 3:
+        if name=='bytes_':
+            char = 'S'
+            base = 'bytes'
+        elif name=='str_':
+            char = 'U'
+            base = 'str'
+    else:
+        if name=='string_':
+            char = 'S'
+            base = 'string'
+        elif name=='unicode_':
+            char = 'U'
+            base = 'unicode'
+
+    bytes = bits // 8
+
+    if char != '' and bytes != 0:
+        char = "%s%d" % (char, bytes)
+
+    return base, bits, char
+
+
+def _add_types():
+    for a in typeinfo.keys():
+        name = english_lower(a)
+        if isinstance(typeinfo[a], tuple):
+            typeobj = typeinfo[a][-1]
+
+            # define C-name and insert typenum and typechar references also
+            allTypes[name] = typeobj
+            sctypeDict[name] = typeobj
+            sctypeDict[typeinfo[a][0]] = typeobj
+            sctypeDict[typeinfo[a][1]] = typeobj
+
+        else:  # generic class
+            allTypes[name] = typeinfo[a]
+_add_types()
+
+def _add_aliases():
+    for a in typeinfo.keys():
+        name = english_lower(a)
+        if not isinstance(typeinfo[a], tuple):
+            continue
+        typeobj = typeinfo[a][-1]
+        # insert bit-width version for this class (if relevant)
+        base, bit, char = bitname(typeobj)
+        if base[-3:] == 'int' or char[0] in 'ui': continue
+        if base != '':
+            myname = "%s%d" % (base, bit)
+            if (name != 'longdouble' and name != 'clongdouble') or \
+                   myname not in allTypes.keys():
+                allTypes[myname] = typeobj
+                sctypeDict[myname] = typeobj
+                if base == 'complex':
+                    na_name = '%s%d' % (english_capitalize(base), bit//2)
+                elif base == 'bool':
+                    na_name = english_capitalize(base)
+                    sctypeDict[na_name] = typeobj
+                else:
+                    na_name = "%s%d" % (english_capitalize(base), bit)
+                    sctypeDict[na_name] = typeobj
+                sctypeNA[na_name] = typeobj
+                sctypeDict[na_name] = typeobj
+                sctypeNA[typeobj] = na_name
+                sctypeNA[typeinfo[a][0]] = na_name
+        if char != '':
+            sctypeDict[char] = typeobj
+            sctypeNA[char] = na_name
+_add_aliases()
+
+# Integers handled so that
+# The int32, int64 types should agree exactly with
+#  PyArray_INT32, PyArray_INT64 in C
+# We need to enforce the same checking as is done
+#  in arrayobject.h where the order of getting a
+#  bit-width match is:
+#       long, longlong, int, short, char
+#   for int8, int16, int32, int64, int128
+
+def _add_integer_aliases():
+    _ctypes = ['LONG', 'LONGLONG', 'INT', 'SHORT', 'BYTE']
+    for ctype in _ctypes:
+        val = typeinfo[ctype]
+        bits = val[2]
+        charname = 'i%d' % (bits//8,)
+        ucharname = 'u%d' % (bits//8,)
+        intname = 'int%d' % bits
+        UIntname = 'UInt%d' % bits
+        Intname = 'Int%d' % bits
+        uval = typeinfo['U'+ctype]
+        typeobj = val[-1]
+        utypeobj = uval[-1]
+        if intname not in allTypes.keys():
+            uintname = 'uint%d' % bits
+            allTypes[intname] = typeobj
+            allTypes[uintname] = utypeobj
+            sctypeDict[intname] = typeobj
+            sctypeDict[uintname] = utypeobj
+            sctypeDict[Intname] = typeobj
+            sctypeDict[UIntname] = utypeobj
+            sctypeDict[charname] = typeobj
+            sctypeDict[ucharname] = utypeobj
+            sctypeNA[Intname] = typeobj
+            sctypeNA[UIntname] = utypeobj
+            sctypeNA[charname] = typeobj
+            sctypeNA[ucharname] = utypeobj
+        sctypeNA[typeobj] = Intname
+        sctypeNA[utypeobj] = UIntname
+        sctypeNA[val[0]] = Intname
+        sctypeNA[uval[0]] = UIntname
+_add_integer_aliases()
+
+# We use these later
+void = allTypes['void']
+generic = allTypes['generic']
+
+#
+# Rework the Python names (so that float and complex and int are consistent
+#                            with Python usage)
+#
+def _set_up_aliases():
+    type_pairs = [('complex_', 'cdouble'),
+                  ('int0', 'intp'),
+                  ('uint0', 'uintp'),
+                  ('single', 'float'),
+                  ('csingle', 'cfloat'),
+                  ('singlecomplex', 'cfloat'),
+                  ('float_', 'double'),
+                  ('intc', 'int'),
+                  ('uintc', 'uint'),
+                  ('int_', 'long'),
+                  ('uint', 'ulong'),
+                  ('cfloat', 'cdouble'),
+                  ('longfloat', 'longdouble'),
+                  ('clongfloat', 'clongdouble'),
+                  ('longcomplex', 'clongdouble'),
+                  ('bool_', 'bool'),
+                  ('unicode_', 'unicode'),
+                  ('object_', 'object')]
+    if sys.version_info[0] >= 3:
+        type_pairs.extend([('bytes_', 'string'),
+                           ('str_', 'unicode'),
+                           ('string_', 'string')])
+    else:
+        type_pairs.extend([('str_', 'string'),
+                           ('string_', 'string'),
+                           ('bytes_', 'string')])
+    for alias, t in type_pairs:
+        try:
+            allTypes[alias] = allTypes[t]
+            sctypeDict[alias] = sctypeDict[t]
+        except KeyError:
+            print 'dtype',t,'not implemented in numpypy, will be missing in numerictypes.sctypeDict'
+    # Remove aliases overriding python types and modules
+    to_remove = ['ulong', 'object', 'unicode', 'int', 'long', 'float',
+                 'complex', 'bool', 'string', 'datetime', 'timedelta']
+    if sys.version_info[0] >= 3:
+        # Py3K
+        to_remove.append('bytes')
+        to_remove.append('str')
+        to_remove.remove('unicode')
+        to_remove.remove('long')
+    for t in to_remove:
+        try:
+            del allTypes[t]
+            del sctypeDict[t]
+        except KeyError:
+            pass
+_set_up_aliases()
+
+# Now, construct dictionary to lookup character codes from types
+_sctype2char_dict = {}
+def _construct_char_code_lookup():
+    for name in typeinfo.keys():
+        tup = typeinfo[name]
+        if isinstance(tup, tuple):
+            if tup[0] not in ['p','P']:
+                _sctype2char_dict[tup[-1]] = tup[0]
+_construct_char_code_lookup()
+
+
+sctypes = {'int': [],
+           'uint':[],
+           'float':[],
+           'complex':[],
+           'others':[bool,object,str,unicode,void]}
+
+def _add_array_type(typename, bits):
+    try:
+        t = allTypes['%s%d' % (typename, bits)]
+    except KeyError:
+        pass
+    else:
+        sctypes[typename].append(t)
+
+def _set_array_types():
+    ibytes = [1, 2, 4, 8, 16, 32, 64]
+    fbytes = [2, 4, 8, 10, 12, 16, 32, 64]
+    for bytes in ibytes:
+        bits = 8*bytes
+        _add_array_type('int', bits)
+        _add_array_type('uint', bits)
+    for bytes in fbytes:
+        bits = 8*bytes
+        _add_array_type('float', bits)
+        _add_array_type('complex', 2*bits)
+    try:
+        _gi = dtype('p')
+    except:
+        print "dtype('p') not implemented yet"
+    else:
+        if _gi.type not in sctypes['int']:
+            indx = 0
+            sz = _gi.itemsize
+            _lst = sctypes['int']
+            while (indx < len(_lst) and sz >= _lst[indx](0).itemsize):
+                indx += 1
+            sctypes['int'].insert(indx, _gi.type)
+            sctypes['uint'].insert(indx, dtype('P').type)
+_set_array_types()
+
+
+genericTypeRank = ['bool', 'int8', 'uint8', 'int16', 'uint16',
+                   'int32', 'uint32', 'int64', 'uint64', 'int128',
+                   'uint128', 'float16',
+                   'float32', 'float64', 'float80', 'float96', 'float128',
+                   'float256',
+                   'complex32', 'complex64', 'complex128', 'complex160',
+                   'complex192', 'complex256', 'complex512', 'object']
+
+def maximum_sctype(t):
+    """
+    Return the scalar type of highest precision of the same kind as the input.
+
+    Parameters
+    ----------
+    t : dtype or dtype specifier
+        The input data type. This can be a `dtype` object or an object that
+        is convertible to a `dtype`.
+
+    Returns
+    -------
+    out : dtype
+        The highest precision data type of the same kind (`dtype.kind`) as `t`.
+
+    See Also
+    --------
+    obj2sctype, mintypecode, sctype2char
+    dtype
+
+    Examples
+    --------
+    >>> np.maximum_sctype(np.int)
+    <type 'numpy.int64'>
+    >>> np.maximum_sctype(np.uint8)
+    <type 'numpy.uint64'>
+    >>> np.maximum_sctype(np.complex)
+    <type 'numpy.complex192'>
+
+    >>> np.maximum_sctype(str)
+    <type 'numpy.string_'>
+
+    >>> np.maximum_sctype('i2')
+    <type 'numpy.int64'>
+    >>> np.maximum_sctype('f4')
+    <type 'numpy.float96'>
+
+    """
+    g = obj2sctype(t)
+    if g is None:
+        return t
+    t = g
+    name = t.__name__
+    base, bits = _evalname(name)
+    if bits == 0:
+        return t
+    else:
+        return sctypes[base][-1]
+
+try:
+    buffer_type = _types.BufferType
+except AttributeError:
+    # Py3K
+    buffer_type = memoryview
+
+_python_types = {int : 'int_',
+                 float: 'float_',
+                 complex: 'complex_',
+                 bool: 'bool_',
+                 bytes: 'bytes_',
+                 unicode: 'unicode_',
+                 buffer_type: 'void',
+                }
+
+if sys.version_info[0] >= 3:
+    def _python_type(t):
+        """returns the type corresponding to a certain Python type"""
+        if not isinstance(t, type):
+            t = type(t)
+        return allTypes[_python_types.get(t, 'object_')]
+else:
+    def _python_type(t):
+        """returns the type corresponding to a certain Python type"""
+        if not isinstance(t, _types.TypeType):
+            t = type(t)
+        return allTypes[_python_types.get(t, 'object_')]
+
+def issctype(rep):
+    """
+    Determines whether the given object represents a scalar data-type.
+
+    Parameters
+    ----------
+    rep : any
+        If `rep` is an instance of a scalar dtype, True is returned. If not,
+        False is returned.
+
+    Returns
+    -------
+    out : bool
+        Boolean result of check whether `rep` is a scalar dtype.
+
+    See Also
+    --------
+    issubsctype, issubdtype, obj2sctype, sctype2char
+
+    Examples
+    --------
+    >>> np.issctype(np.int32)
+    True
+    >>> np.issctype(list)
+    False
+    >>> np.issctype(1.1)
+    False
+
+    Strings are also a scalar type:
+
+    >>> np.issctype(np.dtype('str'))
+    True
+
+    """
+    if not isinstance(rep, (type, dtype)):
+        return False
+    try:
+        res = obj2sctype(rep)
+        if res and res != object_:
+            return True
+        return False
+    except:
+        return False
+
+def obj2sctype(rep, default=None):
+    """
+    Return the scalar dtype or NumPy equivalent of Python type of an object.
+
+    Parameters
+    ----------
+    rep : any
+        The object of which the type is returned.
+    default : any, optional
+        If given, this is returned for objects whose types can not be
+        determined. If not given, None is returned for those objects.
+
+    Returns
+    -------
+    dtype : dtype or Python type
+        The data type of `rep`.
+
+    See Also
+    --------
+    sctype2char, issctype, issubsctype, issubdtype, maximum_sctype
+
+    Examples
+    --------
+    >>> np.obj2sctype(np.int32)
+    <type 'numpy.int32'>
+    >>> np.obj2sctype(np.array([1., 2.]))
+    <type 'numpy.float64'>
+    >>> np.obj2sctype(np.array([1.j]))
+    <type 'numpy.complex128'>
+
+    >>> np.obj2sctype(dict)
+    <type 'numpy.object_'>
+    >>> np.obj2sctype('string')
+    <type 'numpy.string_'>
+
+    >>> np.obj2sctype(1, default=list)
+    <type 'list'>
+
+    """
+    try:
+        if issubclass(rep, generic):
+            return rep
+    except TypeError:
+        pass
+    if isinstance(rep, dtype):
+        return rep.type
+    if isinstance(rep, type):
+        return _python_type(rep)
+    if isinstance(rep, ndarray):
+        return rep.dtype.type
+    try:
+        res = dtype(rep)
+    except:
+        return default
+    return res.type
+
+
+def issubclass_(arg1, arg2):
+    """
+    Determine if a class is a subclass of a second class.
+
+    `issubclass_` is equivalent to the Python built-in ``issubclass``,
+    except that it returns False instead of raising a TypeError is one
+    of the arguments is not a class.
+
+    Parameters
+    ----------
+    arg1 : class
+        Input class. True is returned if `arg1` is a subclass of `arg2`.
+    arg2 : class or tuple of classes.
+        Input class. If a tuple of classes, True is returned if `arg1` is a
+        subclass of any of the tuple elements.
+
+    Returns
+    -------
+    out : bool
+        Whether `arg1` is a subclass of `arg2` or not.
+
+    See Also
+    --------
+    issubsctype, issubdtype, issctype
+
+    Examples
+    --------
+    >>> np.issubclass_(np.int32, np.int)
+    True
+    >>> np.issubclass_(np.int32, np.float)
+    False
+
+    """
+    try:
+        return issubclass(arg1, arg2)
+    except TypeError:
+        return False
+
+def issubsctype(arg1, arg2):
+    """
+    Determine if the first argument is a subclass of the second argument.
+
+    Parameters
+    ----------
+    arg1, arg2 : dtype or dtype specifier
+        Data-types.
+
+    Returns
+    -------
+    out : bool
+        The result.
+
+    See Also
+    --------
+    issctype, issubdtype,obj2sctype
+
+    Examples
+    --------
+    >>> np.issubsctype('S8', str)
+    True
+    >>> np.issubsctype(np.array([1]), np.int)
+    True
+    >>> np.issubsctype(np.array([1]), np.float)
+    False
+
+    """
+    return issubclass(obj2sctype(arg1), obj2sctype(arg2))
+
+def issubdtype(arg1, arg2):
+    """
+    Returns True if first argument is a typecode lower/equal in type hierarchy.
+
+    Parameters
+    ----------
+    arg1, arg2 : dtype_like
+        dtype or string representing a typecode.
+
+    Returns
+    -------
+    out : bool
+
+    See Also
+    --------
+    issubsctype, issubclass_
+    numpy.core.numerictypes : Overview of numpy type hierarchy.
+
+    Examples
+    --------
+    >>> np.issubdtype('S1', str)
+    True
+    >>> np.issubdtype(np.float64, np.float32)
+    False
+
+    """
+    if issubclass_(arg2, generic):
+        return issubclass(dtype(arg1).type, arg2)
+    mro = dtype(arg2).type.mro()
+    if len(mro) > 1:
+        val = mro[1]
+    else:
+        val = mro[0]
+    return issubclass(dtype(arg1).type, val)
+
+
+# This dictionary allows look up based on any alias for an array data-type
+class _typedict(dict):
+    """
+    Base object for a dictionary for look-up with any alias for an array dtype.
+
+    Instances of `_typedict` can not be used as dictionaries directly,
+    first they have to be populated.
+
+    """
+    def __getitem__(self, obj):
+        return dict.__getitem__(self, obj2sctype(obj))
+
+nbytes = _typedict()
+_alignment = _typedict()
+_maxvals = _typedict()
+_minvals = _typedict()
+def _construct_lookups():
+    for name, val in typeinfo.iteritems():
+        if not isinstance(val, tuple):
+            continue
+        obj = val[-1]
+        nbytes[obj] = val[2] // 8
+        _alignment[obj] = val[3]
+        if (len(val) > 5):
+            _maxvals[obj] = val[4]
+            _minvals[obj] = val[5]
+        else:
+            _maxvals[obj] = None
+            _minvals[obj] = None
+
+_construct_lookups()
+
+def sctype2char(sctype):
+    """
+    Return the string representation of a scalar dtype.
+
+    Parameters
+    ----------
+    sctype : scalar dtype or object
+        If a scalar dtype, the corresponding string character is
+        returned. If an object, `sctype2char` tries to infer its scalar type
+        and then return the corresponding string character.
+
+    Returns
+    -------
+    typechar : str
+        The string character corresponding to the scalar type.
+
+    Raises
+    ------
+    ValueError
+        If `sctype` is an object for which the type can not be inferred.
+
+    See Also
+    --------
+    obj2sctype, issctype, issubsctype, mintypecode
+
+    Examples
+    --------
+    >>> for sctype in [np.int32, np.float, np.complex, np.string_, np.ndarray]:
+    ...     print np.sctype2char(sctype)
+    l
+    d
+    D
+    S
+    O
+
+    >>> x = np.array([1., 2-1.j])
+    >>> np.sctype2char(x)
+    'D'
+    >>> np.sctype2char(list)
+    'O'
+
+    """
+    sctype = obj2sctype(sctype)
+    if sctype is None:
+        raise ValueError("unrecognized type")
+    return _sctype2char_dict[sctype]
+
+# Create dictionary of casting functions that wrap sequences
+# indexed by type or type character
+
+
+cast = _typedict()
+try:
+    ScalarType = [_types.IntType, _types.FloatType, _types.ComplexType,
+                  _types.LongType, _types.BooleanType,
+                   _types.StringType, _types.UnicodeType, _types.BufferType]
+except AttributeError:
+    # Py3K
+    ScalarType = [int, float, complex, long, bool, bytes, str, memoryview]
+
+ScalarType.extend(_sctype2char_dict.keys())
+ScalarType = tuple(ScalarType)
+for key in _sctype2char_dict.keys():
+    cast[key] = lambda x, k=key : array(x, copy=False).astype(k)
+
+# Create the typestring lookup dictionary
+_typestr = _typedict()
+for key in _sctype2char_dict.keys():
+    if issubclass(key, allTypes['flexible']):
+        _typestr[key] = _sctype2char_dict[key]
+    else:
+        #_typestr[key] = empty((1,),key).dtype.str[1:]
+        dt = empty((1,),key).dtype
+        _typestr[key] = dt.kind + '%d'%dt.itemsize
+
+# Make sure all typestrings are in sctypeDict
+for key, val in _typestr.items():
+    if val not in sctypeDict:
+        sctypeDict[val] = key
+
+# Add additional strings to the sctypeDict
+
+if sys.version_info[0] >= 3:
+    _toadd = ['int', 'float', 'complex', 'bool', 'object',
+              'str', 'bytes', 'object', ('a', allTypes['bytes_'])]
+else:
+    _toadd = ['int', 'float', 'complex', 'bool', 'object', 'string',
+              ('str', allTypes['string_']),
+              'unicode', 'object', ('a', allTypes['string_'])]
+
+for name in _toadd:
+    if isinstance(name, tuple):
+        sctypeDict[name[0]] = name[1]
+    else:
+        try:
+            sctypeDict[name] = allTypes['%s_' % name]
+        except:
+            print 'dtype',name,'not implemented, not assigned in numerictypes.sctypeDict'
+
+del _toadd, name
+
+# Now add the types we've determined to this module
+for key in allTypes:
+    globals()[key] = allTypes[key]
+    __all__.append(key)
+
+del key
+
+typecodes = {'Character':'c',
+             'Integer':'bhilqp',
+             'UnsignedInteger':'BHILQP',
+             'Float':'efdg',
+             'Complex':'FDG',
+             'AllInteger':'bBhHiIlLqQpP',
+             'AllFloat':'efdgFDG',
+             'Datetime': 'Mm',
+             'All':'?bhilqpBHILQPefdgFDGSUVOMm'}
+
+# backwards compatibility --- deprecated name
+typeDict = sctypeDict
+typeNA = sctypeNA
+
+# b -> boolean
+# u -> unsigned integer
+# i -> signed integer
+# f -> floating point
+# c -> complex
+# M -> datetime
+# m -> timedelta
+# S -> string
+# U -> Unicode string
+# V -> record
+# O -> Python object
+_kind_list = ['b', 'u', 'i', 'f', 'c', 'S', 'U', 'V', 'O', 'M', 'm']
+
+__test_types = '?'+typecodes['AllInteger'][:-2]+typecodes['AllFloat']+'O'
+__len_test_types = len(__test_types)
+
+# Keep incrementing until a common type both can be coerced to
+#  is found.  Otherwise, return None
+def _find_common_coerce(a, b):
+    if a > b:
+        return a
+    try:
+        thisind = __test_types.index(a.char)
+    except ValueError:
+        return None
+    return _can_coerce_all([a,b], start=thisind)
+
+# Find a data-type that all data-types in a list can be coerced to
+def _can_coerce_all(dtypelist, start=0):
+    N = len(dtypelist)
+    if N == 0:
+        return None
+    if N == 1:
+        return dtypelist[0]
+    thisind = start
+    while thisind < __len_test_types:
+        newdtype = dtype(__test_types[thisind])
+        numcoerce = len([x for x in dtypelist if newdtype >= x])
+        if numcoerce == N:
+            return newdtype
+        thisind += 1
+    return None
+
+def find_common_type(array_types, scalar_types):
+    """
+    Determine common type following standard coercion rules.
+
+    Parameters
+    ----------
+    array_types : sequence
+        A list of dtypes or dtype convertible objects representing arrays.
+    scalar_types : sequence
+        A list of dtypes or dtype convertible objects representing scalars.
+
+    Returns
+    -------
+    datatype : dtype
+        The common data type, which is the maximum of `array_types` ignoring
+        `scalar_types`, unless the maximum of `scalar_types` is of a
+        different kind (`dtype.kind`). If the kind is not understood, then
+        None is returned.
+
+    See Also
+    --------
+    dtype, common_type, can_cast, mintypecode
+
+    Examples
+    --------
+    >>> np.find_common_type([], [np.int64, np.float32, np.complex])
+    dtype('complex128')
+    >>> np.find_common_type([np.int64, np.float32], [])
+    dtype('float64')
+
+    The standard casting rules ensure that a scalar cannot up-cast an
+    array unless the scalar is of a fundamentally different kind of data
+    (i.e. under a different hierarchy in the data type hierarchy) then
+    the array:
+
+    >>> np.find_common_type([np.float32], [np.int64, np.float64])
+    dtype('float32')
+
+    Complex is of a different type, so it up-casts the float in the
+    `array_types` argument:
+
+    >>> np.find_common_type([np.float32], [np.complex])
+    dtype('complex128')
+
+    Type specifier strings are convertible to dtypes and can therefore
+    be used instead of dtypes:
+
+    >>> np.find_common_type(['f4', 'f4', 'i4'], ['c8'])
+    dtype('complex128')
+
+    """
+    array_types = [dtype(x) for x in array_types]
+    scalar_types = [dtype(x) for x in scalar_types]
+
+    maxa = _can_coerce_all(array_types)
+    maxsc = _can_coerce_all(scalar_types)
+
+    if maxa is None:
+        return maxsc
+
+    if maxsc is None:
+        return maxa
+
+    try:
+        index_a = _kind_list.index(maxa.kind)
+        index_sc = _kind_list.index(maxsc.kind)
+    except ValueError:
+        return None
+
+    if index_sc > index_a:
+        return _find_common_coerce(maxsc,maxa)
+    else:
+        return maxa