add append, insert, delete functions in numeric package

This commit is contained in:
wyq 2023-08-23 20:14:08 +08:00
parent ed90ae3529
commit ab15b26724
21 changed files with 694 additions and 92 deletions

View File

@ -331,7 +331,11 @@ public class MeshGraphic extends GraphicCollection3D {
vertexColor = new float[getVertexNumber() * 4];
float[] color;
for (int i = 0; i < vertexValue.length; i++) {
if (Float.isNaN(vertexValue[i])) {
color = legendScheme.getLegendBreak(0).getColor().getRGBComponents(null);
} else {
color = legendScheme.findLegendBreak(vertexValue[i]).getColor().getRGBComponents(null);
}
System.arraycopy(color, 0, vertexColor, i * 4, 4);
}
}

View File

@ -67,7 +67,7 @@ import java.util.zip.ZipInputStream;
public static String getVersion(){
String version = GlobalUtil.class.getPackage().getImplementationVersion();
if (version == null || version.equals("")) {
version = "3.6.5";
version = "3.6.6";
}
return version;
}

View File

@ -601,7 +601,7 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
Section section = new Section(origin, size, stride);
RadialRecord record = this.recordMap.get(varName);
Array dataArray = Array.factory(record.getDataType(), section.getShape());
Array dataArray = Array.factory(DataType.FLOAT, section.getShape());
Range zRange = section.getRange(0);
Range yRange = section.getRange(1);
Range xRange = section.getRange(2);
@ -623,6 +623,7 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
}
}
}
}
Attribute aoAttr = variable.findAttribute("add_offset");
Attribute sfAttr = variable.findAttribute("scale_factor");
@ -653,7 +654,6 @@ public class CMARadarBaseDataInfo extends DataInfo implements IGridDataInfo {
}
dataArray = ArrayMath.div(ArrayMath.sub(dataArray, add_offset), scale_factor);
}
}
return dataArray;
} catch (InvalidRangeException e) {

View File

@ -8,27 +8,27 @@
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\no_opengl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volume"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\array\complex"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volume"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\array"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\_reload.py"/>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\radar\radar_bz2_geo.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\array\gradient_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\radar\radar_bz2_3d.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\array\delete_1.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\_reload.py"/>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\io\radar\radar_bz2_geo.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\array\gradient_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\io\radar\radar_bz2_3d.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\array\delete_1.py"/>
</RecentFiles>
</File>
<Font>
@ -36,5 +36,5 @@
</Font>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
<Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-7,0" MainFormSize="1311,742"/>
<Startup MainFormLocation="-7,-7" MainFormSize="1293,685"/>
</MeteoInfo>

View File

@ -26,9 +26,9 @@ class RadarDataFile(DimDataFile):
:return: Scan elevation angles.
"""
if product is None:
return list(self.datainfo.getElevations())
return np.array(self.datainfo.getElevations())
else:
return list(self.datainfo.getElevations(product))
return np.array(self.datainfo.getElevations(product))
def get_vcs_data(self, product, start_point, end_point):
"""

View File

@ -19,6 +19,7 @@ def antenna_to_cartesian(distance, azimuth, elevation, h=None):
"""
azimuth = np.deg2rad(azimuth)
elevation = np.deg2rad(elevation)
if azimuth.ndim == 1:
nd = distance.shape[0]
na = azimuth.shape[0]
distance, azimuth = np.meshgrid(distance, azimuth)
@ -32,6 +33,29 @@ def antenna_to_cartesian(distance, azimuth, elevation, h=None):
r = Transform.antennaToCartesian(distance._array, azimuth._array, elevation, h)
return np.array(r[0]), np.array(r[1]), np.array(r[2])
else:
nd = distance.shape[0]
ns, na = azimuth.shape
x = np.empty((ns, na, nd))
y = np.empty((ns, na, nd))
z = np.empty((ns,na,nd))
for i in range(ns):
dis, azi = np.meshgrid(distance, azimuth[i])
if elevation.ndim == 1:
ele = elevation[i]
else:
ele = elevation[i].reshape(na, 1).copy()
ele = ele.repeat(nd, axis=1)
ele = ele._array
if h is None:
r = Transform.antennaToCartesian(dis._array, azi._array, ele)
else:
r = Transform.antennaToCartesian(dis._array, azi._array, ele, h)
x[i] = np.array(r[0])
y[i] = np.array(r[1])
z[i] = np.array(r[2])
return x, y, z
def antenna_to_geographic(lon, lat, distance, azimuth, elevation, h=None):
"""

View File

@ -80,6 +80,9 @@ class NDArray(object):
return self.dtype.itemsize
def __len__(self):
if self.ndim == 0:
return 0
else:
return self._shape[0]
def __str__(self):
@ -296,10 +299,10 @@ class NDArray(object):
step = 1
alllist = False
elif isinstance(k, (list, tuple, NDArray)):
if isinstance(k, NDArray):
k = k.aslist()
if isinstance(k, (list, tuple)):
k = NDArray(k)
onlyrange = False
ranges.append(k)
ranges.append(k._array)
continue
else:
sidx = 0 if k.start is None else k.start
@ -517,6 +520,32 @@ class NDArray(object):
else:
raise StopIteration()
def item(self, *args):
"""
Copy an element of an array to a standard Python scalar and return it.
:param args: none: in this case, the method only works for arrays with one element
(a.size == 1), which element is copied into a standard Python scalar object and returned.
int_type: this argument is interpreted as a flat index into the array, specifying which
element to copy and return.
tuple of int_types: functions as does a single int_type argument, except that the argument
is interpreted as a nd-index into the array.
:return: A copy of the specified element of the array as a suitable Python scalar
"""
if self.ndim == 0:
return self._array.get()
else:
index = self._array.getIndex()
if len(args) == 1:
if isinstance(args[0], int):
index.setCurrentIndex(args[0])
else:
index.set(args[0])
elif len(args) > 1:
index.set(args)
return self._array.getObject(index)
def copy(self):
"""
Copy array values to a new array.

View File

@ -40,7 +40,7 @@ __all__ = [
'argmin','argmax','argsort','array','array_split','amax','amin','asanyarray','asarray','asgridarray',
'asgriddata','arcsin','asin','asmiarray','asstationdata','atleast_1d','atleast_2d','arctan','atan',
'arctan2','atan2','ave_month','average','histogram','broadcast_to','cdiff','ceil',
'concatenate','conj','conjugate','corrcoef','cos','cosh','cylinder','degrees','delete','delnan','diag','diff',
'concatenate','conj','conjugate','corrcoef','cos','cosh','cylinder','degrees','delnan','diag','diff',
'datatable','dot','empty','empty_like','exp','eye','flatnonzero','floor',
'fmax','fmin','full','hcurl','hdivg','hstack','hypot','identity','indices','interp2d','interpn','isarray',
'isclose','isfinite','isinf','isnan','isscalar','linspace','log','log10','logical_not','logspace',
@ -65,7 +65,7 @@ def array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0):
:param dtype: (*DataType*) Data type
:param copy: (*bool*) If true (default), then the object is copied.
:param order: (*str*) Specify the memory layout of the array.
:param subok: (*bool*) If True, then sub-classes will be passed-through,
:param subok: (*bool*) If True, then subclasses will be passed-through,
otherwise the returned array will be forced to be a base-class array (default).
:param ndmin: (*int*) Specifies the minimum number of dimensions that the
resulting array should have.
@ -1753,8 +1753,8 @@ def argsort(a, axis=-1):
:param axis: (*int or None*) Optional. Axis along which to sort. If None, the array is
flattened after sorting. The default is ``-1`` , which sorts along the last axis.
:returns: (*NDArray*) Array of indices that sort a along the specified axis. If a is
one-dimensional, a[index_array] yields a sorted a.
:returns: (*NDArray*) Array of indices that sort `a` along the specified axis. If `a` is
one-dimensional, a[index_array] yields a sorted `a`.
"""
if isinstance(a, list):
a = array(a)
@ -1992,7 +1992,7 @@ def concatenate(arrays, axis=0):
"""
ars = []
for a in arrays:
ars.append(a.asarray())
ars.append(asanyarray(a).asarray())
r = ArrayUtil.concatenate(ars, axis)
return NDArray(r)
@ -2801,7 +2801,7 @@ def smooth5(x):
if isinstance(x, list):
x = array(x)
if x.ndim != 2:
print 'The array must be 2 dimension!'
print('The array must be 2 dimension!')
raise ValueError()
r = ArrayUtil.smooth5(x._array)
if isinstance(x, DimArray):
@ -2829,7 +2829,7 @@ def smooth9(x):
if isinstance(x, list):
x = array(x)
if x.ndim != 2:
print 'The array must be 2 dimension!'
print('The array must be 2 dimension!')
raise ValueError()
r = ArrayUtil.smooth9(x._array)
if isinstance(x, DimArray):

View File

@ -4,8 +4,10 @@ from ..core import dtype
from ..core._ndarray import NDArray
from ..core.fromnumeric import (ravel, nonzero)
from org.meteoinfo.ndarray.math import ArrayMath
import warnings
__all__ = ['angle','extract', 'place', 'grid_edge', 'gradient']
__all__ = ['angle','extract', 'place', 'grid_edge', 'gradient', 'append',
'delete', 'insert']
def extract(condition, arr):
@ -366,3 +368,401 @@ def gradient(f, *varargs, **kwargs):
return outvals[0]
else:
return outvals
def append(arr, values, axis=None):
"""
Append values to the end of an array.
Parameters
----------
arr : array_like
Values are appended to a copy of this array.
values : array_like
These values are appended to a copy of `arr`. It must be of the
correct shape (the same shape as `arr`, excluding `axis`). If
`axis` is not specified, `values` can be any shape and will be
flattened before use.
axis : int, optional
The axis along which `values` are appended. If `axis` is not
given, both `arr` and `values` are flattened before use.
Returns
-------
append : ndarray
A copy of `arr` with `values` appended to `axis`. Note that
`append` does not occur in-place: a new array is allocated and
filled. If `axis` is None, `out` is a flattened array.
See Also
--------
insert : Insert elements into an array.
delete : Delete elements from an array.
Examples
--------
>>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]])
array([1, 2, 3, ..., 7, 8, 9])
When `axis` is specified, `values` must have the correct shape.
>>> np.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0)
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> np.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0)
Traceback (most recent call last):
...
ValueError: all the input arrays must have same number of dimensions, but
the array at index 0 has 2 dimension(s) and the array at index 1 has 1
dimension(s)
"""
arr = np.asanyarray(arr)
if axis is None:
if arr.ndim != 1:
arr = arr.ravel()
values = ravel(values)
axis = arr.ndim-1
return np.concatenate((arr, values), axis=axis)
def delete(arr, obj, axis=None):
"""
Return a new array with sub-arrays along an axis deleted. For a one
dimensional array, this returns those entries not returned by
`arr[obj]`.
Parameters
----------
arr : array_like
Input array.
obj : slice, int or array of ints
Indicate indices of sub-arrays to remove along the specified axis.
.. versionchanged:: 1.19.0
Boolean indices are now treated as a mask of elements to remove,
rather than being cast to the integers 0 and 1.
axis : int, optional
The axis along which to delete the subarray defined by `obj`.
If `axis` is None, `obj` is applied to the flattened array.
Returns
-------
out : ndarray
A copy of `arr` with the elements specified by `obj` removed. Note
that `delete` does not occur in-place. If `axis` is None, `out` is
a flattened array.
See Also
--------
insert : Insert elements into an array.
append : Append elements at the end of an array.
Notes
-----
Often it is preferable to use a boolean mask. For example:
>>> arr = np.arange(12) + 1
>>> mask = np.ones(len(arr), dtype=bool)
>>> mask[[0,2,4]] = False
>>> result = arr[mask,...]
Is equivalent to ``np.delete(arr, [0,2,4], axis=0)``, but allows further
use of `mask`.
Examples
--------
>>> arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
>>> arr
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> np.delete(arr, 1, 0)
array([[ 1, 2, 3, 4],
[ 9, 10, 11, 12]])
>>> np.delete(arr, np.s_[::2], 1)
array([[ 2, 4],
[ 6, 8],
[10, 12]])
>>> np.delete(arr, [1,3,5], None)
array([ 1, 3, 5, 7, 8, 9, 10, 11, 12])
"""
arr = np.asarray(arr)
ndim = arr.ndim
if axis is None:
if ndim != 1:
arr = arr.ravel()
# needed for np.matrix, which is still not 1d after being ravelled
ndim = arr.ndim
axis = ndim - 1
else:
axis = np.normalize_axis_index(axis, ndim)
slobj = [slice(None)]*ndim
N = arr.shape[axis]
newshape = list(arr.shape)
if isinstance(obj, slice):
start, stop, step = obj.indices(N)
xr = range(start, stop, step)
numtodel = len(xr)
if numtodel <= 0:
return arr.copy()
# Invert if step is negative:
if step < 0:
step = -step
start = xr[-1]
stop = xr[0] + 1
newshape[axis] -= numtodel
new = np.empty(newshape, arr.dtype)
# copy initial chunk
if start == 0:
pass
else:
slobj[axis] = slice(None, start)
new[tuple(slobj)] = arr[tuple(slobj)]
# copy end chunk
if stop == N:
pass
else:
slobj[axis] = slice(stop-numtodel, None)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(stop, None)
new[tuple(slobj)] = arr[tuple(slobj2)]
# copy middle pieces
if step == 1:
pass
else: # use array indexing.
keep = np.ones(stop-start, dtype=np.dtype.bool)
keep[:stop-start:step] = False
slobj[axis] = slice(start, stop-numtodel)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(start, stop)
arr = arr[tuple(slobj2)]
slobj2[axis] = keep
new[tuple(slobj)] = arr[tuple(slobj2)]
return new
if isinstance(obj, int) and not isinstance(obj, bool):
single_value = True
else:
single_value = False
_obj = obj
obj = np.asarray(obj)
# `size == 0` to allow empty lists similar to indexing, but (as there)
# is really too generic:
if obj.size == 0 and not isinstance(_obj, np.NDArray):
obj = obj.astype(np.dtype.int)
elif obj.size == 1 and obj.dtype.kind in "ui":
# For a size 1 integer array we can use the single-value path
# (most dtypes, except boolean, should just fail later).
obj = obj.item()
single_value = True
if single_value:
# optimization for a single value
if (obj < -N or obj >= N):
raise IndexError(
"index %i is out of bounds for axis %i with "
"size %i" % (obj, axis, N))
if (obj < 0):
obj += N
newshape[axis] -= 1
new = np.empty(newshape, arr.dtype,)
slobj[axis] = slice(None, obj)
new[tuple(slobj)] = arr[tuple(slobj)]
slobj[axis] = slice(obj, None)
slobj2 = [slice(None)]*ndim
slobj2[axis] = slice(obj+1, None)
new[tuple(slobj)] = arr[tuple(slobj2)]
else:
if obj.dtype == np.dtype.bool:
if obj.shape != (N,):
raise ValueError('boolean array argument obj to delete '
'must be one dimensional and match the axis '
'length of {}'.format(N))
# optimization, the other branch is slower
keep = ~obj
else:
keep = np.ones(N, dtype=np.dtype.bool)
keep[obj,] = False
slobj[axis] = keep
new = arr[tuple(slobj)]
return new
def insert(arr, obj, values, axis=None):
"""
Insert values along the given axis before the given indices.
Parameters
----------
arr : array_like
Input array.
obj : int, slice or sequence of ints
Object that defines the index or indices before which `values` is
inserted.
Support for multiple insertions when `obj` is a single scalar or a
sequence with one element (similar to calling insert multiple
times).
values : array_like
Values to insert into `arr`. If the type of `values` is different
from that of `arr`, `values` is converted to the type of `arr`.
`values` should be shaped so that ``arr[...,obj,...] = values``
is legal.
axis : int, optional
Axis along which to insert `values`. If `axis` is None then `arr`
is flattened first.
Returns
-------
out : ndarray
A copy of `arr` with `values` inserted. Note that `insert`
does not occur in-place: a new array is returned. If
`axis` is None, `out` is a flattened array.
See Also
--------
append : Append elements at the end of an array.
concatenate : Join a sequence of arrays along an existing axis.
delete : Delete elements from an array.
Notes
-----
Note that for higher dimensional inserts ``obj=0`` behaves very different
from ``obj=[0]`` just like ``arr[:,0,:] = values`` is different from
``arr[:,[0],:] = values``.
Examples
--------
>>> a = np.array([[1, 1], [2, 2], [3, 3]])
>>> a
array([[1, 1],
[2, 2],
[3, 3]])
>>> np.insert(a, 1, 5)
array([1, 5, 1, ..., 2, 3, 3])
>>> np.insert(a, 1, 5, axis=1)
array([[1, 5, 1],
[2, 5, 2],
[3, 5, 3]])
Difference between sequence and scalars:
>>> np.insert(a, [1], [[1],[2],[3]], axis=1)
array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3]])
>>> np.array_equal(np.insert(a, 1, [1, 2, 3], axis=1),
... np.insert(a, [1], [[1],[2],[3]], axis=1))
True
>>> b = a.flatten()
>>> b
array([1, 1, 2, 2, 3, 3])
>>> np.insert(b, [2, 2], [5, 6])
array([1, 1, 5, ..., 2, 3, 3])
>>> np.insert(b, slice(2, 4), [5, 6])
array([1, 1, 5, ..., 2, 3, 3])
>>> np.insert(b, [2, 2], [7.13, False]) # type casting
array([1, 1, 7, ..., 2, 3, 3])
>>> x = np.arange(8).reshape(2, 4)
>>> idx = (1, 3)
>>> np.insert(x, idx, 999, axis=1)
array([[ 0, 999, 1, 2, 999, 3],
[ 4, 999, 5, 6, 999, 7]])
"""
arr = np.asarray(arr)
ndim = arr.ndim
if axis is None:
if ndim != 1:
arr = arr.ravel()
# needed for np.matrix, which is still not 1d after being ravelled
ndim = arr.ndim
axis = ndim - 1
else:
axis = np.normalize_axis_index(axis, ndim)
slobj = [slice(None)]*ndim
N = arr.shape[axis]
newshape = list(arr.shape)
if isinstance(obj, slice):
# turn it into a range object
indices = np.arange(*obj.indices(N), dtype=np.dtype.int)
else:
# need to copy obj, because indices will be changed in-place
indices = np.array(obj).copy()
if indices.dtype == np.dtype.bool:
# See also delete
warnings.warn(
"in the future insert will treat boolean arrays and "
"array-likes as a boolean index instead of casting it to "
"integer", FutureWarning, stacklevel=2)
indices = indices.astype(np.dtype.int)
elif indices.ndim > 1:
raise ValueError(
"index array argument obj to insert must be one dimensional "
"or scalar")
if indices.size == 1:
index = indices.item()
if index < -N or index > N:
raise IndexError("index {} is out of bounds for axis {} with size {}".
format(obj, axis, N))
if (index < 0):
index += N
# There are some object array corner cases here, but we cannot avoid
# that:
values = np.array(values, copy=False, ndmin=arr.ndim, dtype=arr.dtype)
if indices.ndim == 0:
# broadcasting is very different here, since a[:,0,:] = ... behaves
# very different from a[:,[0],:] = ...! This changes values so that
# it works likes the second case. (here a[:,0:1,:])
values = np.moveaxis(values, 0, axis)
numnew = values.shape[axis]
newshape[axis] += numnew
new = np.empty(newshape, arr.dtype,)
slobj[axis] = slice(None, index)
new[tuple(slobj)] = arr[tuple(slobj)]
slobj[axis] = slice(index, index+numnew)
new[tuple(slobj)] = values
slobj[axis] = slice(index+numnew, None)
slobj2 = [slice(None)] * ndim
slobj2[axis] = slice(index, None)
new[tuple(slobj)] = arr[tuple(slobj2)]
return new
elif indices.size == 0 and not isinstance(obj, np.NDArray):
# Can safely cast the empty list to intp
indices = indices.astype(np.dtype.int)
indices[indices < 0] += N
numnew = len(indices)
#order = indices.argsort(kind='mergesort') # stable sort
order = np.argsort(indices)
indices[order] += np.arange(numnew)
newshape[axis] += numnew
old_mask = np.ones(newshape[axis], dtype=np.dtype.bool)
old_mask[indices] = False
new = np.empty(newshape, arr.dtype)
slobj2 = [slice(None)]*ndim
slobj[axis] = indices
slobj2[axis] = old_mask
new[tuple(slobj)] = values
new[tuple(slobj2)] = arr
return new

View File

@ -182,6 +182,10 @@ def getcolors(cs, alpha=None):
if isinstance(cs, (tuple, list, NDArray)):
if isinstance(cs[0], int):
colors.append(getcolor(cs, alpha))
else:
if isinstance(alpha, (tuple, list)):
for c, a in zip(cs, alpha):
colors.append(getcolor(c, a))
else:
for c in cs:
colors.append(getcolor(c, alpha))

View File

@ -0,0 +1,53 @@
package org.meteoinfo.math.sort;
import java.util.Arrays;
public class MergeSort {
/**
* Merge sort
* @param sourceArray Source array
* @return Sorted array
* @throws Exception
*/
public int[] sort(int[] sourceArray) throws Exception {
// arr 进行拷贝不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
if (arr.length < 2) {
return arr;
}
int middle = (int) Math.floor(arr.length / 2);
int[] left = Arrays.copyOfRange(arr, 0, middle);
int[] right = Arrays.copyOfRange(arr, middle, arr.length);
return merge(sort(left), sort(right));
}
protected int[] merge(int[] left, int[] right) {
int[] result = new int[left.length + right.length];
int i = 0;
while (left.length > 0 && right.length > 0) {
if (left[0] <= right[0]) {
result[i++] = left[0];
left = Arrays.copyOfRange(left, 1, left.length);
} else {
result[i++] = right[0];
right = Arrays.copyOfRange(right, 1, right.length);
}
}
while (left.length > 0) {
result[i++] = left[0];
left = Arrays.copyOfRange(left, 1, left.length);
}
while (right.length > 0) {
result[i++] = right[0];
right = Arrays.copyOfRange(right, 1, right.length);
}
return result;
}
}

View File

@ -45,7 +45,7 @@ import java.util.Comparator;
* always appear before S in the sorted list.
* <p>
* For speed of execution, we implement it without recursion. Instead,
* we requires an auxiliary array (stack) of storage, of length
* we require an auxiliary array (stack) of storage, of length
* 2 log<sub><small>2</small></sub> n. When a subarray has gotten down to size 7,
* we sort it by straight insertion.
*

View File

@ -305,8 +305,12 @@ public class ArrayBoolean extends Array {
}
public void setObject(Index i, Object value) {
if (value instanceof Integer) {
storage[i.currentElement()] = ((Integer) value == 1);
} else {
storage[i.currentElement()] = (Boolean) value;
}
}
// package private : mostly for iterators
public double getDouble(int index) {

View File

@ -275,8 +275,12 @@ public class ArrayDouble extends Array {
}
public void setObject(Index i, Object value) {
if (value instanceof Boolean) {
storageD[i.currentElement()] = ((Boolean) value) ? 1 : 0;
} else {
storageD[i.currentElement()] = ((Number) value).doubleValue();
}
}
// trusted, assumes that individual dimension lengths have been checked
public double getDouble(int index) {
@ -368,8 +372,12 @@ public class ArrayDouble extends Array {
}
public void setObject(int index, Object value) {
if (value instanceof Boolean) {
storageD[index] = ((Boolean) value) ? 1 : 0;
} else {
storageD[index] = ((Number) value).doubleValue();
}
}
/**
* Concrete implementation of Array specialized for doubles, rank 0.

View File

@ -298,8 +298,12 @@ public class ArrayInt extends Array {
}
public void setObject(Index i, Object value) {
if (value instanceof Boolean) {
storage[i.currentElement()] = ((Boolean) value) ? 1 : 0;
} else {
storage[i.currentElement()] = ((Number) value).intValue();
}
}
// package private : mostly for iterators
public double getDouble(int index) {
@ -397,8 +401,12 @@ public class ArrayInt extends Array {
}
public void setObject(int index, Object value) {
if (value instanceof Boolean) {
storage[index] = ((Boolean) value) ? 1 : 0;
} else {
storage[index] = ((Number) value).intValue();
}
}
/**
* Concrete implementation of Array specialized for ints, rank 0.

View File

@ -672,6 +672,18 @@ public class Index implements Cloneable {
return this;
}
/**
* Set the current element's index. General-rank case.
*
* @param index set current value to these values
* @return this, so you can use A.get(i.set(i))
* @throws ArrayIndexOutOfBoundsException if index.length != rank.
*/
public Index set(List<Integer> indexList) {
int[] index = indexList.stream().mapToInt(Integer::intValue).toArray();
return set(index);
}
/**
* set current element at dimension dim to v
*

View File

@ -1,6 +1,9 @@
package org.meteoinfo.ndarray;
import org.meteoinfo.ndarray.math.ArrayUtil;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
public class MixIterator implements IndexIterator {
@ -29,7 +32,21 @@ public class MixIterator implements IndexIterator {
if (range instanceof Range) {
shape[i] = ((Range) range).length();
} else {
shape[i] = ((List) range).size();
Array arr = (Array) range;
if (arr.getDataType() == DataType.BOOLEAN) {
List<Integer> tList = new ArrayList<>();
IndexIterator iter = arr.getIndexIterator();
int j = 0;
while (iter.hasNext()) {
if (iter.getBooleanNext()) {
tList.add(j);
}
j += 1;
}
arr = ArrayUtil.array_list(tList, DataType.INT);
this.ranges.set(i, arr);
}
shape[i] = (int) arr.getSize();
}
i += 1;
}
@ -297,9 +314,9 @@ public class MixIterator implements IndexIterator {
int c;
for (Object range : this.ranges) {
if (range instanceof Range) {
c = ((Range)range).elementNC(rangeCounter[i]);
c = ((Range) range).elementNC(rangeCounter[i]);
} else {
c = ((List<Integer>)range).get(rangeCounter[i]);
c = ((Array) range).getInt(rangeCounter[i]);
}
currentCounter[i] = c;
i += 1;

View File

@ -6022,11 +6022,11 @@ public class ArrayMath {
public static Array setSection(Array a, List<Range> ranges, Array v) throws InvalidRangeException {
Array r = a.section(ranges);
IndexIterator iter = r.getIndexIterator();
if (r.getSize() != v.getSize()) {
/*if (r.getSize() != v.getSize()) {
if (r.getShape() != v.getShape()) {
v = ArrayUtil.broadcast(v, r.getShape());
}
}
}*/
Index index = v.getIndex();
while (iter.hasNext()) {
iter.setObjectNext(v.getObject(index));
@ -6207,19 +6207,35 @@ public class ArrayMath {
* @param v Number value
* @return Result array
*/
public static Array setSection_List(Array a, List<List<Integer>> ranges, Number v) {
public static Array setSection_List(Array a, List<Array> ranges, Number v) {
//Array r = copy(a);
int n = a.getRank();
int[] count = new int[n];
Index index = a.getIndex();
int m = ranges.get(0).size();
int m = (int) ranges.get(0).getSize();
if (ranges.get(0).getDataType() == DataType.BOOLEAN) {
for (int i = 0; i < m; i++) {
boolean bool = true;
for (int j = 0; j < n; j++) {
if (!ranges.get(j).getBoolean(i)) {
bool = false;
break;
}
}
if (bool) {
a.setObject(index, v);
}
index.incr();
}
} else {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
count[j] = ranges.get(j).get(i);
count[j] = ranges.get(j).getInt(i);
}
index.set(count);
a.setObject(index, v);
}
}
return a;
}
@ -6232,21 +6248,38 @@ public class ArrayMath {
* @param v Array value
* @return Result array
*/
public static Array setSection_List(Array a, List<List<Integer>> ranges, Array v) {
public static Array setSection_List(Array a, List<Array> ranges, Array v) {
//Array r = copy(a);
int n = a.getRank();
int[] count = new int[n];
Index index = a.getIndex();
Index vIndex = v.getIndex();
int m = ranges.get(0).size();
int m = (int) ranges.get(0).getSize();
if (ranges.get(0).getDataType() == DataType.BOOLEAN) {
for (int i = 0; i < m; i++) {
boolean bool = true;
for (int j = 0; j < n; j++) {
if (!ranges.get(j).getBoolean(i)) {
bool = false;
break;
}
}
if (bool) {
a.setObject(index, v.getObject(vIndex));
vIndex.incr();
}
index.incr();
}
} else {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
count[j] = ranges.get(j).get(i);
count[j] = ranges.get(j).getInt(i);
}
index.set(count);
a.setObject(index, v.getObject(vIndex));
vIndex.incr();
}
}
return a;
}

View File

@ -1633,6 +1633,12 @@ public class ArrayUtil {
StringBuilder sbuff = new StringBuilder();
sbuff.append("array(");
int ndim = a.getRank();
if (ndim == 0) {
sbuff.append(a.getObject(0));
sbuff.append(")");
return sbuff.toString();
}
if (ndim > 1) {
for (int i = 0; i < ndim - 1; i++)
sbuff.append("[");