Пример #1
0
 public IStorage GetStorage(NPTypeCode typeCode)
 {
     return(new TypedArrayStorage(typeCode)
     {
         Engine = this
     });
 }
Пример #2
0
 public override UnmanagedStorage GetStorage(NPTypeCode typeCode)
 {
     return(new UnmanagedStorage(typeCode)
     {
         Engine = this
     });
 }
Пример #3
0
        public NDArray Cast(NDArray nd, NPTypeCode dtype, bool copy)
        {
            if (dtype == NPTypeCode.Empty)
            {
                throw new ArgumentNullException(nameof(dtype));
            }

            NDArray clone()
            {
                var copied = new NDArray(nd.dtype, nd.TensorEngine);

                copied.Storage.Allocate(ArrayConvert.To(nd.Array, dtype), nd.shape);

                return(copied);
            }

            if (nd.GetTypeCode == dtype)
            {
                //casting not needed
                return(copy ? clone() : nd);
            }
            else
            {
                //casting needed
                if (copy)
                {
                    return(clone());
                }

                //just re-set the data, conversion is handled inside.
                nd.Storage.ReplaceData(nd.Storage.GetData(), dtype);
                return(nd);
            }
        }
Пример #4
0
        public static Object ChangeType(Object value, NPTypeCode typeCode)
        {
            if (value == null && (typeCode == NPTypeCode.Empty || typeCode == NPTypeCode.String))
                return null;

            // This line is invalid for things like Enums that return a NPTypeCode
            // of Int32, but the object can't actually be cast to an Int32.
            //            if (v.GetNPTypeCode() == NPTypeCode) return value;
            switch (typeCode)
            {
                case NPTypeCode.Boolean:
                    return ((IConvertible)value).ToBoolean(CultureInfo.InvariantCulture);
                case NPTypeCode.Byte:
                    return ((IConvertible)value).ToByte(CultureInfo.InvariantCulture);
                case NPTypeCode.Int32:
                    return ((IConvertible)value).ToInt32(CultureInfo.InvariantCulture);
                case NPTypeCode.Int64:
                    return ((IConvertible)value).ToInt64(CultureInfo.InvariantCulture);
                case NPTypeCode.Single:
                    return ((IConvertible)value).ToSingle(CultureInfo.InvariantCulture);
                case NPTypeCode.Double:
                    return ((IConvertible)value).ToDouble(CultureInfo.InvariantCulture);
                case NPTypeCode.String:
                    return ((IConvertible)value).ToString(CultureInfo.InvariantCulture);
                case NPTypeCode.Empty:
                    throw new InvalidCastException("InvalidCast_Empty");
                default:
                    throw new ArgumentException("Arg_UnknownNPTypeCode");
            }
        }
Пример #5
0
        /// <summary>
        ///     Return a new array of given shape and type, filled with ones.
        /// </summary>
        /// <param name="shape">Shape of the new array.</param>
        /// <param name="typeCode">The desired data-type for the array, e.g., <see cref="uint8"/>. Default is <see cref="float64"/> / <see cref="double"/>.</param>
        /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.ones.html</remarks>
        public static NDArray ones(Shape shape, NPTypeCode typeCode)
        {
            object one = null;

            switch (typeCode)
            {
            case NPTypeCode.Complex:
                one = new Complex(1d, 0d);
                break;

            case NPTypeCode.NDArray:
                one = NDArray.Scalar(1, np.int32);
                break;

            case NPTypeCode.String:
                one = "1";
                break;

            case NPTypeCode.Char:
                one = '1';
                break;

            default:
                one = Converts.ChangeType((byte)1, typeCode);
                break;
            }

            return(new NDArray(ArraySlice.Allocate(typeCode, shape.size, one), shape));
        }
