FloatArray.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Thu, 29 Sep 2011 16:44:37 +0100
branchjv
changeset 17869 9610c6c94e71
parent 17865 598963c6ff8e
child 17892 d86c8bd5ece3
permissions -rw-r--r--
(none)

"
 COPYRIGHT (c) 1993 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
"{ Package: 'stx:libbasic' }"

ArrayedCollection variableFloatSubclass:#FloatArray
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	category:'Collections-Arrayed'
!

!FloatArray class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1993 by Claus Gittinger
	      All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

documentation
"
    FloatArrays store floats (and nothing else).
    See documentation in DoubleArray for more information.

    [memory requirements:]
        OBJ-HEADER + (size * float-size)

    [See also:]
        DoubleArray Array

    [author:]
        Claus Gittinger
"
! !



!FloatArray class methodsFor:'queries'!

elementByteSize
    ^ 4

    "Created: / 15-09-2011 / 14:12:39 / cg"
! !


!FloatArray methodsFor:'arithmetic'!

* anObject
    "return the product of the receiver and the argument.
     The argument may either be a scalar or another vector"

    ^ self clone *= anObject

    "
     #(1 2 3 4) asFloatArray * 3  
     #(1 2 3 4) asFloatArray * #(1 2 3 4) asFloatArray
    "
!

+ anObject
    "return the sum of the receiver and the argument.
     The argument may either be a scalar or another vector"

    ^ self clone += anObject

    "
     #(1 2 3 4) asFloatArray + 3      
     #(1 2 3 4) asFloatArray + #(1 2 3 4) asFloatArray  
    "
!

- anObject
    "return the difference of the receiver and the argument.
     The argument may either be a scalar or another vector"

    ^ self clone -= anObject

    "
     #(1 2 3 4) asFloatArray - 3      
     #(1 2 3 4) asFloatArray - #(1 2 3 4) asFloatArray  
    "

    "Created: / 30-05-2007 / 17:41:46 / cg"
!

/ anObject
    "return the division of the receiver and the argument.
     The argument may either be a scalar or another vector"

    ^ self clone /= anObject

    "
     #(1 2 3 4) asFloatArray / 3      
     #(1 2 3 4) asFloatArray / #(1 2 3 4) asFloatArray  
    "

    "Created: / 30-05-2007 / 17:46:05 / cg"
!

abs
    ^ self clone primAbs

    "Created: / 30-05-2007 / 17:47:50 / cg"
!

negated
    ^ self clone primNegated

    "Modified: / 30-05-2007 / 17:51:47 / cg"
!

primAbs
    "destructive absolute value of each element"

%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        int _sz = __floatArraySize(self);
        int i;
        float *_p = __FloatArrayInstPtr(self)->f_element;

        /* how about inline-mmx-asm for this ... */
        for (i=0; i<_sz; i++) {
            float f = _p[i];

            if (f < 0) {
                _p[i] = -f;
            }
        }
        RETURN (self);
    }
%}. 
    1 to: self size do:[:i| self at: i put: (self at: i) abs].

    "
     |f|

     f := FloatArray withAll:#(-1 2 -3 4 -5).
     f abs.   
     f
    "

    "Created: / 30-05-2007 / 17:50:17 / cg"
!

primAddArray: floatArray
    "add the vector argument into the receiver (destructive).
     The argument must be another vector"

%{
    if ((__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0))
     && __isFloats(floatArray)
     && (__ClassInstPtr(__qClass(floatArray))->c_ninstvars == __mkSmallInteger(0))) {
        int _sz1 = __floatArraySize(self);
        int _sz2 = __floatArraySize(floatArray);
        int i;
        float *_p1 = __FloatArrayInstPtr(self)->f_element;
        float *_p2 = __FloatArrayInstPtr(floatArray)->f_element;

        if (_sz2 >= _sz1) {
            /* how about inline-mmx-asm for this ... */
            for (i=0; i<_sz1; i++) {
                _p1[i] += _p2[i];
            }
        }
        RETURN (self);
    }
%}. 
    1 to: self size do:[:i| self at: i put: (self at: i) + (floatArray at: i)].

    "
     |f1 f2|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f2 := FloatArray withAll:#(2 2 2 3 3).
     f1 += f2.
     f1         
    "
