Rumah > pembangunan bahagian belakang > C++ > Bagaimanakah Kita Boleh Menukar Antara Integer Beregu dan 64-bit Dengan Cekap Menggunakan SSE2?

Bagaimanakah Kita Boleh Menukar Antara Integer Beregu dan 64-bit Dengan Cekap Menggunakan SSE2?

DDD
Lepaskan: 2024-12-04 10:55:11
asal
877 orang telah melayarinya

How Can We Efficiently Convert Between Doubles and 64-bit Integers Using SSE2?

Penukaran Double/Int64 yang Cekap tanpa AVX512

SSE2 menyediakan arahan untuk menukar antara apungan dan integer 32-bit, tetapi tidak mempunyai persamaan untuk menukar antara berganda dan integer 64-bit. Bagaimanakah kita boleh mensimulasikan penukaran sedemikian dengan cekap?

Penukaran Sudut Potong

Jika sekatan julat boleh diterima, helah berikut boleh melakukan penukaran hanya dalam dua arahan:

Berganda kepada Int64

__m128i double_to_int64(__m128d x) {
    x = _mm_add_pd(x, _mm_set1_pd(0x0018000000000000));
    return _mm_sub_epi64(_mm_castpd_si128(x), _mm_castpd_si128(_mm_set1_pd(0x0018000000000000)));
}
Salin selepas log masuk

Double kepada UInt64

__m128i double_to_uint64(__m128d x){
    x = _mm_add_pd(x, _mm_set1_pd(0x0010000000000000));
    return _mm_xor_si128(_mm_castpd_si128(x), _mm_castpd_si128(_mm_set1_pd(0x0010000000000000)));
}
Salin selepas log masuk

Int64 to Double

__m128d int64_to_double(__m128i x){
    x = _mm_add_epi64(x, _mm_castpd_si128(_mm_set1_pd(0x0018000000000000)));
    return _mm_sub_pd(_mm_castsi128_pd(x), _mm_set1_pd(0x0018000000000000));
}
Salin selepas log masuk

UInt64 ke Berganda

__m128d uint64_to_double(__m128i x){
    x = _mm_or_si128(x, _mm_castpd_si128(_mm_set1_pd(0x0010000000000000)));
    return _mm_sub_pd(_mm_castsi128_pd(x), _mm_set1_pd(0x0010000000000000));
}
Salin selepas log masuk

Penukaran Julat Penuh

Untuk penukaran yang mengendalikan julat penuh integer 64-bit, berikut ialah pelaksanaan yang dioptimumkan:

UInt64 ke Gandakan

__m128d uint64_to_double_full(__m128i x){
    __m128i xH = _mm_srli_epi64(x, 32);
    xH = _mm_or_si128(xH, _mm_castpd_si128(_mm_set1_pd(19342813113834066795298816.)));          //  2^84
    __m128i xL = _mm_blend_epi16(x, _mm_castpd_si128(_mm_set1_pd(0x0010000000000000)), 0xcc);   //  2^52
    __m128d f = _mm_sub_pd(_mm_castsi128_pd(xH), _mm_set1_pd(19342813118337666422669312.));     //  2^84 + 2^52
    return _mm_add_pd(f, _mm_castsi128_pd(xL));
}
Salin selepas log masuk

Int64 kepada Gandakan

__m128d int64_to_double_full(__m128i x){
    __m128i xH = _mm_srai_epi32(x, 16);
    xH = _mm_blend_epi16(xH, _mm_setzero_si128(), 0x33);
    xH = _mm_add_epi64(xH, _mm_castpd_si128(_mm_set1_pd(442721857769029238784.)));              //  3*2^67
    __m128i xL = _mm_blend_epi16(x, _mm_castpd_si128(_mm_set1_pd(0x0010000000000000)), 0x88);   //  2^52
    __m128d f = _mm_sub_pd(_mm_castsi128_pd(xH), _mm_set1_pd(442726361368656609280.));          //  3*2^67 + 2^52
    return _mm_add_pd(f, _mm_castsi128_pd(xL));
}
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimanakah Kita Boleh Menukar Antara Integer Beregu dan 64-bit Dengan Cekap Menggunakan SSE2?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan