FloatArray.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Wed, 10 Jun 2015 08:43:00 +0100
branchjv
changeset 18482 68a43e2b3e78
parent 18120 e3a375d5f6a8
child 18608 7d521f25267c
permissions -rw-r--r--
Merge

"
 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' }"

AbstractNumberVector 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).
    They have been added to support heavy duty number crunching and
    data exchange with openGL frameworks and other mass data libraries. 
    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
    "for bit-like containers, return the number of bytes stored per element.
     Here, 4 is returned"

    ^ 4

    "Created: / 15-09-2011 / 14:12:39 / 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 INT)__start < __sz)
		 && ((unsigned INT)__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 INT)__start < __sz)
		 && ((unsigned INT)__stop < __sz)
		 && ((unsigned INT)__replStart < __otherSz)
		 && ((unsigned INT)__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:'destructive arithmetic support'!

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;
        float prev_p;

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

                if (prev_p < 0) {
                    _p[i-1] = -prev_p;
                }
                prev_p = next_p;
            }
            if (prev_p < 0) {
                _p[i-1] = -prev_p;
            }
        }
        RETURN (self);
    }
%}.
    super primAbs

    "
     |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 (_sz1 > 0) {
            if (_sz2 >= _sz1) {
                /* how about inline-mmx-asm for this ... */
                float prev_p1 = _p1[0];
                float prev_p2 = _p2[0];

                for (i=1; i<_sz1; i++) {
                    float next_p1 = _p1[i];
                    float next_p2 = _p2[i];
                    _p1[i-1] = prev_p1 + prev_p2;
                    prev_p1 = next_p1;
                    prev_p2 = next_p2;
                }
                _p1[i-1] = prev_p1 + prev_p2;
            }
        }
        RETURN (self);
    }
%}.
    super primAddArray:floatArray

    "
     |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;
        float prev_p1;

        if (_sz1 > 0) {
            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 ... */
            prev_p1 = _p1[0];
            for (i=1; i<_sz1; i++) {
                float next_p1 = _p1[i];
                _p1[i-1] = prev_p1 + v;
                prev_p1 = next_p1;
            }
            _p1[i-1] = prev_p1 + v;
        }
        RETURN (self);
    }
    badArg: ;
%}.
    super primAddScalar: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 (_sz1 > 0) {
            if (_sz2 >= _sz1) {
                /* how about inline-mmx-asm for this ... */
                float prev_p1 = _p1[0];
                float prev_p2 = _p2[0];

                for (i=1; i<_sz1; i++) {
                    float next_p1 = _p1[i];
                    float next_p2 = _p2[i];
                    _p1[i-1] = prev_p1 / prev_p2;
                    prev_p1 = next_p1;
                    prev_p2 = next_p2;
                }
                _p1[i-1] = prev_p1 / prev_p2;
            }
        }
        RETURN (self);
    }
%}.
    super primDivArray: floatArray

    "
     |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;
        float prev_p1;

        if (_sz1 > 0) {
            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 ... */
            prev_p1 = _p1[0];
            for (i=1; i<_sz1; i++) {
                float next_p1 = _p1[i];
                _p1[i-1] = prev_p1 / v;
                prev_p1 = next_p1;
            }
            _p1[i-1] = prev_p1 / v;
        }
        RETURN (self);
    }
    badArg: ;
%}.
    super primDivScalar: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 (_sz1 > 0) {
            if (_sz2 >= _sz1) {
                float prev_p1 = _p1[0];
                float prev_p2 = _p2[0];

                for (i=1; i<_sz1; i++) {
                    float next_p1 = _p1[i];
                    float next_p2 = _p2[i];
                    _p1[i-1] = prev_p1 * prev_p2;
                    prev_p1 = next_p1;
                    prev_p2 = next_p2;
                }
                _p1[i-1] = prev_p1 * prev_p2;
            }
        }
        RETURN (self);
    }
