Comment convertir un flotteur hexagonal à un flotteur en C / C ++ en utilisant GCC instrinc SSE _mm_extract_ps fonction

StackOverflow https://stackoverflow.com/questions/3130169

Question

Je suis en train d'écrire un code SSE à convolution 2D mais la documentation SSE est très clairsemée. Je calcul produit scalaire avec _mm_dp_ps et en utilisant _mm_extract_ps pour obtenir le résultat du produit scalaire, mais _mm_extract_ps renvoie un hexagone qui représente un flotteur et je ne peux pas comprendre comment convertir ce flotteur hexagonal à un flotteur régulier. Je pourrais utiliser __builtin_ia32_vec_ext_v4sf qui retourne un flotteur, mais je veux garder la compatibilité avec d'autres compilateurs.

_mm_extract_ps (__m128 __X, const int __N)
{
  union { int i; float f; } __tmp;
  __tmp.f = __builtin_ia32_vec_ext_v4sf ((__v4sf)__X, __N);
  return __tmp.i;
}

quel point je suis absent?

Un peu d'aide sera appréciée, merci.

OpenSUSE 11.2
GCC 4.4.1
C de la
Options du compilateur
-fopenmp -Wall -O3 -msse4.1 -march = Core2
Options Linker
-lgomp -Wall -O3 -msse4.1 -march = Core2

Était-ce utile?

La solution

Vous devriez pouvoir utiliser _MM_EXTRACT_FLOAT.

Par ailleurs, il semble à moi comme si _mm_extract_ps et _MM_EXTRACT_FLOAT devrait être l'inverse, à savoir _mm_extract_ps REVERSE un flotteur et _MM_EXTRACT_FLOAT doit retourner la représentation int, mais qu'est-ce que je sais.

Autres conseils

_mm_cvtss_f32(_mm_shuffle_ps(__X, __X, __N)) fera le travail.

Et pour illustrer tout ce qui a été dit jusqu'à présent:

main.c

#include <assert.h>

#include <x86intrin.h>

int main(void) {

    /* 32-bit. */
    {
        __m128 x = _mm_set_ps(1.5f, 2.5f, 3.5f, 4.5f);

        /* _MM_EXTRACT_FLOAT */
        float f;
        _MM_EXTRACT_FLOAT(f, x, 3);
        assert(f == 1.5f);
        _MM_EXTRACT_FLOAT(f, x, 2);
        assert(f == 2.5f);
        _MM_EXTRACT_FLOAT(f, x, 1);
        assert(f == 3.5f);
        _MM_EXTRACT_FLOAT(f, x, 0);
        assert(f == 4.5f);

        /* _mm_cvtss_f32 + _mm_shuffle_ps */
        assert(_mm_cvtss_f32(x) == 4.5f);
        assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 1)) == 3.5f);
        assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 2)) == 2.5f);
        assert(_mm_cvtss_f32(_mm_shuffle_ps(x, x, 3)) == 1.5f);
    }

    /* 64-bit. */
    {
        __m128d x = _mm_set_pd(1.5, 2.5);
        /* _mm_cvtsd_f64 + _mm_unpackhi_pd */
        assert(_mm_cvtsd_f64(x) == 2.5);
        assert(_mm_cvtsd_f64(_mm_unpackhi_pd(x, x)) == 1.5);
    }
}

GitHub en amont .

compilez et exécutez:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

Double mentionné à: _mm_cvtsd_f64 analogon de virgule flottante d'ordre supérieur

Testé sur Ubuntu 19.04 amd64.

_mm_store_ss extern void (float *, __m128);

Voir 'xmmintrin.h.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top