Пример #6
0
        public static Type AsType(this NPTypeCode typeCode)
        {
            switch (typeCode)
            {
#if _REGEN
	            %foreach all_dtypes,all_dtypes_lowercase%
	            case NPTypeCode.#1: return typeof(#2);
	            %
Пример #7
0
        public static IMemoryBlock CastTo(this IMemoryBlock source, NPTypeCode to)
        {
            switch (to)
            {
#if _REGEN1
	            %foreach supported_dtypes,supported_dtypes_lowercase%
	            case NPTypeCode.#1: return CastTo<#2>(source);
	            %
Пример #8
0
        public override NDArray Cast(NDArray nd, NPTypeCode dtype, bool copy)
        {
            if (dtype == NPTypeCode.Empty)
            {
                throw new ArgumentNullException(nameof(dtype));
            }

            NDArray clone() => new NDArray(nd.Storage.Clone());

            if (nd.Shape.IsEmpty)
            {
                if (copy)
                {
                    return(new NDArray(dtype));
                }

                nd.Storage = new UnmanagedStorage(dtype);
                return(nd);
            }

            if (nd.Shape.IsScalar || (nd.Shape.size == 1 && nd.Shape.NDim == 1))
            {
                var ret = NDArray.Scalar(nd.GetAtIndex(0), dtype);
                if (copy)
                {
                    return(ret);
                }

                nd.Storage = ret.Storage;
                return(nd);
            }

            if (nd.GetTypeCode == dtype)
            {
                //casting not needed
                return(copy ? clone() : nd);
            }
            else
            {
                //casting needed
                if (copy)
                {
                    if (nd.Shape.IsSliced)
                    {
                        nd = clone();
                    }

                    return(new NDArray(new UnmanagedStorage(ArraySlice.FromMemoryBlock(nd.Array.CastTo(dtype), false), nd.Shape)));
                }
                else
                {
                    var storage = nd.Shape.IsSliced ? nd.Storage.Clone() : nd.Storage;
                    nd.Storage = new UnmanagedStorage(ArraySlice.FromMemoryBlock(storage.InternalArray.CastTo(dtype), false), storage.Shape);
                    return(nd);
                }
            }
        }
Пример #9
0
        /// <summary>
        ///     Return a new double array of given shape, filled with zeros.
        /// </summary>
        /// <param name="shape">Shape of the new array,</param>
        /// <param name="typeCode">The desired data-type for the array, e.g., <see cref="uint8"/>. Default is <see cref="float64"/> / <see cref="double"/>.</param>
        /// <returns>Array of zeros with the given shape, dtype.</returns>
        /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.zeros.html</remarks>
        public static NDArray zeros(Shape shape, NPTypeCode typeCode)
        {
            if (typeCode == NPTypeCode.Empty)
            {
                throw new ArgumentNullException(nameof(typeCode));
            }

            return(new NDArray(typeCode, shape, true)); //already allocates inside.
        }
Пример #10
0
        /// <summary>
        ///     Creates a scalar <see cref="NDArray"/> of <see cref="value"/> and <see cref="dtype"/>.
        /// </summary>
        /// <param name="value">The value of the scalar</param>
        /// <param name="typeCode">The type code of the scalar.</param>
        /// <returns></returns>
        /// <remarks>In case when <see cref="value"/> is not <see cref="dtype"/>, <see cref="Convert.ChangeType(object,System.Type)"/> will be called.</remarks>
        public static NDArray Scalar(object value, NPTypeCode typeCode)
        {
            var type    = typeCode.AsType();
            var ndArray = new NDArray(type, new int[0]);

            ndArray.Storage.ReplaceData(Arrays.Wrap(typeCode, Convert.ChangeType(value, type))); //todo! create a NPConvert to support NPTypeCode

            return(ndArray);
        }
Пример #11
0
        /// <summary>
        ///     Return a new array of given shape and type, without initializing entries.
        /// </summary>
        /// <param name="shape">Shape of the empty array, e.g., (2, 3) or 2.</param>
        /// <param name="typeCode">Desired output data-type for the array, e.g, numpy.int8. Default is numpy.float64.</param>
        /// <returns>Array of uninitialized (arbitrary) data of the given shape, dtype, and order. Object arrays will be initialized to None.</returns>
        /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.empty.html</remarks>
        public static NDArray empty(Shape shape, NPTypeCode typeCode)
        {
            if (typeCode == NPTypeCode.Empty)
            {
                throw new ArgumentNullException(nameof(typeCode));
            }

            return(new NDArray(typeCode, shape, false));
        }
Пример #12
0
        /// <summary>
        ///     Return a new array of given shape and type, filled with fill_value.
        /// </summary>
        /// <param name="fill_value">Fill value.</param>
        /// <param name="shape">Shape of the empty array, e.g., (2, 3) or 2.</param>
        /// <param name="typeCode">The desired data-type for the array The default, null, means np.array(fill_value).dtype.</param>
        /// <returns>Array of fill_value with the given shape, dtype, and order.</returns>
        /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.full.html</remarks>
        public static NDArray full(ValueType fill_value, Shape shape, NPTypeCode typeCode)
        {
            if (typeCode == NPTypeCode.Empty)
            {
                throw new ArgumentNullException(nameof(typeCode));
            }

            return(new NDArray(new UnmanagedStorage(ArraySlice.Allocate(typeCode, shape.size, Convert.ChangeType(fill_value, (TypeCode)typeCode)), shape)));
        }
Пример #13
0
        /// <summary>
        ///     Convert <see cref="NPTypeCode"/> into its <see cref="Type"/>
        /// </summary>
        /// <param name="typeCode"></param>
        /// <returns></returns>
        public static Type AsType(this NPTypeCode typeCode)
        {
            switch (typeCode)
            {
            case NPTypeCode.Empty:
                return(null);

            case NPTypeCode.Boolean:
                return(typeof(Boolean));

            case NPTypeCode.Char:
                return(typeof(Char));

            case NPTypeCode.Byte:
                return(typeof(Byte));

            case NPTypeCode.Int16:
                return(typeof(Int16));

            case NPTypeCode.UInt16:
                return(typeof(UInt16));

            case NPTypeCode.Int32:
                return(typeof(Int32));

            case NPTypeCode.UInt32:
                return(typeof(UInt32));

            case NPTypeCode.Int64:
                return(typeof(Int64));

            case NPTypeCode.UInt64:
                return(typeof(UInt64));

            case NPTypeCode.Single:
                return(typeof(Single));

            case NPTypeCode.Double:
                return(typeof(Double));

            case NPTypeCode.Decimal:
                return(typeof(Decimal));

            case NPTypeCode.String:
                return(typeof(String));

            case NPTypeCode.NDArray:
                return(typeof(NDArray));

            case NPTypeCode.Complex:
                return(typeof(Complex));

            default:
                throw new ArgumentOutOfRangeException(nameof(typeCode), typeCode, null);
            }
        }
Пример #14
0
        /// <summary>
        ///     Creates an array of 1D of type <paramref name="typeCode"/>.
        /// </summary>
        /// <param name="typeCode">The type to create this array.</param>
        /// <param name="length">The length of the array</param>
        /// <remarks>Do not use this if you are trying to create jagged or multidimensional array.</remarks>
        public static Array Create(NPTypeCode typeCode, int length)
        {
            switch (typeCode)
            {
#if _REGEN
                % foreach supported_dtypes, supported_dtypes_lowercase %
            case NPTypeCode.#1:
            {
                return(new #2[length]);
            }
Пример #15
0
        /// <summary>
        ///     Return a casted <see cref="UnmanagedStorage"/> to a specific dtype only if necessary
        /// </summary>
        /// <param name="typeCode">The dtype to convert to</param>
        /// <returns>A copy of this <see cref="UnmanagedStorage"/> casted to a specific dtype.</returns>
        /// <remarks>Copies only if dtypes does not match <paramref name="typeCode"/></remarks>
        public UnmanagedStorage CastIfNecessary(NPTypeCode typeCode)
        {
            if (_shape.IsEmpty || _typecode == typeCode)
            {
                return(this);
            }

            //this also handles slices
            return(new UnmanagedStorage((IArraySlice)InternalArray.CastTo(typeCode), _shape.Clone(true, true, true)));
        }
Пример #16
0
 /// <summary>
 /// Translates the <see cref="NPTypeCode"/> type code in to the actual reflecton type.
 /// </summary>
 /// <param name="code">The type code to translate into the type.</param>
 /// <returns>The <see cref="NDArray"/> element <see cref="Type"/>translated.</returns>
 public static Type Translate(NPTypeCode code)
 {
     if (s_types.TryGetValue(code, out var type))
     {
         return(type);
     }
     else
     {
         throw new ArgumentException($"The operation index does not support requested type code: {code}.");
     }
 }
Пример #17
0
        /// <summary>
        ///     Return a casted <see cref="UnmanagedStorage"/> to a specific dtype.
        /// </summary>
        /// <param name="typeCode">The dtype to convert to</param>
        /// <returns>A copy of this <see cref="UnmanagedStorage"/> casted to a specific dtype.</returns>
        /// <remarks>Always copies, If dtype==typeof(T) then a <see cref="Clone"/> is returned.</remarks>
        public UnmanagedStorage Cast(NPTypeCode typeCode)
        {
            if (Shape.IsEmpty)
            {
                return(new UnmanagedStorage(typeCode));
            }

            if (_typecode == typeCode)
            {
                return(Clone());
            }

            //this also handles slices
            return(new UnmanagedStorage((IArraySlice)InternalArray.CastTo(typeCode), Shape.Clone(true, true)));
        }
Пример #18
0
        /// <summary>
        ///     Get the min value of given <see cref="NPTypeCode"/>.
        /// </summary>
        public static object MaxValue(this NPTypeCode typeCode)
        {
            switch (typeCode)
            {
            case NPTypeCode.Complex:
                return(new Complex(double.MaxValue, double.MaxValue));

            case NPTypeCode.Boolean:
                return(true);

#if _REGEN
                % foreach except(supported_primitives, "Boolean", "String") %
            case NPTypeCode.#1:
                return(#1.MaxValue);

                %
#else
            case NPTypeCode.Byte:
                return(Byte.MaxValue);
Пример #19
0
        /// <summary>
        ///     Return evenly spaced numbers over a specified interval.<br></br>
        ///     Returns num evenly spaced samples, calculated over the interval[start, stop].<br></br>
        ///     The endpoint of the interval can optionally be excluded.
        /// </summary>
        /// <param name="start">The starting value of the sequence.</param>
        /// <param name="stop">The end value of the sequence, unless endpoint is set to False. In that case, the sequence consists of all but the last of num + 1 evenly spaced samples, so that stop is excluded. Note that the step size changes when endpoint is False.</param>
        /// <param name="num">Number of samples to generate. Default is 50. Must be non-negative.</param>
        /// <param name="endpoint">If True, stop is the last sample. Otherwise, it is not included. Default is True.</param>
        /// <param name="typeCode">The type of the output array. If dtype is not given, infer the data type from the other input arguments.</param>
        /// <remarks>https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.linspace.html</remarks>
        public static NDArray linspace(double start, double stop, int num, bool endpoint = true, NPTypeCode typeCode = NPTypeCode.Double)
        {
            if (typeCode == NPTypeCode.Empty)
            {
                throw new ArgumentException("Invalid typeCode", nameof(typeCode));
            }

            NDArray ret  = new NDArray(typeCode, new Shape(num), false);
            double  step = (stop - start) / (endpoint ? num - 1.0 : num);

            switch (ret.GetTypeCode)
            {
#if _REGEN
            case NPTypeCode.Boolean:
            {
                unsafe
                {
                    var addr = (bool *)ret.Address;
                    for (int i = 0; i < num; i++)
                    {
                        *(addr + i) = (start + i * step) != 0;
                    }
                }

                return(ret);
            }

                % foreach except(supported_dtypes, "Boolean"), except(supported_dtypes_lowercase, "bool") %
            case NPTypeCode.#1:
            {
                unsafe
                {
                    var addr = (#2 *)ret.Address;
                    for (int i = 0; i < num; i++)
                    {
                        *(addr + i) = Convert.To #1 (start + i * step);
                    }
                }

                return(ret);
            }
Пример #20
0
 /// <summary>
 ///     Get storage for given <paramref name="typeCode"/>.
 /// </summary>
 public abstract UnmanagedStorage GetStorage(NPTypeCode typeCode);
Пример #21
0
 public static bool IsNumerical(this NPTypeCode typeCode)
 {
     var val = (int)typeCode;
     return val >= 3 && val <= 15 || val == 129;
 }
Пример #22
0
 /// <summary>
 /// Constructor for init data type
 /// internal storage is 1D with 1 element
 /// </summary>
 /// <param name="typeCode">Data type of elements</param>
 /// <param name="engine">The engine of this <see cref="NDArray"/></param>
 /// <remarks>This constructor does not call allocation/></remarks>
 protected internal NDArray(NPTypeCode typeCode, TensorEngine engine)
 {
     tensorEngine = engine;
     Storage = TensorEngine.GetStorage(typeCode);
 }
Пример #23
0
 /// <summary>
 /// Constructor which initialize elements with 0
 /// type and shape are given.
 /// </summary>
 /// <param name="dtype">internal data type</param>
 /// <param name="shape">Shape of NDArray</param>
 /// <param name="fillZeros">Should set the values of the new allocation to default(dtype)? otherwise - old memory noise</param>
 /// <remarks>This constructor calls <see cref="IStorage.Allocate(NumSharp.Shape,System.Type)"/></remarks>
 public NDArray(NPTypeCode dtype, Shape shape, bool fillZeros) : this(dtype)
 {
     Storage.Allocate(shape, dtype, fillZeros);
 }
Пример #24
0
 /// <summary>
 ///     Constructor which initialize elements with length of <paramref name="size"/>
 /// </summary>
 /// <param name="dtype">Internal data type</param>
 /// <param name="size">The size as a single dimension shape</param>
 /// <param name="fillZeros">Should set the values of the new allocation to default(dtype)? otherwise - old memory noise</param>
 /// <remarks>This constructor calls <see cref="IStorage.Allocate(NumSharp.Shape,System.Type)"/></remarks>
 public NDArray(NPTypeCode dtype, int size, bool fillZeros) : this(dtype, Shape.Vector(size), true) { }
Пример #25
0
 /// <summary>
 ///     Constructor which initialize elements with length of <paramref name="size"/>
 /// </summary>
 /// <param name="dtype">Internal data type</param>
 /// <param name="size">The size as a single dimension shape</param>
 /// <remarks>This constructor calls <see cref="IStorage.Allocate(NumSharp.Shape,System.Type)"/></remarks>
 public NDArray(NPTypeCode dtype, int size) : this(dtype, Shape.Vector(size), true) { }
Пример #26
0
 /// <summary>
 /// Constructor which initialize elements with 0
 /// type and shape are given.
 /// </summary>
 /// <param name="dtype">internal data type</param>
 /// <param name="shape">Shape of NDArray</param>
 /// <remarks>This constructor calls <see cref="IStorage.Allocate(NumSharp.Shape,System.Type)"/></remarks>
 public NDArray(NPTypeCode dtype, Shape shape) : this(dtype, shape, true) { }
Пример #27
0
        /// <summary>
        ///     Join a sequence of arrays along an existing axis.
        /// </summary>
        /// <param name="axis">The axis along which the arrays will be joined. If axis is None, arrays are flattened before use. Default is 0.</param>
        /// <param name="arrays">The arrays must have the same shape, except in the dimension corresponding to axis (the first, by default).</param>
        /// <returns>The concatenated array.</returns>
        /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.concatenate.html</remarks>
        public static NDArray concatenate(NDArray[] arrays, int axis = 0)
        {
            //What we do is we have the axis which is the only dimension that is allowed to be different
            //We need to perform a check if the dimensions actually match.
            //After we have the axis ax=1 where shape is (3,ax,3) - ax is the only dimension that can vary.
            //So if we got input of (3,5,3) and (3,1,3), we create a return shape of (3,6,3).
            //We perform the assignment by iterating a slice: (:,n,:) on src and dst where dst while n of dst grows as we iterate all arrays.

            if (arrays == null)
            {
                throw new ArgumentNullException(nameof(arrays));
            }

            if (arrays.Length == 0)
            {
                throw new ArgumentException("Value cannot be an empty collection.", nameof(arrays));
            }

            if (arrays.Length == 1)
            {
                return(arrays[0]);
            }

            var first      = arrays[0];
            var firstShape = (int[])first.shape.Clone();

            while (axis < 0)
            {
                axis = first.ndim + axis; //translate negative axis
            }
            int        i, j;
            int        axisSize = 0; //accumulated shape[axis] size for return shape.
            NPTypeCode retType  = first.GetTypeCode;

            foreach (var src in arrays)
            {
                //accumulate the concatenated axis
                var shape = src.shape;
                axisSize += shape[axis];

                if (ReferenceEquals(src, first))
                {
                    continue;
                }

                var srcType = src.GetTypeCode;

                //resolve what the return type should be and should we perform casting.
                if (first.GetTypeCode != srcType)
                {
                    if (srcType.CompareTo(retType) == 1)
                    {
                        retType = srcType;
                    }
                }

                if (shape.Length != first.ndim)
                {
                    throw new IncorrectShapeException("all the input arrays must have same number of dimensions.");
                }

                //verify the shapes are equal
                for (j = 0; j < shape.Length; j++)
                {
                    if (axis == j)
                    {
                        continue;
                    }

                    if (shape[j] != firstShape[j])
                    {
                        throw new IncorrectShapeException("all the input array dimensions except for the concatenation axis must match exactly.");
                    }
                }
            }

            //prepare return shape
            firstShape[axis] = axisSize;
            var retShape = new Shape(firstShape);

            var dst         = new NDArray(retType, retShape);
            var accessorDst = new Slice[retShape.NDim];
            var accessorSrc = new Slice[retShape.NDim];

            for (i = 0; i < accessorDst.Length; i++)
            {
                accessorSrc[i] = accessorDst[i] = Slice.All;
            }

            accessorSrc[axis] = Slice.Index(0);
            accessorDst[axis] = Slice.Index(0);

            foreach (var src in arrays)
            {
                var len = src.shape[axis];
                for (i = 0; i < len; i++)
                {
                    var writeTo   = dst[accessorDst];
                    var writeFrom = src[accessorSrc];
                    MultiIterator.Assign(writeTo.Storage, writeFrom.Storage);
                    accessorSrc[axis]++;
                    accessorDst[axis]++; //increment every step
                }

                accessorSrc[axis] = Slice.Index(0); //reset src
            }

            return(dst);
        }
Пример #28
0
 /// <summary>
 ///     Return a new array of given shape and type, filled with fill_value.
 /// </summary>
 /// <param name="fill_value">Fill value.</param>
 /// <param name="shape">Shape of the empty array, e.g., (2, 3) or 2.</param>
 /// <param name="typeCode">The desired data-type for the array The default, null, means np.array(fill_value).dtype.</param>
 /// <returns>Array of fill_value with the given shape, dtype, and order.</returns>
 /// <remarks>https://docs.scipy.org/doc/numpy/reference/generated/numpy.full.html</remarks>
 public static NDArray full(Shape shape, ValueType fill_value, NPTypeCode typeCode)
 {
     return(full(fill_value, shape, typeCode));
 }
Пример #29
0
        static InfoOf()
        {
            NPTypeCode = typeof(T).GetTypeCode();
            Zero       = default;
            try
            {
                MaxValue = (T)NPTypeCode.MaxValue();
                MinValue = (T)NPTypeCode.MinValue();
            }
            catch (ArgumentOutOfRangeException) { }

            switch (NPTypeCode)
            {
            case NPTypeCode.NDArray:
                Size = IntPtr.Size;
                break;

            case NPTypeCode.Boolean:
                Size = 1;
                break;

            case NPTypeCode.Char:
                Size = 2;
                break;

            case NPTypeCode.Byte:
                Size = 1;
                break;

            case NPTypeCode.Int16:
                Size = 2;
                break;

            case NPTypeCode.UInt16:
                Size = 2;
                break;

            case NPTypeCode.Int32:
                Size = 4;
                break;

            case NPTypeCode.UInt32:
                Size = 4;
                break;

            case NPTypeCode.Int64:
                Size = 8;
                break;

            case NPTypeCode.UInt64:
                Size = 8;
                break;

            case NPTypeCode.Single:
                Size = 4;
                break;

            case NPTypeCode.Double:
                Size = 8;
                break;

            case NPTypeCode.Decimal:
                Size = 16;
                break;

            case NPTypeCode.String:
                break;

            case NPTypeCode.Complex:
            default:
                Size = Marshal.SizeOf <T>();
                break;
            }
        }
Пример #30
0
 /// <summary>
 /// Constructor for init data type
 /// internal storage is 1D with 1 element
 /// </summary>
 /// <param name="typeCode">Data type of elements</param>
 /// <remarks>This constructor does not call allocation/></remarks>
 public NDArray(NPTypeCode typeCode) : this(typeCode, BackendFactory.GetEngine()) { }