public NDArray this[string slice] { get { return(this[Slice.ParseSlices(slice)]); } set { throw new NotImplementedException("slice data set is not implemented for types less NDArray's."); } }
protected void SetIndices(object[] indicesObjects, NDArray values) { var indicesLen = indicesObjects.Length; if (indicesLen == 1) { switch (indicesObjects[0]) { case NDArray nd: SetIndices(this, new NDArray[] {nd}, values); return; case int i: Storage.SetData(values, i); return; case bool boolean: if (boolean == false) return; //do nothing SetData(values); return; // np.expand_dims(this, 0); //equivalent to [np.newaxis] case int[] coords: SetData(values, coords); return; case NDArray[] nds: this[nds] = values; return; case object[] objs: this[objs] = values; return; case string slicesStr: new NDArray(Storage.GetView(Slice.ParseSlices(slicesStr))).SetData(values); return; case null: throw new ArgumentNullException($"The 1th dimension in given indices is null."); //no default } } int ints = 0; int bools = 0; for (var i = 0; i < indicesObjects.Length; i++) { switch (indicesObjects[i]) { case NDArray _: case int[] _: goto _NDArrayFound; case int _: ints++; continue; case bool @bool: bools++; continue; case string _: case Slice _: continue; case null: throw new ArgumentNullException($"The {i}th dimension in given indices is null."); default: throw new ArgumentException($"Unsupported indexing type: '{(indicesObjects[i]?.GetType()?.Name ?? "null")}'"); } } //handle all ints if (ints == indicesLen) { Storage.SetData(values, indicesObjects.Cast<int>().ToArray()); return; } //handle all booleans if (bools == indicesLen) { this[np.array(indicesObjects.Cast<bool>().ToArray(), false).MakeGeneric<bool>()] = values; return; } Slice[] slices; //handle regular slices try { slices = indicesObjects.Select(x => { switch (x) { case Slice o: return o; case int o: return Slice.Index(o); case string o: return new Slice(o); case bool o: return o ? Slice.NewAxis : throw new NumSharpException("false bool detected"); //TODO: verify this case IConvertible o: return Slice.Index((int)o.ToInt32(CultureInfo.InvariantCulture)); default: throw new ArgumentException($"Unsupported slice type: '{(x?.GetType()?.Name ?? "null")}'"); } }).ToArray(); } catch (NumSharpException e) when (e.Message.Contains("false bool detected")) { //handle rare case of false bool return; } new NDArray(Storage.GetView(slices)).SetData(values); //handle complex ndarrays indexing _NDArrayFound: var @this = this; var indices = new List<NDArray>(); bool foundNewAxis = false; int countNewAxes = 0; //handle ndarray indexing bool hasCustomExpandedSlice = false; //use for premature slicing detection for (int i = 0; i < indicesLen; i++) { var idx = indicesObjects[i]; _recuse: switch (idx) { case Slice o: if (o.IsEllipsis) { indicesObjects = ExpandEllipsis(indicesObjects, @this.ndim).ToArray(); //TODO: i think we need to set here indicesLen = indicesObjects.Length continue; } if (o.IsNewAxis) { //TODO: whats the approach to handling a newaxis in setter, findout. countNewAxes++; foundNewAxis = true; continue; } hasCustomExpandedSlice = true; indices.Add(GetIndicesFromSlice(@this.Shape.dimensions, o, i - countNewAxes)); continue; case int o: indices.Add(NDArray.Scalar<int>(o)); continue; case string o: indicesObjects[i] = idx = new Slice(o); goto _recuse; case bool o: if (o) { indicesObjects[i] = idx = Slice.NewAxis; goto _recuse; } else return; //false bool causes nullification of return. case IConvertible o: indices.Add(NDArray.Scalar<int>(o.ToInt32(CultureInfo.InvariantCulture))); continue; case int[] o: indices.Add(np.array(o, copy: false)); //we dont copy, pinning will be freed automatically after we done indexing. continue; case NDArray nd: if (nd.typecode == NPTypeCode.Boolean) { //TODO: mask only specific axis??? find a unit test to check it against. throw new Exception("if (nd.typecode == NPTypeCode.Boolean)"); } indices.Add(nd); continue; default: throw new ArgumentException($"Unsupported slice type: '{(idx?.GetType()?.Name ?? "null")}'"); } } NDArray[] indicesArray = indices.ToArray(); //handle premature slicing when the shapes cant be broadcasted together if (hasCustomExpandedSlice && !np.are_broadcastable(indicesArray)) { var ndim = indicesObjects.Length; var prematureSlices = new Slice[ndim]; var dims = @this.shape; for (int i = 0; i < ndim; i++) { if (indicesObjects[i] is Slice slice) { prematureSlices[i] = slice; //todo: we might need this in the future indicesObjects[i] = Slice.All; } else { prematureSlices[i] = Slice.All; } } @this = @this[prematureSlices]; //updated premature axes dims = @this.shape; for (int i = 0; i < ndim; i++) { if (prematureSlices[i] != Slice.All) { indicesArray[i] = GetIndicesFromSlice(dims, Slice.All, i); } } } //TODO: we can use a slice as null indice instead of expanding it, then we use PrepareIndexGetters to actually simulate that. SetIndices(@this, indicesArray, values); //TODO: this is valid code for getter, we need to impl a similar technique before passing @this. //if (foundNewAxis) //{ // //TODO: This is not the behavior when setting with new axis, is it even possible? // var targettedAxis = indices.Count - 1; // var axisOffset = this.ndim - targettedAxis; // var retShape = ret.Shape; // for (int i = 0; i < indicesLen; i++) // { // if (!(indicesObjects[i] is Slice slc) || !slc.IsNewAxis) // continue; // // var axis = Math.Max(0, Math.Min(i - axisOffset, ret.ndim)); // retShape = retShape.ExpandDimension(axis); // } // // ret = ret.reshape(retShape); //} // //return ret; }
public ViewStorage(IStorage dataStorage, string slice_notation) : this(dataStorage, Slice.ParseSlices(slice_notation)) { }