/src/Simd/src/Simd/SimdSse41DescrInt.cpp
Line | Count | Source |
1 | | /* |
2 | | * Simd Library (http://ermig1979.github.io/Simd). |
3 | | * |
4 | | * Copyright (c) 2011-2026 Yermalayeu Ihar. |
5 | | * |
6 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | | * of this software and associated documentation files (the "Software"), to deal |
8 | | * in the Software without restriction, including without limitation the rights |
9 | | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
10 | | * copies of the Software, and to permit persons to whom the Software is |
11 | | * furnished to do so, subject to the following conditions: |
12 | | * |
13 | | * The above copyright notice and this permission notice shall be included in |
14 | | * all copies or substantial portions of the Software. |
15 | | * |
16 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
21 | | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
22 | | * SOFTWARE. |
23 | | */ |
24 | | #include "Simd/SimdMemory.h" |
25 | | #include "Simd/SimdStore.h" |
26 | | #include "Simd/SimdExtract.h" |
27 | | #include "Simd/SimdArray.h" |
28 | | #include "Simd/SimdUnpack.h" |
29 | | #include "Simd/SimdDescrInt.h" |
30 | | #include "Simd/SimdDescrIntCommon.h" |
31 | | #include "Simd/SimdCpu.h" |
32 | | #include "Simd/SimdFloat16.h" |
33 | | #include "Simd/SimdMax.h" |
34 | | |
35 | | namespace Simd |
36 | | { |
37 | | #ifdef SIMD_SSE41_ENABLE |
38 | | namespace Sse41 |
39 | | { |
40 | | static void MinMax32f(const float* src, size_t size, float& min, float& max) |
41 | 0 | { |
42 | 0 | assert(size % 8 == 0); |
43 | 0 | __m128 _min = _mm_set1_ps(FLT_MAX); |
44 | 0 | __m128 _max = _mm_set1_ps(-FLT_MAX); |
45 | 0 | size_t i = 0; |
46 | 0 | for (; i < size; i += 4) |
47 | 0 | { |
48 | 0 | __m128 _src = _mm_loadu_ps(src + i); |
49 | 0 | _min = _mm_min_ps(_src, _min); |
50 | 0 | _max = _mm_max_ps(_src, _max); |
51 | 0 | } |
52 | 0 | MinVal32f(_min, min); |
53 | 0 | MaxVal32f(_max, max); |
54 | 0 | } |
55 | | |
56 | | //------------------------------------------------------------------------------------------------- |
57 | | |
58 | | static void MinMax16f(const uint16_t* src, size_t size, float& min, float& max) |
59 | 0 | { |
60 | 0 | assert(size % 8 == 0); |
61 | 0 | __m128 _min = _mm_set1_ps(FLT_MAX); |
62 | 0 | __m128 _max = _mm_set1_ps(-FLT_MAX); |
63 | 0 | size_t i = 0; |
64 | 0 | for (; i < size; i += 4) |
65 | 0 | { |
66 | 0 | __m128i f16 = _mm_loadl_epi64((__m128i*)(src + i)); |
67 | 0 | __m128 _src = Float16ToFloat32(UnpackU16<0>(f16)); |
68 | 0 | _min = _mm_min_ps(_src, _min); |
69 | 0 | _max = _mm_max_ps(_src, _max); |
70 | 0 | } |
71 | 0 | MinVal32f(_min, min); |
72 | 0 | MaxVal32f(_max, max); |
73 | 0 | } |
74 | | |
75 | | //------------------------------------------------------------------------------------------------- |
76 | | |
77 | | static void UnpackNormA(size_t count, const uint8_t* const* src, float* dst, size_t stride) |
78 | 0 | { |
79 | 0 | for (size_t i = 0; i < count; ++i) |
80 | 0 | _mm_storeu_si128((__m128i*)dst + i, _mm_loadu_si128((__m128i*)src[i])); |
81 | 0 | } |
82 | | |
83 | | //------------------------------------------------------------------------------------------------- |
84 | | |
85 | | static void UnpackNormB(size_t count, const uint8_t* const* src, float* dst, size_t stride) |
86 | 0 | { |
87 | 0 | size_t count4 = AlignLo(count, 4), i = 0; |
88 | 0 | for (; i < count4; i += 4, src += 4, dst += 4) |
89 | 0 | { |
90 | 0 | __m128 s0 = _mm_loadu_ps((float*)src[0]); |
91 | 0 | __m128 s1 = _mm_loadu_ps((float*)src[1]); |
92 | 0 | __m128 s2 = _mm_loadu_ps((float*)src[2]); |
93 | 0 | __m128 s3 = _mm_loadu_ps((float*)src[3]); |
94 | 0 | __m128 s00 = _mm_unpacklo_ps(s0, s2); |
95 | 0 | __m128 s01 = _mm_unpacklo_ps(s1, s3); |
96 | 0 | __m128 s10 = _mm_unpackhi_ps(s0, s2); |
97 | 0 | __m128 s11 = _mm_unpackhi_ps(s1, s3); |
98 | 0 | _mm_storeu_ps(dst + 0 * stride, _mm_unpacklo_ps(s00, s01)); |
99 | 0 | _mm_storeu_ps(dst + 1 * stride, _mm_unpackhi_ps(s00, s01)); |
100 | 0 | _mm_storeu_ps(dst + 2 * stride, _mm_unpacklo_ps(s10, s11)); |
101 | 0 | _mm_storeu_ps(dst + 3 * stride, _mm_unpackhi_ps(s10, s11)); |
102 | 0 | } |
103 | 0 | for (; i < count; i++, src++, dst++) |
104 | 0 | { |
105 | 0 | dst[0 * stride] = ((float*)src[0])[0]; |
106 | 0 | dst[1 * stride] = ((float*)src[0])[1]; |
107 | 0 | dst[2 * stride] = ((float*)src[0])[2]; |
108 | 0 | dst[3 * stride] = ((float*)src[0])[3]; |
109 | 0 | } |
110 | 0 | } |
111 | | |
112 | | //------------------------------------------------------------------------------------------------- |
113 | | |
114 | | DescrInt::DescrInt(size_t size, size_t depth) |
115 | 0 | : Base::DescrInt(size, depth) |
116 | 0 | { |
117 | 0 | _minMax32f = MinMax32f; |
118 | 0 | _minMax16f = MinMax16f; |
119 | 0 | _encode32f = GetEncode32f(_depth); |
120 | 0 | _encode16f = GetEncode16f(_depth); |
121 | |
|
122 | 0 | _decode32f = GetDecode32f(_depth); |
123 | 0 | _decode16f = GetDecode16f(_depth); |
124 | |
|
125 | 0 | _cosineDistance = GetCosineDistance(_depth); |
126 | 0 | _macroCosineDistancesDirect = GetMacroCosineDistancesDirect(_depth); |
127 | 0 | _microMd = 2; |
128 | 0 | _microNd = 4; |
129 | |
|
130 | 0 | _unpackNormA = UnpackNormA; |
131 | 0 | _unpackNormB = UnpackNormB; |
132 | 0 | _unpackDataA = GetUnpackData(_depth, false); |
133 | 0 | _unpackDataB = GetUnpackData(_depth, true); |
134 | 0 | _macroCosineDistancesUnpack = GetMacroCosineDistancesUnpack(_depth); |
135 | 0 | _unpSize = _size * (_depth == 8 ? 2 : 1); |
136 | 0 | _microMu = _depth == 8 ? 6 : 5; |
137 | 0 | _microNu = 8; |
138 | 0 | } |
139 | | |
140 | | //------------------------------------------------------------------------------------------------- |
141 | | |
142 | | void* DescrIntInit(size_t size, size_t depth) |
143 | 0 | { |
144 | 0 | if (!Base::DescrInt::Valid(size, depth)) |
145 | 0 | return NULL; |
146 | 0 | return new Sse41::DescrInt(size, depth); |
147 | 0 | } |
148 | | } |
149 | | #endif |
150 | | } |