HalfFloatArray.st
author Claus Gittinger <cg@exept.de>
Sat, 02 May 2020 21:40:13 +0200
changeset 5476 7355a4b11cb6
parent 5217 d2ab1dc1961b
permissions -rw-r--r--
#FEATURE by cg class: Socket class added: #newTCPclientToHost:port:domain:domainOrder:withTimeout: changed: #newTCPclientToHost:port:domain:withTimeout:

"{ Encoding: utf8 }"

"
 COPYRIGHT (c) 2014 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:libbasic2' }"

"{ NameSpace: Smalltalk }"

UnboxedFloatArray variableWordSubclass:#HalfFloatArray
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	category:'Collections-Arrayed'
!

!HalfFloatArray primitiveFunctions!
%{
typedef unsigned short uint16;
typedef unsigned int   uint32;
#if 0
#if defined(__GNUC__) || defined(__CLANG__) || defined(__MINGW__)
inline float
XMConvertHalfToFloat(float16_t Value) {
    __m128i V1 = _mm_cvtsi32_si128( (uint32)(Value) );
    __m128 V2 = _mm_cvtph_ps( V1 );
    return _mm_cvtss_f32( V2 );
}

inline float16_t
XMConvertFloatToHalf(float Value) {
    __m128 V1 = _mm_set_ss( Value );
    __m128i V2 = _mm_cvtps_ph( V1, 0 );
    return (float16_t)( _mm_cvtsi128_si32(V2) );
}
#endif
#endif
//
// convert a halffloat (16-bit float) to a float
//
extern float __STX_halffloat_to_float(float16_t h);

//
// convert a float to a halffloat (16-bit float)
//
extern float16_t __STX_float_to_halffloat(float f32);

%}
! !

!HalfFloatArray class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 2014 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
"
    HalfFloatArrays store half precision (16bit) floats (and nothing else).
    HalfFloats were traditionally seldom used, but seem to become more popular
    these days, as some 3D graphics accelerators and game engines use them
    for very dense and compact storage of texture and vertex data.

    Notice, that HalfFloats are not supported as first class objects by the ST/X system;
    i.e. outside of a HalfFloatArray, these values are represented as floats
    or doubles. When accessing a HalfFloatArray's element via getters/setters,
    shortFloat (i.e. single precision 32bit floats) are exchanged.

    Be aware that the numeric range of a half-float is very very limited.

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

    [See also:]
	FloatArray DoubleArray Array
	http://www.opengl.org/wiki/Small_Float_Formats
	https://en.wikipedia.org/wiki/Half-precision

    [author:]
	Claus Gittinger
"
! !

!HalfFloatArray class methodsFor:'queries'!

elementByteSize
    "for bit-like containers, return the number of bytes stored per element.
     Here, 2 is returned"

    ^ 2
!

epsilon
    "return the maximum relative spacing of elements of mySelf
     (i.e. the value-delta of the least significant bit)"

     ^ 2.0 raisedToInteger:(self precision negated).

    "
     HalfFloatArray epsilon printStringScientific
    "

    "Created: / 19-07-2019 / 17:20:20 / Claus Gittinger"
!

precision
    "answer the precision (the number of bits in the mantissa) of my elements (in bits)
     This is an IEEE halffloat, where only the fraction from the normalized mantissa is stored
     and so there is a hidden bit and the mantissa is actually represented by 11 binary digits
     (although only 10 are needed in the binary representation)"

    ^ 11

    "Created: / 19-07-2019 / 17:20:25 / Claus Gittinger"
! !

!HalfFloatArray methodsFor:'accessing'!

at:index
%{  /* NOCONTEXT */
    if (__isSmallInteger(index)) {
        int i = __intVal(index)-1;
        int n = __wordArraySize(self);

        if ((unsigned)i < n) {
            float16_t h;
            OBJ newFloat;
            float f;

            h = (float16_t)(__WordArrayInstPtr(self)->s_element[i]);

            f = __STX_halffloat_to_float(h);
            __qMKSFLOAT(newFloat, f);
            RETURN ( newFloat );
        }
    }
%}.
    self primitiveFailed
!

at:index put:aFloat
%{
    if (! __isImmutable(self)) {
        if (__isSmallInteger(index)) {
            int i = __intVal(index)-1;
            int n = __wordArraySize(self);

            if ((unsigned)i < n) {
                float16_t h;
                float f;

                if (__isFloat(aFloat)) {
                    f = (float)(__floatVal(aFloat));
                } else if (__isShortFloat(aFloat)) {
                    f = __shortFloatVal(aFloat);
                } else if (__isSmallInteger(aFloat)) {
                    f = (float)(__intVal(aFloat));
                } else
                    goto error;

                h = __STX_float_to_halffloat(f);
                __WordArrayInstPtr(self)->s_element[i] = h;
                RETURN (aFloat);
            }
        }
    }
  error: ;
%}.
    "/ arrive here only in case of an error
    self isImmutable ifTrue:[
        self noModificationError
    ].    
    self primitiveFailed

    "Modified: / 09-06-2019 / 15:32:32 / Claus Gittinger"
! !

!HalfFloatArray methodsFor:'queries'!

defaultElement
    ^ ShortFloat zero
!

isValidElement:anObject
    "return true, if I can hold this kind of object"

    ^ anObject isNumber
!

numFloats
    ^ self size
! !

!HalfFloatArray methodsFor:'testing'!

isFloatArray
    "return true if the receiver has float elements.
     These are Float, Double- and HalfFloat arrays"

    ^ true

    "Created: / 02-03-2019 / 23:14:00 / Claus Gittinger"
! !

!HalfFloatArray class methodsFor:'documentation'!

version
    ^ '$Header$'
!

version_CVS
    ^ '$Header$'
! !