!

primAddScalar: aScalar
    "add the scalar argument into the receiver (destructive)."

%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        int _sz1 = __floatArraySize(self);
        int i;
        float *_p1 = __FloatArrayInstPtr(self)->f_element;
        float v;

        if (__isFloat(aScalar)) {
            v = (float)(__floatVal(aScalar));
        } else  if (__isShortFloat(aScalar)) {
            v = __shortFloatVal(aScalar);
        } else if (__isSmallInteger(aScalar)) {
            v = (float)(__intVal(aScalar));
        } else 
            goto badArg;

        /* how about inline-mmx-asm for this ... */
        for (i=0; i<_sz1; i++) {
            _p1[i] += v;
        }
        RETURN (self);
    }
    badArg: ;
%}.   
    1 to: self size do:[:i| self at: i put: (self at: i) + aScalar].

    "
     |f1 f2|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f1 += 2.0.
     Transcript showCR:f1.              
     f1 += 2.0 asShortFloat.
     Transcript showCR:f1.              
     f1 += 2.
     Transcript showCR:f1.              
    "
!

primDivArray: floatArray
    "divide the vector argument into the receiver (destructive).
     The argument must be another vector"

%{
    if ((__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0))
     && __isFloats(floatArray)
     && (__ClassInstPtr(__qClass(floatArray))->c_ninstvars == __mkSmallInteger(0))) {
        int _sz1 = __floatArraySize(self);
        int _sz2 = __floatArraySize(floatArray);
        int i;
        float *_p1 = __FloatArrayInstPtr(self)->f_element;
        float *_p2 = __FloatArrayInstPtr(floatArray)->f_element;

        if (_sz2 >= _sz1) {
            /* how about inline-mmx-asm for this ... */
            for (i=0; i<_sz1; i++) {
                _p1[i] /= _p2[i];
            }
        }
        RETURN (self);
    }
%}.
    1 to: self size do:[:i| self at: i put: (self at: i) / (floatArray at: i)].

    "
     |f1 f2|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f2 := FloatArray withAll:#(2 2 2 3 3).
     f1 /= f2.
     f1         
    "

    "Modified: / 29-05-2007 / 16:01:34 / cg"
!

primDivScalar: aScalar
    "divide the scalar argument into the receiver (destructive)."

%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        int _sz1 = __floatArraySize(self);
        int i;
        float *_p1 = __FloatArrayInstPtr(self)->f_element;
        float v;

        if (__isFloat(aScalar)) {
            v = (float)(__floatVal(aScalar));
        } else  if (__isShortFloat(aScalar)) {
            v = __shortFloatVal(aScalar);
        } else if (__isSmallInteger(aScalar)) {
            v = (float)(__intVal(aScalar));
        } else 
            goto badArg;

        /* how about inline-mmx-asm for this ... */
        for (i=0; i<_sz1; i++) {
            _p1[i] /= v;
        }
        RETURN (self);
    }
    badArg: ;
%}.
    1 to: self size do:[:i| self at: i put: (self at: i) / aScalar].

    "
     |f1 f2|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f1 /= 2.0.
     Transcript showCR:f1.              
     f1 /= 2.0 asShortFloat.
     Transcript showCR:f1.              
     f1 /= 2.
     Transcript showCR:f1.              
    "

    "Modified: / 29-05-2007 / 16:01:39 / cg"
!

primMulArray: floatArray
    "multiply the vector argument into the receiver (destructive).
     The argument must be another vector"

%{
    if ((__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0))
     && __isFloats(floatArray)
     && (__ClassInstPtr(__qClass(floatArray))->c_ninstvars == __mkSmallInteger(0))) {
        int _sz1 = __floatArraySize(self);
        int _sz2 = __floatArraySize(floatArray);
        int i;
        float *_p1 = __FloatArrayInstPtr(self)->f_element;
        float *_p2 = __FloatArrayInstPtr(floatArray)->f_element;

        if (_sz2 >= _sz1) {
            /* how about inline-mmx-asm for this ... */
            for (i=0; i<_sz1; i++) {
                _p1[i] *= _p2[i];
            }
        }
        RETURN (self);
    }
