Skip to content

Commit c289bc7

Browse files
committed
Shape: Added 1D optimized Shape.GetOffset
1 parent 088103a commit c289bc7

File tree

1 file changed

+197
-1
lines changed

1 file changed

+197
-1
lines changed

src/NumSharp.Core/View/Shape.cs

Lines changed: 197 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ public int GetOffset(params int[] indices)
450450
}
451451

452452
var orig_strides = vi.OriginalShape.strides;
453-
var orig_dims = vi.OriginalShape.dimensions;
453+
//var orig_dims = vi.OriginalShape.dimensions;
454454
offset = 0;
455455
unchecked
456456
{
@@ -485,6 +485,104 @@ public int GetOffset(params int[] indices)
485485
return vi.ParentShape.GetOffset(parent_coords1);
486486
}
487487

488+
/// <summary>
489+
/// Get offset index out of coordinate indices.
490+
/// </summary>
491+
/// <param name="index">The coordinates to turn into linear offset</param>
492+
/// <returns>The index in the memory block that refers to a specific value.</returns>
493+
/// <remarks>Handles sliced indices and broadcasting</remarks>
494+
[MethodImpl((MethodImplOptions)768)]
495+
internal int GetOffset_1D(int index)
496+
{
497+
int offset;
498+
if (!IsSliced)
499+
{
500+
if (dimensions.Length == 0)
501+
return index;
502+
503+
offset = 0;
504+
unchecked
505+
{
506+
offset += strides[0] * index;
507+
}
508+
509+
if (IsBroadcasted)
510+
return offset % BroadcastInfo.OriginalShape.size;
511+
512+
return offset;
513+
}
514+
515+
//if both sliced and broadcasted
516+
if (IsBroadcasted)
517+
return GetOffset_broadcasted_1D(index);
518+
519+
// we are dealing with a slice
520+
521+
var vi = ViewInfo;
522+
if (IsRecursive && vi.Slices == null)
523+
{
524+
// we are dealing with an unsliced recursively reshaped slice
525+
offset = GetOffset_IgnoreViewInfo(index);
526+
var parent_coords = vi.ParentShape.GetCoordinates(offset, ignore_view_info: true);
527+
return vi.ParentShape.GetOffset(parent_coords);
528+
}
529+
530+
var coords = new List<int>(1) {index};
531+
if (vi.UnreducedShape.IsScalar && index == 0 && !IsRecursive)
532+
return 0;
533+
if (1 > vi.UnreducedShape.dimensions.Length)
534+
throw new ArgumentOutOfRangeException(nameof(index), $"select has too many coordinates for this shape");
535+
var orig_ndim = vi.OriginalShape.NDim;
536+
if (orig_ndim > NDim && orig_ndim > 1)
537+
{
538+
// fill in reduced dimensions in the provided coordinates
539+
for (int i = 0; i < vi.OriginalShape.NDim; i++)
540+
{
541+
var slice = ViewInfo.Slices[i];
542+
if (slice.IsIndex)
543+
coords.Insert(i, 0);
544+
if (coords.Count == orig_ndim)
545+
break;
546+
}
547+
}
548+
549+
var orig_strides = vi.OriginalShape.strides;
550+
//var orig_dims = vi.OriginalShape.dimensions;
551+
offset = 0;
552+
unchecked
553+
{
554+
for (int i = 0; i < coords.Count; i++)
555+
{
556+
// note: we can refrain from bounds checking here, because we should not allow negative indices at all, this should be checked higher up though.
557+
//var coord = coords[i];
558+
//var dim = orig_dims[i];
559+
//if (coord < -dim || coord >= dim)
560+
// throw new ArgumentException($"index {coord} is out of bounds for axis {i} with a size of {dim}");
561+
//if (coord < 0)
562+
// coord = dim + coord;
563+
if (vi.Slices.Length <= i)
564+
{
565+
offset += orig_strides[i] * coords[i];
566+
continue;
567+
}
568+
569+
var slice = vi.Slices[i];
570+
var start = slice.Start;
571+
if (slice.IsIndex)
572+
offset += orig_strides[i] * start; // the coord is irrelevant for index-slices (they are reduced dimensions)
573+
else
574+
offset += orig_strides[i] * (start + coords[i] * slice.Step);
575+
}
576+
}
577+
578+
if (!IsRecursive)
579+
return offset;
580+
// we are dealing with a sliced recursively reshaped slice
581+
var parent_coords1 = vi.ParentShape.GetCoordinates(offset, ignore_view_info: true);
582+
return vi.ParentShape.GetOffset(parent_coords1);
583+
}
584+
585+
488586
/// <summary>
489587
/// Calculate the offset in an unsliced shape. If the shape is sliced, ignore the ViewInfo
490588
/// Note: to be used only inside of GetOffset()
@@ -606,6 +704,104 @@ private int GetOffset_broadcasted(params int[] indices)
606704
return vi.ParentShape.GetOffset(parent_coords1);
607705
}
608706

