📄 arrays.hhf
字号:
?_i_ := _i_ - 1; #endwhile // Compute index into the destination array. // Note: to properly transpose, we need to // swap the zero index with the _xpos_ index. // // Begin by checking to see if the highest dimension // is _xpos_. If so, use loop counter zero as the // index value. If not, use loop counter n (n=arity-1) // as the index value. ?_i_ := @Elements( _destArray_.dopeVector ) - 1; #if( _i_ = _xpos_ ) mov( (type dword [esp] ), edi ); #else mov ( (type dword [esp + _i_*4] ), edi ); #endif // Okay, for all dimensions except _xpos_ and zero, // compute the row-major offset into the array. // Swap indicies zero and _xpos_. Note that _xpos_ // may have been handled above. ?_i_ := _i_ - 1; #while( _i_ > 0 ) intmul( _destArray_.dopeVector[_i_*4], edi ); #if( _i_ = _xpos_ ) add( [esp], edi ); #else add( [esp+_i_*4], edi ); #endif ?_i_ := _i_ - 1; #endwhile intmul( _destArray_.dopeVector[_xpos_*4], edi ); add( [esp + _xpos_*4], edi ); // Okay, EDI is the index into the destination array. // ESI contains the pointer at the current source // element. Copy the data from the source array to // the destination array. #if( _sSize_ = 1 ) mov( [esi], al ); mov( al, [ebx+edi] ); inc( esi ); #elseif( _sSize_ = 2 ) mov( [esi], ax ); mov( ax, [ebx+edi*2] ); add( 2, esi ); #elseif( _sSize_ = 4 ) mov( [esi], eax ); mov( eax, [ebx+edi*4] ); add( 4, esi ); #else mov( [esi], eax ); mov( [esi+4], edx ); mov( eax, [ebx+edi*8] ); mov( edx, [ebx+edi*8+4] ); add( 8, esi ); #endif ?_i_ := 0; #while( _i_ < @Elements( _destArray_.dopeVector )) inc( (type dword [esp + _i_ * 4 ])); endwhile; ?_i_ := _i_ + 1; #endwhile // Remove loop control variables from the stack. add( @Elements( _srcArray_.dopeVector ) * 4, esp ); // Remove registers from the stack: pop( edi ); pop( esi ); pop( ebx ); pop( eax ); #endif #endif // Handle the case where the source array is static // and the destination array is dynamic. #elseif ( !array.isItDynamic( _srcArray_ ) & array.isItDynamic( _destArray_ ) ) ?_srcd_ := @dim( _srcArray_ ); ?_sSize_ := @ElementSize( _srcArray_ ); ?_dSize_ := @Size( _destArray_.elementType ); #if ( _sSize_ <> 1 & _sSize_ <> 2 & _sSize_ <> 4 & _sSize_ <> 8 & _sSize_ <> _dSize_ ) #error ( "array.transpose: " nl "Can only handle arrays with 1, 2, 4, or 8 byte elements" ); #elseif ( @elements( _destArray_.dopeVector ) <= _xpos_ | @arity( _srcArray_ ) <= _xpos_ | @elements( _destArray_.dopeVector ) <> @arity( _srcArray_ ) ) #error ( "array.transpose:" nl "Arrays must have at least " + string( _xpos_ ) + " dimensions" nl "and they must have the same number of dimensions" ); #else // We must check for proper array shapes at run-time // since we don't know the dest array dimensions // until then. if (#{ ?_i_ := 1; #while( _i_ < @arity( _srcArray_ )) #if( _i_ <> _xpos_ ) cmp ( _destArray_.dopeVector[ _i_ * 4 ], _srcd_[_i_] ); jne true; #endif ?_i_ := _i_ + 1; #endwhile cmp ( _destArray_.dopeVector[0], _srcd_[_xpos_] ); jne true; cmp ( _destArray_.dopeVector[_xpos_*4], _srcd_[0] ); je false; }#) then raise( ex.ArrayShapeViolation ); endif; // Optimize the most common case (transposing // a two-dim array or the last two dimensions // of an array). #if( _xpos_ = 1 ) push( eax ); push( ebx ); push( ecx ); push( edx ); push( esi ); push( edi ); // Note: assume that the src and dest array // sizes are the same: lea( ebx, _srcArray_ ); lea( ecx, [ebx + @size( _srcArray_ )] ); push( ecx ); mov( _destArray_.dataPtr, ecx ); sub( _srcd_[0] * _srcd_[1] * _sSize_, ecx ); while( ebx < [esp] ) do add( _srcd_[0] * _srcd_[1] * _sSize_, ecx ); for( mov(0, esi ); esi < _srcd_[0]; inc( esi )) do for ( mov( 0, edi ); edi < _srcd_[_xpos_]; inc( edi ) ) do #if( _sSize_ = 1 ) intmul( _srcd_[0], edi, edx ); add( esi, edx ); mov( [ebx], al ); mov( al, [ecx+edx] ); inc( ebx ); #elseif( _sSize_ = 2 ) intmul( _srcd_[0], edi, edx ); add( esi, edx ); mov( [ebx], ax ); mov( ax, [ecx+edx*2] ); add( 2, ebx ); #elseif( _sSize_ = 4 ) intmul( _srcd_[0], edi, edx ); add( esi, edx ); mov( [ebx], eax ); mov( eax, [ecx+edx*4] ); add( 4, ebx ); #else intmul( _srcd_[0], edi, edx ); add( esi, edx ); mov( [ebx], eax ); mov( eax, [ecx+edx*8] ); mov( [ebx+4], eax ); mov( eax, [ecx+edx*8+4] ); add( 8, ebx ); #endif endfor; endfor; endwhile; add( 4, esp ); pop( edi ); pop( esi ); pop( edx ); pop( ecx ); pop( ebx ); pop( eax ); // Okay, handle the case where we are not transposing // the last two dimensions of the array. This one is // ugly and less efficient (hence the special case // above). #else push( eax ); push( ebx ); push( esi ); push( edi ); // Make room for a set of loop control variables // on the stack: sub( @arity( _srcArray_ ) * 4, esp ); // Initialize array base pointers. mov( _destArray_.dataPtr, ebx ); lea( esi, _srcArray_ ); // Emit the for loops that will do the // transposition. ?_i_ := @arity( _srcArray_ ); #while( _i_ > 0 ) ?_offset_ := ( _i_ - 1 ) * 4; for ( mov(0, (type dword [esp+_offset_])); (type dword [esp+_offset_]) < _srcd_[_i_ - 1]; inc( (type dword [esp+_offset_])) ) do ?_i_ := _i_ - 1; #endwhile // Compute index into the source array. // Note: to properly transpose, we need to // swap the zero index with the _xpos_ index. // // Begin by checking to see if the highest dimension // is _xpos_. If so, use loop counter zero as the // index value. If not, use loop counter n (n=arity-1) // as the index value. ?_i_ := @arity( _srcArray_ ) - 1; #if( _i_ = _xpos_ ) mov( (type dword [esp] ), edi ); #else mov ( (type dword [esp + _i_*4] ), edi ); #endif // Okay, for all dimensions except _xpos_ and zero, // compute the row-major offset into the array. // Swap indicies zero and _xpos_. Note that _xpos_ // may have been handled above. ?_i_ := _i_ - 1; #while( _i_ > 0 ) array.mulbyConst ( @dim( _srcArray_ )[_i_], edi ); #if( _i_ = _xpos_ ) add( [esp], edi ); #else add( [esp+_i_*4], edi ); #endif ?_i_ := _i_ - 1; #endwhile array.mulbyConst( _srcd_[_xpos_], edi ); add( [esp + _xpos_*4], edi ); // Okay, EDI is the index into the destination array. // ESI contains the pointer at the current source // element. Copy the data from the source array to // the destination array. #if( _sSize_ = 1 ) mov( [esi], al ); mov( al, [ebx+edi] ); inc( esi ); #elseif( _sSize_ = 2 ) mov( [esi], ax ); mov( ax, [ebx+edi*2] ); add( 2, esi ); #elseif( _sSize_ = 4 ) mov( [esi], eax ); mov( eax, [ebx+edi*4] ); add( 4, esi ); #else mov( [esi], eax ); mov( [esi+4], edx ); mov( eax, [ebx+edi*8] ); mov( edx, [ebx+edi*8+4] ); add( 8, esi ); #endif ?_i_ := 0; #while( _i_ < @arity( _srcArray_ )) endfor; ?_i_ := _i_ + 1; #endwhile // Remove loop control variables from the stack. add( @arity( _srcArray_ ) * 4, esp ); // Remove registers from the stack: pop( edi ); pop( esi ); pop( ebx ); pop( eax ); #endif #endif // Handle the case where the source array is dynamic and // the destination array is static. #elseif ( array.isItDynamic( _srcArray_ ) & !array.isItDynamic( _destArray_ ) ) ?_dstd_ := @dim( _destArray_ ); ?_dSize_ := @ElementSize( _destArray_ ); ?_sSize_ := @Size( _srcArray_.elementType ); #if ( _sSize_ <> 1 & _sSize_ <> 2 & _sSize_ <> 4 & _sSize_ <> 8 & _sSize_ <> _dSize_ ) #error ( "array.transpose: " nl "Can only handle arrays with 1, 2, 4, or 8 byte elements" ); #elseif ( @elements( _srcArray_.dopeVector ) <= _xpos_ | @arity( _destArray_ ) <= _xpos_ | @elements( _srcArray_.dopeVector ) <> @arity( _destArray_ ) ) #error ( "array.transpose:" nl "Arrays must have at least " + string( _xpos_ ) + " dimensions" nl "and they must have the same number of dimensions" ); #else // We must check for proper array shapes at run-time // since we don't know the source array dimensions // until then. if (#{ ?_i_ := 1; #while( _i_ < @arity( _destArray_ )) #if( _i_ <> _xpos_ ) cmp ( _srcArray_.dopeVector[ _i_ * 4 ], _dstd_[_i_] ); jne true; #endif ?_i_ := _i_ + 1; #endwhile cmp ( _srcArray_.dopeVector[0], _dstd_[_xpos_] ); jne true; cmp ( _srcArray_.dopeVector[_xpos_*4], _dstd_[0] ); je false; }#) then raise( ex.ArrayShapeViolation ); endif; // Optimize the most common case (transposing // a two-dim array or the last two dimensions // of an array). #if( _xpos_ = 1 ) push( eax ); push( ebx ); push( ecx ); push( edx ); push( esi ); push( edi ); // Note: assume that the src and dest array // sizes are the same: mov( _srcArray_.dataPtr, ebx ); lea( ecx, [ebx + @size( _destArray_ )] ); push( ecx ); lea( ecx, _destArray_ ); sub( _dstd_[0] * _dstd_[1] * _dSize_, ecx ); while( ebx < [esp] ) do add( _dstd_[0] * _dstd_[1] * _dSize_, ecx ); for( mov(0, esi ); esi < _dstd_[0]; inc( esi )) do for ( mov( 0, edi ); edi < _dstd_[_xpos_]; inc( edi ) ) do #if( _dSize_ = 1 ) intmul( _dstd_[0], edi, edx ); add( esi, edx ); mov( [ebx], al ); mov( al, [ecx+edx] ); inc( ebx ); #elseif( _dSize_ = 2 ) intmul( _dstd_[0], edi, edx ); add( esi, edx ); mov( [ebx], ax ); mov( ax, [ecx+edx*2] ); add( 2, ebx ); #elseif( _dSize_ = 4 ) intmul( _dstd_[0], edi, edx ); add( esi, edx ); mov( [ebx], eax ); mov( eax, [ecx+edx*4] ); add( 4, ebx ); #else intmul( _dstd_[0], edi, edx ); add( esi, edx ); mov( [ebx], eax ); mov( eax, [ecx+edx*8] ); mov( [ebx+4], eax ); mov( eax, [ecx+edx*8+4] ); add( 8, ebx ); #endif endfor; endfor; endwhile; add( 4, esp ); pop( edi ); pop( esi ); pop( edx ); pop( ecx ); pop( ebx ); pop( eax ); // Okay, handle the case where we are not transposing // the last two dimensions of the array. This one is // ugly and less efficient (hence the special case // above). #else push( eax ); push( ebx ); push( esi ); push( edi ); // Make room for a set of loop control variables // on the stack: sub( @arity( _destArray_ ) * 4, esp ); // Initialize array base pointers. mov( _srcArray_.dataPtr, esi ); lea( ebx, _destArray_ ); // Emit the for loops that will do the // transposition. ?_i_ := @arity( _destArray_ ); #while( _i_ > 0 ) ?_offset_ := ( _i_ - 1 ) * 4; for ( mov(0, (type dword [esp+_offset_])); (type dword [esp+_offset_]) < _dstd_[_i_ - 1]; inc( (type dword [esp+_offset_])) ) do ?_i_ := _i_ - 1; #endwhile // Compute index into the destination array. // Note: to properly transpose, we need to // swap the zero index with the _xpos_ index. //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -