Skip to content

Instantly share code, notes, and snippets.

@Themaister
Created October 11, 2011 21:57
Show Gist options
  • Save Themaister/1279585 to your computer and use it in GitHub Desktop.
Save Themaister/1279585 to your computer and use it in GitHub Desktop.
#include <emmintrin.h>
#include <stdio.h>
int main(void)
{
// Attempt to divide by 0x8000. With integer math this is right shift by 15.
// IEEE floats are laid out like this:
// [1 - 8 - 23]
// [Sign bit - Exponent - Mantissa]
// The value is calculated as: (-1)^sign * (1 + mantissa) * (2 ^ (exponent - 127)).
// Thus, we'll need to subtract the exponent part by 15. 2 ^ (-15) = 1.0/0x8000.
static float buf[] __attribute__((aligned(16))) = {0x4000, 0x3000, 0x2000, 0x1000};
printf("Before: %f, %f, %f, %f\n", buf[0], buf[1], buf[2], buf[3]);
// Load vector into 128-bit register.
__m128i reg = _mm_load_si128((__m128i*)buf);
// We're working on 4 values at a time, 32-bit for each.
// exp gets the exponent part, mantissa gets sign bit and mantissa itself which we don't care about for now.
// _mm_set1_epi32() splats a value into a vector. splat(10) = [10, 10, 10, 10].
__m128i exp = _mm_and_si128(reg, _mm_set1_epi32(0x7f800000));
__m128i mantissa = _mm_and_si128(reg, _mm_set1_epi32(0x807fffff));
// Subtract 15 from the exponent (shift by 23 to get to the exponent).
// Mask again incase we overflow our bounaries.
exp = _mm_and_si128(_mm_sub_epi32(exp, _mm_set1_epi32(15 << 23)), _mm_set1_epi32(0x7f800000));
// OR together fixed up exponent and old mantissa/sign.
_mm_store_ps(buf, (__m128)_mm_or_si128(exp, mantissa));
printf("After: %f, %f, %f, %f\n", buf[0], buf[1], buf[2], buf[3]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment