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
1025 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!

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