Created
October 11, 2011 21:57
-
-
Save Themaister/1279585 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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