707+
/// <summary>
708+
/// Get offset index out of coordinate indices.
709+
/// </summary>
710+
/// <param name="index">The coordinates to turn into linear offset</param>
711+
/// <returns>The index in the memory block that refers to a specific value.</returns>
712+
/// <remarks>Handles sliced indices and broadcasting</remarks>
713+
[MethodImpl((MethodImplOptions)768)]
714+
private int GetOffset_broadcasted_1D(int index)
715+
{
716+
int offset;
717+
var vi = ViewInfo;
718+
var bi = BroadcastInfo;
719+
if (IsRecursive && vi.Slices == null)
720+
{
721+
// we are dealing with an unsliced recursively reshaped slice
722+
offset = GetOffset_IgnoreViewInfo(index);
723+
var parent_coords = vi.ParentShape.GetCoordinates(offset, ignore_view_info: true);
724+
return vi.ParentShape.GetOffset(parent_coords);
725+
}
726+
727+
var coords = new List<int>(1) {index};
728+
if (vi.UnreducedShape.IsScalar && index == 0 && !IsRecursive)
729+
return 0;
730+
if (1 > vi.UnreducedShape.dimensions.Length)
731+
throw new ArgumentOutOfRangeException(nameof(index), $"select has too many coordinates for this shape");
732+
var orig_ndim = vi.OriginalShape.NDim;
733+
if (orig_ndim > NDim && orig_ndim > 1)
734+
{
735+
// fill in reduced dimensions in the provided coordinates
736+
for (int i = 0; i < vi.OriginalShape.NDim; i++)
737+
{
738+
var slice = ViewInfo.Slices[i];
739+
if (slice.IsIndex)
740+
coords.Insert(i, 0);
741+
if (coords.Count == orig_ndim)
742+
break;
743+
}
744+
}
745+
746+
var orig_strides = vi.OriginalShape.strides;
747+
Shape unreducedBroadcasted;
748+
if (!bi.UnbroadcastShape.HasValue)
749+
{
750+
if (bi.OriginalShape.IsScalar)
751+
{
752+
unreducedBroadcasted = vi.OriginalShape.Clone(true, false, false);
753+
for (int i = 0; i < unreducedBroadcasted.NDim; i++)
754+
{
755+
unreducedBroadcasted.dimensions[i] = 1;
756+
unreducedBroadcasted.strides[i] = 0;
757+
}
758+
}
759+
else
760+
{
761+
unreducedBroadcasted = vi.OriginalShape.Clone(true, false, false);
762+
for (int i = Math.Abs(vi.OriginalShape.NDim - NDim), j = 0; i < unreducedBroadcasted.NDim; i++, j++)
763+
{
764+
if (strides[j] == 0)
765+
{
766+
unreducedBroadcasted.dimensions[i] = 1;
767+
unreducedBroadcasted.strides[i] = 0;
768+
}
769+
}
770+
}
771+
772+
bi.UnbroadcastShape = unreducedBroadcasted;
773+
}
774+
else
775+
unreducedBroadcasted = bi.UnbroadcastShape.Value;
776+
777+
orig_strides = unreducedBroadcasted.strides;
778+
offset = 0;
779+
unchecked
780+
{
781+
for (int i = 0; i < coords.Count; i++)
782+
{
783+
if (vi.Slices.Length <= i)
784+
{
785+
offset += orig_strides[i] * coords[i];
786+
continue;
787+
}
788+
789+
var slice = vi.Slices[i];
790+
var start = slice.Start;
791+
if (slice.IsIndex)
792+
offset += orig_strides[i] * start; // the coord is irrelevant for index-slices (they are reduced dimensions)
793+
else
794+
offset += orig_strides[i] * (start + coords[i] * slice.Step);
795+
}
796+
}
797+
798+
if (!IsRecursive)
799+
return offset;
800+
// we are dealing with a sliced recursively reshaped slice
801+
var parent_coords1 = vi.ParentShape.GetCoordinates(offset, ignore_view_info: true);
802+
return vi.ParentShape.GetOffset(parent_coords1);
803+
}
804+
609805

610806
/// <summary>
611807
/// Gets the shape based on given <see cref="indicies"/> and the index offset (C-Contiguous) inside the current storage.

0 commit comments

Comments
 (0)