%}.
    super primMulArray: floatArray

    "
     |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;
        float prev_p1;

        if (_sz1 > 0) {
            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 ... */
            prev_p1 = _p1[0];
            for (i=1; i<_sz1; i++) {
                float next_p1 = _p1[i];
                _p1[i-1] = prev_p1 * v;
                prev_p1 = next_p1;
            }
            _p1[i-1] = prev_p1 * v;
        }
        RETURN (self);
    }
    badArg: ;
%}.
    super primMulScalar: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;
        float prev_p;

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

                _p[i-1] = -prev_p;
                prev_p = next_p;
            }
            _p[i-1] = -prev_p;
        }
        RETURN (self);
    }
%}.
    super primNegated

    "
     |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 (_sz1 > 0) {
            if (_sz2 >= _sz1) {
                float prev_p1 = _p1[0];
                float prev_p2 = _p2[0];

                for (i=1; i<_sz1; i++) {
                    float next_p1 = _p1[i];
                    float next_p2 = _p2[i];
                    _p1[i-1] = prev_p1 - prev_p2;
                    prev_p1 = next_p1;
                    prev_p2 = next_p2;
                }
                _p1[i-1] = prev_p1 - prev_p2;
            }
        }
        RETURN (self);
    }
%}.
    super primSubtractArray: floatArray

    "
     |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;
        float prev_p1;

        if (_sz1 > 0) {
            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... ? */
            prev_p1 = _p1[0];
            for (i=1; i<_sz1; i++) {
                float next_p1 = _p1[i];
                _p1[i-1] = prev_p1 - v;
                prev_p1 = next_p1;
            }
            _p1[i-1] = prev_p1 - v;
        }
        RETURN (self);
    }
    badArg: ;
%}.
    super primSubtractScalar: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:'queries'!

defaultElement
    ^ ShortFloat zero
!

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];
#ifdef PRE_4_OCT_2011
	    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;
		}
	    }
#else
	    for (_i=_sz-1; _i>0; _i-=2) {
		float _v1 = _p[_i];
		float _v2 = _p[_i-1];
		if (_v1 < _v2) {
		    if (_v1 < _min) _min = _v1;
		    if (_v2 > _max) _max = _v2;
		} else {
		    if (_v2 < _min) _min = _v2;
		    if (_v1 > _max) _max = _v1;
		}
	    }
#endif
	    min = __MKFLOAT(_min);
	    max = __MKFLOAT(_max);
	    RETURN (__ARRAY_WITH2(min, max));
	}
    }
%}.
    ^ Array with:(super min) with:(super max)

    "
     |f1|

     f1 := (1 to:10000) 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
    "

    "Modified (comment): / 07-10-2011 / 13:03:30 / cg"
!

numFloats
    ^ self size
! !

!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);
        float __result = 0.0;

        if (__mySize == __otherSize) {
            if (__mySize > 0) {
                float *__p1 = __FloatArrayInstPtr(self)->f_element;
                float *__p2 = __FloatArrayInstPtr(aFloatVector)->f_element;
                INT __i;
                /* how about inline-mmx-asm for this ... */
                for (__i=0; __i<__mySize; __i++) {
                    __result += (__p1[__i] * __p2[__i]);
                }
            }
            RETURN (__MKFLOAT(__result));
        }
    }
%}.
    ^ super dot:aFloatVector

    "
     |v|

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

     v1 := FloatArray new:10000 withAll:2.
     v2 := FloatArray new:10000 withAll:3. 
     Time millisecondsToRun:[
        10000 timesRepeat:[
          v1 dot:v2.       
        ]          
     ]          
    "

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


!FloatArray class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libbasic/FloatArray.st,v 1.35 2014-12-08 17:30:24 cg Exp $'
!

version_CVS
    ^ '$Header: /cvs/stx/stx/libbasic/FloatArray.st,v 1.35 2014-12-08 17:30:24 cg Exp $'
! !