%}.
    1 to: self size do:[:i| self at: i put: (self at: i) * (floatArray at: i)].

    "
     |f1 f2|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f2 := FloatArray withAll:#(2 2 2 3 3).
     f1 *= f2.
     f1         
    "
!

primMulScalar: aScalar
    "multiply the scalar argument into the receiver (destructive)."

%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        int _sz1 = __floatArraySize(self);
        int i;
        float *_p1 = __FloatArrayInstPtr(self)->f_element;
        float v;

        if (__isFloat(aScalar)) {
            v = (float)(__floatVal(aScalar));
        } else  if (__isShortFloat(aScalar)) {
            v = __shortFloatVal(aScalar);
        } else if (__isSmallInteger(aScalar)) {
            v = (float)(__intVal(aScalar));
        } else 
            goto badArg;

        /* how about inline-mmx-asm for this ... */
        for (i=0; i<_sz1; i++) {
            _p1[i] *= v;
        }
        RETURN (self);
    }
    badArg: ;
%}.
    1 to: self size do:[:i| self at: i put: (self at: i) * aScalar].

    "
     |f1 f2|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f1 *= 2.0.
     Transcript showCR:f1.              
     f1 *= 2.0 asShortFloat.
     Transcript showCR:f1.              
     f1 *= 2.
     Transcript showCR:f1.              
    "
!

primNegated
    "destructive negative value of each element"

%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        int _sz = __floatArraySize(self);
        int i;
        float *_p = __FloatArrayInstPtr(self)->f_element;

        /* how about inline-mmx-asm for this ... */
        for (i=0; i<_sz; i++) {
            float f = _p[i];

            _p[i] = -f;
        }
        RETURN (self);
    }
%}. 
    1 to: self size do:[:i| self at: i put: (self at: i) negated].

    "
     |f|

     f := FloatArray withAll:#(-1 2 -3 4 -5).
     f negated.   
     f    
    "

    "Created: / 30-05-2007 / 17:51:29 / cg"
!

primSubtractArray: floatArray
    "subtract the vector argument from the receiver (destructive).
     The argument must be another vector"

%{
    if ((__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0))
     && __isFloats(floatArray)
     && (__ClassInstPtr(__qClass(floatArray))->c_ninstvars == __mkSmallInteger(0))) {
        int _sz1 = __floatArraySize(self);
        int _sz2 = __floatArraySize(floatArray);
        int i;
        float *_p1 = __FloatArrayInstPtr(self)->f_element;
        float *_p2 = __FloatArrayInstPtr(floatArray)->f_element;

        if (_sz2 >= _sz1) {
            /* how about inline-mmx-asm for this ... */
            for (i=0; i<_sz1; i++) {
                _p1[i] -= _p2[i];
            }
        }
        RETURN (self);
    }
%}. 
    1 to: self size do:[:i| self at: i put: (self at: i) - (floatArray at: i)].

    "
     |f1 f2|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f2 := FloatArray withAll:#(2 2 2 3 3).
     f1 -= f2.
     f1         
    "

    "Created: / 30-05-2007 / 17:42:41 / cg"
!

primSubtractScalar: aScalar
    "subtract the scalar argument from the receiver (destructive)."

%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        int _sz1 = __floatArraySize(self);
        int i;
        float *_p1 = __FloatArrayInstPtr(self)->f_element;
        float v;

        if (__isFloat(aScalar)) {
            v = (float)(__floatVal(aScalar));
        } else  if (__isShortFloat(aScalar)) {
            v = __shortFloatVal(aScalar);
        } else if (__isSmallInteger(aScalar)) {
            v = (float)(__intVal(aScalar));
        } else 
            goto badArg;

        /* how about inline-mmx-asm for this ... */
        for (i=0; i<_sz1; i++) {
            _p1[i] -= v;
        }
        RETURN (self);
    }
    badArg: ;
%}.   
    1 to: self size do:[:i| self at: i put: (self at: i) - aScalar].

    "
     |f1 f2|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f1 -= 2.0.
     Transcript showCR:f1.              
     f1 -= 2.0 asShortFloat.
     Transcript showCR:f1.              
     f1 -= 2.
     Transcript showCR:f1.              
    "

    "Created: / 30-05-2007 / 17:43:06 / cg"
