HalfFloatArray.st
changeset 3159 1ea80d1ded0c
child 3160 d5bef8d7e676
equal deleted inserted replaced
3158:32762c55c099 3159:1ea80d1ded0c
       
     1 "
       
     2  COPYRIGHT (c) 2014 by Claus Gittinger
       
     3 	      All Rights Reserved
       
     4 
       
     5  This software is furnished under a license and may be used
       
     6  only in accordance with the terms of that license and with the
       
     7  inclusion of the above copyright notice.   This software may not
       
     8  be provided or otherwise made available to, or used by, any
       
     9  other person.  No title to or ownership of the software is
       
    10  hereby transferred.
       
    11 "
       
    12 "{ Package: 'stx:libbasic2' }"
       
    13 
       
    14 AbstractNumberVector variableWordSubclass:#HalfFloatArray
       
    15 	instanceVariableNames:''
       
    16 	classVariableNames:''
       
    17 	poolDictionaries:''
       
    18 	category:'Collections-Arrayed'
       
    19 !
       
    20 
       
    21 !HalfFloatArray primitiveFunctions!
       
    22 
       
    23 %{
       
    24 typedef unsigned short halffloat;
       
    25 typedef unsigned short uint16;
       
    26 typedef unsigned int   uint32;
       
    27 
       
    28 //
       
    29 // convert a halffloat (16-bit float) to a float
       
    30 //
       
    31 float
       
    32 __STX_halffloat_to_float(halffloat h) {
       
    33 	int e;
       
    34 	uint16 hs, he, hm;
       
    35 	uint32 xs, xe, xm;
       
    36 	int32 xes;
       
    37 	union {
       
    38 	    uint32 u32;
       
    39 	    float f32;
       
    40 	} u;
       
    41 
       
    42 	if( (h & 0x7FFFu) == 0 ) {  // Signed zero
       
    43 	    u.u32 = ((uint32) h) << 16;  // Return the signed zero
       
    44 	} else { // Not zero
       
    45 	    hs = h & 0x8000u;  // Pick off sign bit
       
    46 	    he = h & 0x7C00u;  // Pick off exponent bits
       
    47 	    hm = h & 0x03FFu;  // Pick off mantissa bits
       
    48 	    if( he == 0 ) {  // Denormal will convert to normalized
       
    49 		e = -1; // The following loop figures out how much extra to adjust the exponent
       
    50 		do {
       
    51 		    e++;
       
    52 		    hm <<= 1;
       
    53 		} while( (hm & 0x0400u) == 0 ); // Shift until leading bit overflows into exponent bit
       
    54 		xs = ((uint32) hs) << 16; // Sign bit
       
    55 		xes = ((uint32) (he >> 10)) - 15 + 127 - e; // Exponent unbias the halfp, then bias the single
       
    56 		xe = (uint32) (xes << 23); // Exponent
       
    57 		xm = ((uint32) (hm & 0x03FFu)) << 13; // Mantissa
       
    58 		u.u32 = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits
       
    59 	    } else if( he == 0x7C00u ) {  // Inf or NaN (all the exponent bits are set)
       
    60 		if( hm == 0 ) { // If mantissa is zero ...
       
    61 		    u.u32 = (((uint32) hs) << 16) | ((uint32) 0x7F800000u); // Signed Inf
       
    62 		} else {
       
    63 		    u.u32 = (uint32) 0xFFC00000u; // NaN, only 1st mantissa bit set
       
    64 		}
       
    65 	    } else { // Normalized number
       
    66 		xs = ((uint32) hs) << 16; // Sign bit
       
    67 		xes = ((uint32) (he >> 10)) - 15 + 127; // Exponent unbias the halfp, then bias the single
       
    68 		xe = (uint32) (xes << 23); // Exponent
       
    69 		xm = ((uint32) hm) << 13; // Mantissa
       
    70 		u.u32 = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits
       
    71 	    }
       
    72 	}
       
    73 	return u.f32;
       
    74 }
       
    75 
       
    76 //
       
    77 // convert a float to a halffloat (16-bit float)
       
    78 //
       
    79 halffloat
       
    80 __STX_float_to_halffloat(float f32) {
       
    81 	uint16    hs, he, hm;
       
    82 	uint32 x, xs, xe, xm;
       
    83 	int hes;
       
    84 	union {
       
    85 	    uint32 u32;
       
    86 	    float f32;
       
    87 	} u;
       
    88 	halffloat h;
       
    89 
       
    90 	u.f32 = f32;
       
    91 	x = u.u32;
       
    92 	if( (x & 0x7FFFFFFFu) == 0 ) {  // Signed zero
       
    93 	    h = (uint16) (x >> 16);  // Return the signed zero
       
    94 	} else { // Not zero
       
    95 	    xs = x & 0x80000000u;  // Pick off sign bit
       
    96 	    xe = x & 0x7F800000u;  // Pick off exponent bits
       
    97 	    xm = x & 0x007FFFFFu;  // Pick off mantissa bits
       
    98 	    if( xe == 0 ) {  // Denormal will underflow, return a signed zero
       
    99 		h = (uint16) (xs >> 16);
       
   100 	    } else if( xe == 0x7F800000u ) {  // Inf or NaN (all the exponent bits are set)
       
   101 		if( xm == 0 ) { // If mantissa is zero ...
       
   102 		    h = (uint16) ((xs >> 16) | 0x7C00u); // Signed Inf
       
   103 		} else {
       
   104 		    h = (uint16) 0xFE00u; // NaN, only 1st mantissa bit set
       
   105 		}
       
   106 	    } else { // Normalized number
       
   107 		hs = (uint16) (xs >> 16); // Sign bit
       
   108 		hes = ((int)(xe >> 23)) - 127 + 15; // Exponent unbias the single, then bias the halfp
       
   109 		if( hes >= 0x1F ) {  // Overflow
       
   110 		    h = (uint16) ((xs >> 16) | 0x7C00u); // Signed Inf
       
   111 		} else if( hes <= 0 ) {  // Underflow
       
   112 		    if( (14 - hes) > 24 ) {  // Mantissa shifted all the way off & no rounding possibility
       
   113 			hm = (uint16) 0u;  // Set mantissa to zero
       
   114 		    } else {
       
   115 			xm |= 0x00800000u;  // Add the hidden leading bit
       
   116 			hm = (uint16) (xm >> (14 - hes)); // Mantissa
       
   117 			if( (xm >> (13 - hes)) & 0x00000001u ) // Check for rounding
       
   118 			    hm += (uint16) 1u; // Round, might overflow into exp bit, but this is OK
       
   119 		    }
       
   120 		    h = (hs | hm); // Combine sign bit and mantissa bits, biased exponent is zero
       
   121 		} else {
       
   122 		    he = (uint16) (hes << 10); // Exponent
       
   123 		    hm = (uint16) (xm >> 13); // Mantissa
       
   124 		    if( xm & 0x00001000u ) // Check for rounding
       
   125 			h = (hs | he | hm) + (uint16) 1u; // Round, might overflow to inf, this is OK
       
   126 		    else
       
   127 			h = (hs | he | hm);  // No rounding
       
   128 		}
       
   129 	    }
       
   130 	}
       
   131 	return h;
       
   132 }
       
   133 
       
   134 %}
       
   135 !
       
   136 
       
   137 !HalfFloatArray class methodsFor:'documentation'!
       
   138 
       
   139 copyright
       
   140 "
       
   141  COPYRIGHT (c) 1993 by Claus Gittinger
       
   142 	      All Rights Reserved
       
   143 
       
   144  This software is furnished under a license and may be used
       
   145  only in accordance with the terms of that license and with the
       
   146  inclusion of the above copyright notice.   This software may not
       
   147  be provided or otherwise made available to, or used by, any
       
   148  other person.  No title to or ownership of the software is
       
   149  hereby transferred.
       
   150 "
       
   151 !
       
   152 
       
   153 documentation
       
   154 "
       
   155     HalfFloatArrays store half precision (16bit) floats (and nothing else).
       
   156     HalfFloats were trditionally seldom used, but seem to become more popular
       
   157     these days, as some 3D graphics accelerators and game engines use them
       
   158     for very dens and compact storage.
       
   159     Notice, that when accessing a HalfFloats elements via getters/setters,
       
   160     shortFloat (i.e. single precision 32bit floats are exchanged).
       
   161     HalfFloats are not supported as first class objects by the st/x system (yet?).
       
   162 
       
   163     [memory requirements:]
       
   164 	OBJ-HEADER + (size * 2)
       
   165 
       
   166     [See also:]
       
   167 	FloatArray DoubleArray Array
       
   168 
       
   169     [author:]
       
   170 	Claus Gittinger
       
   171 "
       
   172 ! !
       
   173 
       
   174 !HalfFloatArray class methodsFor:'queries'!
       
   175 
       
   176 elementByteSize
       
   177     ^ 2
       
   178 ! !
       
   179 
       
   180 
       
   181 !HalfFloatArray methodsFor:'accessing'!
       
   182 
       
   183 at:index
       
   184 %{  /* NOCONTEXT */
       
   185     if (__isSmallInteger(index)) {
       
   186 	int i = __intVal(index);
       
   187 
       
   188 	if ((unsigned int)i <= __wordArraySize(self)) {
       
   189 	    unsigned short h;
       
   190 	    OBJ newFloat;
       
   191 	    float f;
       
   192 
       
   193 	    h = __WordArrayInstPtr(self)->s_element[i];
       
   194 
       
   195 	    f = __STX_halffloat_to_float(h);
       
   196 	    __qMKSFLOAT(newFloat, f);
       
   197 	    RETURN ( newFloat );
       
   198 	}
       
   199     }
       
   200 %}.
       
   201     self primitiveFailed
       
   202 !
       
   203 
       
   204 at:index put:aFloat
       
   205 %{
       
   206     if (__isSmallInteger(index)) {
       
   207 	int i = __intVal(index);
       
   208 
       
   209 	if ((unsigned)i <= __wordArraySize(self)) {
       
   210 	    unsigned short h;
       
   211 	    float f;
       
   212 
       
   213 	    if (__isFloat(aFloat)) {
       
   214 		f = (float)(__floatVal(aFloat));
       
   215 	    } else if (__isShortFloat(aFloat)) {
       
   216 		f = __shortFloatVal(aFloat);
       
   217 	    } else if (__isSmallInteger(aFloat)) {
       
   218 		f = (float)(__intVal(aFloat));
       
   219 	    } else
       
   220 		goto error;
       
   221 
       
   222 	    h = __STX_float_to_halffloat(f);
       
   223 	    __WordArrayInstPtr(self)->s_element[i] = h;
       
   224 	    RETURN (aFloat);
       
   225 	}
       
   226     }
       
   227   error: ;
       
   228 %}.
       
   229     self primitiveFailed
       
   230 ! !
       
   231 
       
   232 !HalfFloatArray methodsFor:'queries'!
       
   233 
       
   234 defaultElement
       
   235     ^ ShortFloat zero
       
   236 !
       
   237 
       
   238 numFloats
       
   239     ^ self size
       
   240 ! !
       
   241 
       
   242 !HalfFloatArray class methodsFor:'documentation'!
       
   243 
       
   244 version_CVS
       
   245     ^ '$Header: /cvs/stx/stx/libbasic2/HalfFloatArray.st,v 1.1 2014-02-04 17:05:02 cg Exp $'
       
   246 ! !