/* * Must be broadcastable. * This code is very similar to NpyArray_CopyInto/NpyArray_MoveInto * except casting is done --- NPY_BUFSIZE is used * as the size of the casting buffer. */ /* * Cast to an already created array. */ internal static int NpyArray_CastTo(NpyArray dest, NpyArray src) { bool simple; bool same; NpyArray_VectorUnaryFunc castfunc = null; npy_intp srcSize = NpyArray_SIZE(src); bool iswap, oswap; if (srcSize == 0) { return(0); } if (!NpyArray_ISWRITEABLE(dest)) { NpyErr_SetString(npyexc_type.NpyExc_ValueError, "output array is not writeable"); return(-1); } castfunc = NpyArray_GetCastFunc(src.descr, dest.descr.type_num); if (castfunc == null) { return(-1); } same = NpyArray_SAMESHAPE(dest, src); simple = same && (NpyArray_ISWRITEABLE(src) && NpyArray_ISWRITEABLE(dest)) && ((NpyArray_ISCARRAY_RO(src) && NpyArray_ISCARRAY(dest)) || (NpyArray_ISFARRAY_RO(src) && NpyArray_ISFARRAY(dest))); if (simple) { castfunc(src.data, dest.data, srcSize, src, dest); if (NpyErr_Occurred()) { return(-1); } return(0); } /* * If the input or output is OBJECT, STRING, UNICODE, or VOID * then getitem and setitem are used for the cast * and byteswapping is handled by those methods */ if (NpyArray_ISFLEXIBLE(src) || NpyArray_ISOBJECT(src) || NpyArray_ISOBJECT(dest) || NpyArray_ISFLEXIBLE(dest)) { iswap = oswap = false; } else { iswap = NpyArray_ISBYTESWAPPED(src); oswap = NpyArray_ISBYTESWAPPED(dest); } return(_broadcast_cast(dest, src, castfunc, iswap, oswap)); }
internal static int NpyArray_CastAnyTo(NpyArray dst, NpyArray mp) { bool simple; NpyArray_VectorUnaryFunc castfunc = null; npy_intp mpsize = NpyArray_SIZE(mp); if (mpsize == 0) { return(0); } if (!NpyArray_ISWRITEABLE(dst)) { NpyErr_SetString(npyexc_type.NpyExc_ValueError, "output array is not writeable"); return(-1); } if (!(mpsize == NpyArray_SIZE(dst))) { NpyErr_SetString(npyexc_type.NpyExc_ValueError, "arrays must have the same number of elements for the cast."); return(-1); } castfunc = NpyArray_GetCastFunc(mp.descr, dst.descr.type_num); if (castfunc == null) { return(-1); } simple = (NpyArray_ISWRITEABLE(mp) && NpyArray_ISWRITEABLE(dst)) && ((NpyArray_ISCARRAY_RO(mp) && NpyArray_ISCARRAY(dst)) || (NpyArray_ISFARRAY_RO(mp) && NpyArray_ISFARRAY(dst))); if (simple) { castfunc(mp.data, dst.data, mpsize, mp, dst); return(0); } if (NpyArray_SAMESHAPE(dst, mp)) { bool iswap, oswap; iswap = NpyArray_ISBYTESWAPPED(mp) && !NpyArray_ISFLEXIBLE(mp); oswap = NpyArray_ISBYTESWAPPED(dst) && !NpyArray_ISFLEXIBLE(dst); return(_broadcast_cast(dst, mp, castfunc, iswap, oswap)); } return(_bufferedcast(dst, mp, castfunc)); }
static void _strided_buffered_cast(VoidPtr dptr, npy_intp dstride, int delsize, bool dswap, NpyArray_CopySwapNFunc dcopyfunc, VoidPtr sptr, npy_intp sstride, int selsize, bool sswap, NpyArray_CopySwapNFunc scopyfunc, npy_intp N, VoidPtr[] buffers, int bufsize, NpyArray_VectorUnaryFunc castfunc, NpyArray dest, NpyArray src) { int i; if (N <= bufsize) { /* * 1. copy input to buffer and swap * 2. cast input to output * 3. swap output if necessary and copy from output buffer */ scopyfunc(buffers[1], selsize, sptr, sstride, N, sswap, src); castfunc(buffers[1], buffers[0], N, src, dest); dcopyfunc(dptr, dstride, buffers[0], delsize, N, dswap, dest); return; } /* otherwise we need to divide up into bufsize pieces */ i = 0; while (N > 0) { int newN = (int)Math.Min(N, bufsize); _strided_buffered_cast(dptr + i * dstride, dstride, delsize, dswap, dcopyfunc, sptr + i * sstride, sstride, selsize, sswap, scopyfunc, (npy_intp)newN, buffers, bufsize, castfunc, dest, src); i += newN; N -= (npy_intp)bufsize; } return; }
public void NpyArray_GetCastFunc_Test1() { var NPY_TYPES_Values = Enum.GetValues(typeof(NPY_TYPES)); foreach (NPY_TYPES type in NPY_TYPES_Values) { int ExpectedSize = Common.GetDefaultItemSize(type); if (ExpectedSize < 0) { continue; } NpyArray_VectorUnaryFunc castfunc = null; var newDescr = numpyAPI.NpyArray_DescrNewFromType(type); castfunc = numpyAPI.NpyArray_GetCastFunc(newDescr, NPY_TYPES.NPY_INT32); Assert.IsTrue(castfunc != Common.DefaultCastFunction); int result = numpyAPI.NpyArray_RegisterCastFunc(newDescr, NPY_TYPES.NPY_INT32, Common.DefaultCastFunction); Assert.AreEqual(0, result); castfunc = numpyAPI.NpyArray_GetCastFunc(newDescr, NPY_TYPES.NPY_INT32); Assert.IsTrue(castfunc == Common.DefaultCastFunction); } }
/* * Get a cast function to cast from the input descriptor to the * output type_number (must be a registered data-type). * Returns null if un-successful. */ internal static NpyArray_VectorUnaryFunc NpyArray_GetCastFunc(NpyArray_Descr descr, NPY_TYPES type_num) { NpyArray_VectorUnaryFunc castfunc = null; if (type_num < NPY_TYPES.NPY_NTYPES) { castfunc = descr.f.cast[(int)type_num]; } else { /* Check castfuncs for casts to user defined types. */ if (descr.f.castfuncs != null) { NpyArray_CastFuncsItem pitem = descr.f.castfuncs.FirstOrDefault(t => t.totype == type_num); if (pitem != null) { castfunc = pitem.castfunc; } } } if (NpyTypeNum_ISCOMPLEX(descr.type_num) && !NpyTypeNum_ISCOMPLEX(type_num) && NpyTypeNum_ISNUMBER(type_num) && !NpyTypeNum_ISBOOL(type_num)) { NpyErr_SetString(npyexc_type.NpyExc_ComplexWarning, "Casting complex values to real discards the imaginary part"); } if (null == castfunc) { NpyErr_SetString(npyexc_type.NpyExc_ValueError, "No cast function available."); return(null); } return(castfunc); }
internal static int NpyArray_RegisterCastFunc(NpyArray_Descr descr, NPY_TYPES totype, NpyArray_VectorUnaryFunc castfunc) { if (totype < NPY_TYPES.NPY_NTYPES) { descr.f.cast[(int)totype] = castfunc; return(0); } if (!NpyTypeNum_ISUSERDEF(totype)) { NpyErr_SetString(npyexc_type.NpyExc_TypeError, "invalid type number."); return(-1); } if (descr.f.castfuncs == null) { descr.f.castfuncs = new List <NpyArray_CastFuncsItem>(); if (descr.f.castfuncs == null) { return(-1); } } descr.f.castfuncs.Add(new NpyArray_CastFuncsItem() { castfunc = castfunc, totype = totype }); return(0); }
static int _bufferedcast(NpyArray dst, NpyArray src, NpyArray_VectorUnaryFunc castfunc) { VoidPtr inbuffer; VoidPtr bptr; VoidPtr optr; VoidPtr outbuffer = null; NpyArrayIterObject it_in = null, it_out = null; npy_intp i, index; npy_intp ncopies = NpyArray_SIZE(dst) / NpyArray_SIZE(src); int elsize = src.descr.elsize; int nels = npy_defs.NPY_BUFSIZE; int el; bool inswap, outswap = false; bool obuf = !NpyArray_ISCARRAY(dst); int oelsize = dst.descr.elsize; int retval = -1; /* * If the input or output is STRING, UNICODE, or VOID * then getitem and setitem are used for the cast * and byteswapping is handled by those methods */ inswap = !(NpyArray_ISFLEXIBLE(src) || NpyArray_ISNOTSWAPPED(src)); inbuffer = NpyDataMem_NEW(dst.descr.type_num, (ulong)(npy_defs.NPY_BUFSIZE * elsize)); if (inbuffer == null) { return(-1); } it_in = NpyArray_IterNew(src); if (it_in == null) { goto exit; } if (obuf) { outswap = !(NpyArray_ISFLEXIBLE(dst) || NpyArray_ISNOTSWAPPED(dst)); outbuffer = NpyDataMem_NEW(dst.descr.type_num, (ulong)(npy_defs.NPY_BUFSIZE * oelsize)); if (outbuffer == null) { goto exit; } it_out = NpyArray_IterNew(dst); if (it_out == null) { goto exit; } nels = Math.Min(nels, npy_defs.NPY_BUFSIZE); } optr = new VoidPtr((obuf) ? outbuffer : dst.data); bptr = new VoidPtr(inbuffer); el = 0; while (ncopies-- > 0) { index = it_in.size; NpyArray_ITER_RESET(it_in); while (index-- > 0) { _default_copyswap(bptr, 0, it_in.dataptr, 0, 1, inswap, src); bptr.data_offset += elsize; NpyArray_ITER_NEXT(it_in); el += 1; if ((el == nels) || (index == 0)) { /* buffer filled, do cast */ castfunc(inbuffer, optr, (npy_intp)el, src, dst); if (obuf) { /* Copy from outbuffer to array */ for (i = 0; i < el; i++) { _default_copyswap(it_out.dataptr, 0, optr, 0, 1, outswap, dst); optr.data_offset += oelsize; NpyArray_ITER_NEXT(it_out); } optr = new VoidPtr(outbuffer); } else { optr.data_offset += dst.descr.elsize * nels; } el = 0; bptr = new VoidPtr(inbuffer); } } } retval = 0; exit: Npy_XDECREF(it_in); if (obuf) { Npy_XDECREF(it_out); } return(retval); }
internal static int _broadcast_cast(NpyArray dest, NpyArray src, NpyArray_VectorUnaryFunc castfunc, bool iswap, bool oswap) { int delsize, selsize, maxaxis, i, N; NpyArrayMultiIterObject multi; npy_intp maxdim, ostrides, istrides; VoidPtr [] buffers = new VoidPtr[2]; NpyArray_CopySwapNFunc ocopyfunc, icopyfunc; delsize = NpyArray_ITEMSIZE(dest); selsize = NpyArray_ITEMSIZE(src); multi = NpyArray_MultiIterFromArrays(null, 0, 2, dest, src); if (multi == null) { return(-1); } if (multi.size != NpyArray_SIZE(dest)) { NpyErr_SetString(npyexc_type.NpyExc_ValueError, "array dimensions are not compatible for copy"); Npy_DECREF(multi); return(-1); } icopyfunc = _default_copyswap; ocopyfunc = _default_copyswap; maxaxis = NpyArray_RemoveSmallest(multi); if (maxaxis < 0) { /* cast 1 0-d array to another */ N = 1; maxdim = 1; ostrides = (npy_intp)delsize; istrides = (npy_intp)selsize; } else { maxdim = multi.dimensions[maxaxis]; N = (int)Math.Min(maxdim, npy_defs.NPY_BUFSIZE); ostrides = multi.iters[0].strides[maxaxis]; istrides = multi.iters[1].strides[maxaxis]; } buffers[0] = NpyDataMem_NEW(dest.descr.type_num, (ulong)(N * delsize)); buffers[1] = NpyDataMem_NEW(src.descr.type_num, (ulong)(N * selsize)); if (buffers[0] == null || buffers[1] == null) { NpyErr_MEMORY(); return(-1); } // NpyArray_ITER_ParallelSplit system will not work here. Processing must be done in sequential order. while (multi.index < multi.size) { _strided_buffered_cast(multi.iters[0].dataptr, ostrides, delsize, oswap, ocopyfunc, multi.iters[1].dataptr, istrides, selsize, iswap, icopyfunc, maxdim, buffers, N, castfunc, dest, src); NpyArray_MultiIter_NEXT(multi); } Npy_DECREF(multi); if (NpyErr_Occurred()) { return(-1); } return(0); }
internal static int NpyArray_RegisterCastFunc(NpyArray_Descr descr, NPY_TYPES totype, NpyArray_VectorUnaryFunc castfunc) { return(numpyinternal.NpyArray_RegisterCastFunc(descr, totype, castfunc)); }