! !

!FloatArray methodsFor:'arithmetic destructive'!

*= anObject
    "multiply the argument into the receiver (destructive).
     The argument may either be a scalar or another vector"

    ^ anObject isNumber
            ifTrue:[self primMulScalar: anObject asFloat]
            ifFalse:[self primMulArray: anObject]

    "
     |f|

     f := #(1 2 3 4) asFloatArray.
     f *= 3.
     f         
    "
    "
     |f|

     f := #(1 2 3 4) asFloatArray.
     f *= #(1 2 3 4) asFloatArray.
     f     
    "
!

+= anObject
    "add the argument into the receiver (destructive).
     The argument may either be a scalar or another vector"

    ^ anObject isNumber
            ifTrue:[self primAddScalar: anObject asFloat]
            ifFalse:[self primAddArray: anObject]

    "
     |f|

     f := #(1 2 3 4) asFloatArray.
     f += 3.
     f         
    "
    "
     |f|

     f := #(1 2 3 4) asFloatArray.
     f += #(1 2 3 4) asFloatArray.
     f      
    "
!

-= anObject
    "subtract the argument from the receiver (destructive).
     The argument may either be a scalar or another vector"

    ^ anObject isNumber
            ifTrue:[self primSubtractScalar: anObject asFloat]
            ifFalse:[self primSubtractArray: anObject]

    "
     |f|

     f := #(1 2 3 4) asFloatArray.
     f -= 3.
     f         
    "
    "
     |f|

     f := #(1 2 3 4) asFloatArray.
     f += #(1 2 3 4) asFloatArray.
     f      
    "

    "Created: / 30-05-2007 / 17:42:13 / cg"
!

/= anObject
    "divide the argument into the receiver (destructive).
     The argument may either be a scalar or another vector"

    ^ anObject isNumber
            ifTrue:[self primDivScalar: anObject asFloat]
            ifFalse:[self primDivArray: anObject]

    "Modified: / 30-05-2007 / 17:45:46 / cg"
! !

!FloatArray methodsFor:'copying'!

clone
    "return a copy of the receiver"

    |newArr|

    newArr := self class new:(self size).
%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        int _sz = __floatArraySize(self);

        bcopy(__FloatArrayInstPtr(self)->f_element,
              __FloatArrayInstPtr(newArr)->f_element,
              sizeof(float) * _sz);

        RETURN (newArr);
    }
%}.
    newArr replaceFrom:1 to:self size with:self startingAt:1.
    ^ newArr

    "
     |f1 f2|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f1 clone         
    "
!

copyFrom:start to:stop
    "return a partial copy of the receiver"

%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        if (__bothSmallInteger(start, stop)) {
            int __start = __intVal(start) - 1;
            int __stop = __intVal(stop) - 1 ;

            if (__stop >= __start) {
                int __sz = __floatArraySize(self);

                if (((unsigned)__start < __sz) 
                 && ((unsigned)__stop < __sz)) {
                    int __n = __stop - __start + 1;
                    OBJ __nObj;

                    __nObj = __STX___new(sizeof(struct __FloatArray) + (__n - 1) * sizeof(float));
                    if (__nObj != nil) {
                        __objPtr(__nObj)->o_class = __qClass(self);
                        __STORE(__nObj, __qClass(self));
                        bcopy(__FloatArrayInstPtr(self)->f_element + __start,
                              __FloatArrayInstPtr(__nObj)->f_element,
                              sizeof(float) * __n);
                        RETURN(__nObj);
                    }
                }
            }
        }
    }
%}. 
    ^ super copyFrom:start to:stop

    "
     |f1 f2|

     f1 := FloatArray withAll:#(1 2 3 4 5 6).
     f2 := f1 copyFrom:2 to:4.         
     f2        
    "
!

