@@ -142,27 +142,31 @@ public static int ComputeSize(Object o)
142142 if ( t . IsArray )
143143 {
144144 int size = 0 ;
145+ var array = ( Array ) o ;
145146
146- if ( t . HasElementType && t . GetElementType ( ) . IsPrimitive )
147+ // Rectangular multi-dimensional array: total elements * element size
148+ if ( array . Rank > 1 && t . HasElementType && t . GetElementType ( ) . IsPrimitive )
149+ {
150+ size = array . Length * ( int ) sizes [ t . GetElementType ( ) ] ;
151+ }
152+ else if ( t . HasElementType && t . GetElementType ( ) . IsPrimitive )
147153 {
148- var array = ( Array ) o ;
149154 if ( array . Length > 0 )
150155 {
151- IEnumerator i = ( ( Array ) o ) . GetEnumerator ( ) ;
156+ IEnumerator i = array . GetEnumerator ( ) ;
152157 i . MoveNext ( ) ;
153158
154159 size += array . Length * ComputeSize ( i . Current ) ;
155160 }
156161 }
157162 else
158163 {
159- for ( IEnumerator i = ( ( Array ) o ) . GetEnumerator ( ) ; i . MoveNext ( ) ; )
164+ for ( IEnumerator i = array . GetEnumerator ( ) ; i . MoveNext ( ) ; )
160165 {
161166 size += ComputeSize ( i . Current ) ;
162167 }
163168 }
164169
165- //return size;
166170 result = size ;
167171 }
168172 else if ( t == typeof ( String ) )
@@ -444,27 +448,23 @@ public static Type GetBaseClass(Object o)
444448
445449 if ( o . GetType ( ) . IsArray )
446450 {
447- // if 'o' is a jagged array of 2 or more than 2 dimensions
448- // with all dimensions of type premitive,
449- // check for the type of last dimension.
450- if ( o . GetType ( ) . ToString ( ) . StartsWith ( "System.Array" ) )
451+ // Rectangular multi-dimensional array (e.g., float[,,])
452+ if ( ( ( Array ) o ) . Rank > 1 )
451453 {
452- return GetBaseClass ( ( ( Array ) o ) . GetValue ( 0 ) ) ;
454+ return o . GetType ( ) . GetElementType ( ) ;
453455 }
454- // if 'o' is a multidimension array of any dimension
455- // or a jagged array of 2 or more than 2 dimension having
456- // first dimension of non-primitive type,
457- // return the type of 'o' directly without dimension brackets.
458- else
456+ // Jagged array of arrays (e.g., Array[] of Array[] of float[])
457+ if ( o . GetType ( ) . ToString ( ) . StartsWith ( "System.Array" ) )
459458 {
460- return Type . GetType ( o . ToString ( ) . Substring ( 0 , o . ToString ( ) . IndexOf ( "[" ) ) ) ;
459+ return GetBaseClass ( ( ( Array ) o ) . GetValue ( 0 ) ) ;
461460 }
461+ // 1D or jagged typed array - strip all bracket notation to get base type
462+ return Type . GetType ( o . ToString ( ) . Substring ( 0 , o . ToString ( ) . IndexOf ( "[" ) ) ) ;
462463 }
463464 else
464465 {
465466 return o . GetType ( ) ;
466467 }
467-
468468 }
469469
470470 /// <summary>This routine returns the base class of an object with the dimension indication
@@ -582,19 +582,27 @@ public static Object Flatten(Object input)
582582 protected internal static int DoFlatten ( Object input , Array output , int offset )
583583 {
584584 int result = 0 ;
585+ var array = ( Array ) input ;
586+
587+ // Rectangular multi-dimensional array: use Buffer.BlockCopy for efficiency
588+ if ( array . Rank > 1 && array . GetType ( ) . GetElementType ( ) . IsPrimitive )
589+ {
590+ int elementSize = ( int ) sizes [ array . GetType ( ) . GetElementType ( ) ] ;
591+ Buffer . BlockCopy ( array , 0 , output , offset * elementSize , array . Length * elementSize ) ;
592+ return array . Length ;
593+ }
585594
586595 if ( IsArrayOfArrays ( input ) )
587596 {
588- int i = offset ;
589- for ( IEnumerator e = ( ( Array ) input ) . GetEnumerator ( ) ; e . MoveNext ( ) ; )
597+ for ( IEnumerator e = array . GetEnumerator ( ) ; e . MoveNext ( ) ; )
590598 {
591599 Object a = e . Current ;
592600 result += DoFlatten ( a , output , offset + result ) ;
593601 }
594602 }
595603 else if ( input . GetType ( ) . IsArray )
596604 {
597- IEnumerator e = ( ( Array ) input ) . GetEnumerator ( ) ;
605+ IEnumerator e = array . GetEnumerator ( ) ;
598606 for ( int i = offset ; e . MoveNext ( ) ; ++ i )
599607 {
600608 output . SetValue ( e . Current , i ) ;
@@ -643,19 +651,13 @@ public static Array Curl(Array input, int[] dimens)
643651
644652 for ( IEnumerator i = input . GetEnumerator ( ) ; i . MoveNext ( ) && NextIndex ( index , dimens ) ; )
645653 {
646- //NewInstance call creates a jagged array. So we cannot set the value using Array.SetValue
647- //as it works for multi-dimensional arrays and not for jagged
648- //newArray.SetValue(i.Current, index);
649-
650654 Array tarr = newArray ;
651655 for ( int i2 = 0 ; i2 < index . Length - 1 ; i2 ++ )
652656 {
653657 tarr = ( Array ) tarr . GetValue ( index [ i2 ] ) ;
654658 }
655659 tarr . SetValue ( i . Current , index [ index . Length - 1 ] ) ;
656660 }
657- //int offset = 0;
658- //DoCurl(input, newArray, dimens, offset);
659661 return newArray ;
660662 }
661663 /// <summary>
@@ -791,22 +793,26 @@ public static Array NewInstance(Type cl, int[] dims, int dim)
791793
792794 return a ;
793795 }
794- /*
795- Array o = Array.CreateInstance(cl, dims);
796- if(o == null)
796+ }
797+
798+ /// <summary>Create a rectangular (multi-dimensional) array with a single allocation.
799+ /// For 1D arrays, returns a simple typed array. For 2D+, returns e.g. float[,] or float[,,].
800+ /// This is more efficient than jagged arrays for image data.</summary>
801+ /// <param name="cl">The element type.</param>
802+ /// <param name="dims">The dimensions.</param>
803+ public static Array NewRectangularInstance ( Type cl , int [ ] dims )
804+ {
805+ if ( dims . Length == 0 )
797806 {
798- System.String desc = cl + "[";
799- System.String comma = "";
800- for(int i = 0; i < dims.Length; i += 1)
801- {
802- desc += comma + dims[i];
803- comma = ",";
804- }
805- desc += "]";
806- throw new System.OutOfMemoryException("Unable to allocate array: " + desc);
807+ dims = new int [ ] { 1 } ;
807808 }
808- return o;
809- */
809+
810+ if ( dims . Length == 1 )
811+ {
812+ return NewInstance ( cl , dims [ 0 ] ) ;
813+ }
814+
815+ return Array . CreateInstance ( cl , dims ) ;
810816 }
811817
812818
@@ -869,6 +875,27 @@ public static bool ArrayEquals(Object x, Object y, double tolf, double told)
869875
870876 if ( xClass != yClass )
871877 {
878+ // Allow comparing jagged vs rectangular arrays with the same base type and dimensions
879+ if ( x is Array xa && y is Array ya )
880+ {
881+ Type xBase = GetBaseClass ( x ) ;
882+ Type yBase = GetBaseClass ( y ) ;
883+ int [ ] xDims = GetDimensions ( x ) ;
884+ int [ ] yDims = GetDimensions ( y ) ;
885+ if ( xBase == yBase && xDims . Length == yDims . Length )
886+ {
887+ bool sameDims = true ;
888+ for ( int i = 0 ; i < xDims . Length ; i ++ )
889+ if ( xDims [ i ] != yDims [ i ] ) { sameDims = false ; break ; }
890+ if ( sameDims && xBase . IsPrimitive )
891+ {
892+ // Flatten both and compare bytes
893+ Object fx = Flatten ( x ) ;
894+ Object fy = Flatten ( y ) ;
895+ return ArrayEquals ( fx , fy , tolf , told ) ;
896+ }
897+ }
898+ }
872899 return false ;
873900 }
874901
0 commit comments