public ViewStorage(IStorage dataStorage, params Slice[] slices) { if (dataStorage == null) { throw new ArgumentException("dataStorage must not be null"); } if (slices == null) { throw new ArgumentException("slices must not be null"); } if (slices.Length == 0) { // if now slices are given the view returns all of all dimensions slices = new Slice[dataStorage.Shape.NDim]; for (int dim = 0; dim < dataStorage.Shape.NDim; dim++) { slices[dim] = Slice.All(); } } _data = (IStorage)dataStorage; //all types must inheriet IInternalStorage _slices = slices; Engine = dataStorage.Engine; EnsureValidSlicingDefinitions(); }
private void EnsureValidSlicingDefinitions() { // we need to be working with the original shape here because Slicing changes the own shape! var shape = _data.Shape; // we need at least one slice per dimension in order to correctly handle multi-dimensional arrays, if not given, extend by Slice.All() which returns the whole dimension var temp_slices = _slices; if (_slices == null) { temp_slices = new Slice[0]; } _slices = new Slice[shape.NDim]; for (int dim = 0; dim < shape.NDim; dim++) { if (temp_slices.Length > dim) { _slices[dim] = temp_slices[dim] ?? Slice.All(); // <-- allow to pass null for Slice.All() } else { _slices[dim] = Slice.All(); } } for (int dim = 0; dim < shape.NDim; dim++) { var slice = _slices[dim]; var size = shape.Dimensions[dim]; if (slice.IsIndex) { // special case: reduce this dimension if (slice.Start < 0 || slice.Start >= size) { throw new IndexOutOfRangeException($"Index {slice.Start} is out of bounds for axis {dim} with size {size}"); } } slice.Start = Math.Max(0, slice.Start ?? 0); slice.Stop = Math.Min(size, slice.Stop ?? size); } // internal shape contains axis with only 1 element that will be reduced in public shape. internal_shape = _data.Shape.Slice(_slices, reduce: false); Shape = _data.Shape.Slice(_slices, reduce: true); }