replaceFrom:start to:stop with:aCollection startingAt:replStart
%{
    if ((__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0))
     && __isFloats(aCollection)
     && (__ClassInstPtr(__qClass(aCollection))->c_ninstvars == __mkSmallInteger(0))) {
        if (__bothSmallInteger(start, stop)
         && __isSmallInteger(replStart)) {
            int __start = __intVal(start) - 1;
            int __stop = __intVal(stop) - 1 ;
            int __replStart = __intVal(replStart) - 1 ;

            if (__stop >= __start) {
                int __sz = __floatArraySize(self);
                int __otherSz = __floatArraySize(aCollection);
                int __replStop = __replStart + (__stop-__start);

                if (((unsigned)__start < __sz) 
                 && ((unsigned)__stop < __sz)
                 && ((unsigned)__replStart < __otherSz)
                 && ((unsigned)__replStop < __otherSz)) {
                    int __n = __stop - __start + 1;

                    if (aCollection != self) {
                        bcopy(&(__FloatArrayInstPtr(aCollection)->f_element[__replStart]),
                              &(__FloatArrayInstPtr(self)->f_element[__start]),
                              sizeof(float) * __n);
                        RETURN(self);
                    }
                }
            }
        }
    }
%}.
    ^ super replaceFrom:start to:stop with:aCollection startingAt:replStart

    "
     |f1 f2|

     f1 := (1 to:5) asFloatArray.
     f2 := #(10 9 8 7 6) asFloatArray.
     f1 replaceFrom:1 to:3 with:f2 startingAt:3       
    "
! !

!FloatArray methodsFor:'queries'!

absMax
    "return the largest absolute value"

    |mm|

    mm := self minMax.
    ^ (mm at:1) abs max:(mm at:2) abs

    "
     |f1|

     f1 := (1 to:1000) asFloatArray.
     Time millisecondsToRun:[ 1000 timesRepeat:[ f1 absMax ] ]
    "

    "
     |f1|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f1 absMax             
    "
    "
     |f1|

     f1 := FloatArray withAll:#(5 4 3 2 1).
     f1 absMax             
    "
    "
     |f1|

     f1 := FloatArray withAll:#(5 -4 3 2 1).
     f1 absMax             
    "
    "
     |f1|

     f1 := FloatArray withAll:#(5 -5 3 2 1).
     f1 absMax             
    "
    "
     |f1|

     f1 := FloatArray withAll:#(5 -6 3 2 1).
     f1 absMax             
    "
!

defaultElement
    ^ ShortFloat zero
!

length
    "Return the length of the receiver interpreted as vector 
     (that is the length of the vector from 0.0 @ 0.0 @ ... @ 0.0
      to the point in the n-dimensional space represented by the receiver)"

    ^ self squaredLength sqrt

    "
     #(10.0 10.0) asFloatArray length                 
     #(10.0 10.0 10.0) asFloatArray length                 
    "
!

max
    "return the largest element;
     redefined for speed"
%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        int _sz = __floatArraySize(self);

        if (_sz > 0) {
            float *_p = __FloatArrayInstPtr(self)->f_element;
            float _max;

            _max = _p[0];
            if (_sz > 1) {
                int _i;
                float _prev, _this;

                /* how about inline-mmx-asm for this ... */
                _this = _p[1];
                for (_i=2; _i<_sz; _i++) {
                    _prev = _this;
                    _this = _p[_i];
                    if (_prev > _max) _max = _prev;
                }
                if (_this > _max) _max = _this;
            }
            RETURN (__MKFLOAT(_max));
        }
    }
%}.
    ^ super max

    "
     |f1|

     f1 := (1 to:1000) asFloatArray.
     Time millisecondsToRun:[ 1000 timesRepeat:[ f1 max ] ]
    "
    "
     |f1|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f1 max             
    "
    "
     |f1|

     f1 := FloatArray withAll:#(5 4 3 2 1).
     f1 max             
    "
!

min
    "return the largest element;
     redefined for speed"
%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        int _sz = __floatArraySize(self);

        if (_sz > 0) {
            float *_p = __FloatArrayInstPtr(self)->f_element;
            float _min;

            _min = _p[0];
            if (_sz > 1) {
                int _i;
                float _prev, _this;

                /* how about inline-mmx-asm for this ... */
                _this = _p[1];
                for (_i=2; _i<_sz; _i++) {
                    _prev = _this;
                    _this = _p[_i];
                    if (_prev < _min) _min = _prev;
                }
                if (_this < _min) _min = _this;
            }
            RETURN (__MKFLOAT(_min));
        }
    }
%}.
    ^ super min

    "
     |f1|

     f1 := (1 to:1000) asFloatArray.
     Time millisecondsToRun:[ 1000 timesRepeat:[ f1 min ] ]
    "
    "
     |f1|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f1 min             
    "
    "
     |f1|

     f1 := FloatArray withAll:#(5 4 3 2 1).
     f1 min             
    "
!

minMax
    "return a Tuple holding the smallest and largest element;
     redefined for speed"

    |min max|

%{
    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
        int _sz = __floatArraySize(self);
        if (_sz > 0) {
            int _i;
            float *_p = __FloatArrayInstPtr(self)->f_element;
            float _min, _max;

            _min = _max = _p[0];

            if (_sz > 1) {
                float _this = _p[1];
                float _prev;

                /* how about inline-mmx-asm for this ... */
                for (_i=2; _i<_sz; _i++) {
                    _prev = _this;
                    _this = _p[_i];
                    if (_prev < _min) {
                        _min = _prev;
                    } else if (_prev > _max) {
                        _max = _prev;
                    }
                }
                if (_this < _min) {
                    _min = _this;
                } else if (_this > _max) {
                    _max = _this;
                }
            }
            min = __MKFLOAT(_min);
            max = __MKFLOAT(_max);
            RETURN (__ARRAY_WITH2(min, max));
        }
    }
%}.
    ^ Array with:(super min) with:(super max)

    "
     |f1|

     f1 := (1 to:1000) asFloatArray.
     Time millisecondsToRun:[ 1000 timesRepeat:[ f1 minMax ] ] 
    "
    "
     |f1|

     f1 := FloatArray withAll:#(1 2 3 4 5).
     f1 minMax     
    "
    "
     |f1|

     f1 := FloatArray withAll:#(5 4 3 2 1).
     f1 minMax        
    "
!

numFloats
    ^ self size
!

squaredLength
    "Return the squared length of the receiver interpreted as vector"

    ^ self dot: self
! !

!FloatArray methodsFor:'vector arithmetic'!

dot: aFloatVector
    "Return the dot product of the receiver and the argument.
     Fail if the argument is not of the same size as the receiver."

    | mySize result |

"/    <primitive:'primitiveDotProduct' module: 'FloatArrayPlugin'>
%{
    if (__isFloats(aFloatVector)
    && (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0))
    && (__ClassInstPtr(__qClass(aFloatVector))->c_ninstvars == __mkSmallInteger(0))) {
        int __mySize = __floatArraySize(self);
        int __otherSize = __floatArraySize(aFloatVector);
        if (__mySize == __otherSize) {
            float *__p1 = __FloatArrayInstPtr(self)->f_element;
            float *__p2 = __FloatArrayInstPtr(aFloatVector)->f_element;
            float __result = 0.0;
            int __i;

            /* how about inline-mmx-asm for this ... */
            for (__i=0; __i<__mySize; __i++) {
                __result = __result + (__p1[__i] * __p2[__i]);
            }
            RETURN (__MKFLOAT(__result));
        }
    }
%}.

    mySize := self size.
    mySize = aFloatVector size ifFalse:[^self error:'Must be of equal size'].
    result := 0.0.
    1 to: mySize do:[:i|
        result := result + ((self at: i) * (aFloatVector at: i)).
    ].
    ^result

    "
     |v|

     v := #(2.0 2.0 1.0) asFloatArray.
     v dot:v.    
    "

    "Created: / 29-05-2007 / 13:13:39 / cg"
! !

!FloatArray class methodsFor:'documentation'!

version
    ^ '$Id: FloatArray.st 10700 2011-09-29 15:44:37Z vranyj1 $'
!

version_CVS
    ^ '§Header: /cvs/stx/stx/libbasic/FloatArray.st,v 1.27 2011/09/15 13:11:52 cg Exp §'
!

version_SVN
    ^ '$Id: FloatArray.st 10700 2011-09-29 15:44:37Z vranyj1 $'
! !