1 /****
2 DIAMOND protein aligner
3 Copyright (C) 2016-2020 Max Planck Society for the Advancement of Science e.V.
4                         Benjamin Buchfink
5 
6 Code developed by Benjamin Buchfink <benjamin.buchfink@tue.mpg.de>
7 
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 ****/
21 
22 #pragma once
23 #include "../util/simd.h"
24 #include "../basic/config.h"
25 
26 #ifdef __AVX2__
27 
28 struct Byte_finger_print_32
29 {
Byte_finger_print_32Byte_finger_print_3230 	Byte_finger_print_32(const Letter* q) :
31 #ifdef SEQ_MASK
32 		r1(letter_mask(_mm256_loadu_si256((__m256i const*)(q - 16))))
33 #else
34 		r1(_mm256_loadu_si256((__m256i const*)(q - 16)))
35 #endif
36 	{}
match_blockByte_finger_print_3237 	static uint64_t match_block(__m256i x, __m256i y)
38 	{
39 		return (uint64_t)_mm256_movemask_epi8(_mm256_cmpeq_epi8(x, y));
40 	}
matchByte_finger_print_3241 	unsigned match(const Byte_finger_print_32& rhs) const
42 	{
43 		return popcount64(match_block(r1, rhs.r1));
44 	}
45 	__m256i r1;
46 };
47 
48 struct Byte_finger_print_64
49 {
Byte_finger_print_64Byte_finger_print_6450 	Byte_finger_print_64(const Letter* q) :
51 #ifdef SEQ_MASK
52 		r1(letter_mask(_mm256_loadu_si256((__m256i const*)(q - 32)))),
53 		r2(letter_mask(_mm256_loadu_si256((__m256i const*)q)))
54 #else
55 		r1(_mm256_loadu_si256((__m256i const*)(q - 32))),
56 		r2(_mm256_loadu_si256((__m256i const*)q))
57 #endif
58 	{}
match_blockByte_finger_print_6459 	static uint64_t match_block(__m256i x, __m256i y)
60 	{
61 		return (uint64_t)_mm256_movemask_epi8(_mm256_cmpeq_epi8(x, y));
62 	}
matchByte_finger_print_6463 	unsigned match(const Byte_finger_print_64& rhs) const
64 	{
65 		return popcount64(match_block(r1, rhs.r1) << 32 | match_block(r2, rhs.r2));
66 	}
67 	__m256i r1, r2;
68 };
69 
70 #endif
71 
72 #ifdef __SSE2__
73 
74 struct Byte_finger_print_48
75 {
Byte_finger_print_48Byte_finger_print_4876 	Byte_finger_print_48(const Letter *q) :
77 #ifdef SEQ_MASK
78 		r1(letter_mask(_mm_loadu_si128((__m128i const*)(q - 16)))),
79 		r2(letter_mask(_mm_loadu_si128((__m128i const*)(q)))),
80 		r3(letter_mask(_mm_loadu_si128((__m128i const*)(q + 16))))
81 #else
82 		r1(_mm_loadu_si128((__m128i const*)(q - 16))),
83 		r2(_mm_loadu_si128((__m128i const*)(q))),
84 		r3(_mm_loadu_si128((__m128i const*)(q + 16)))
85 #endif
86 	{}
match_blockByte_finger_print_4887 	static uint64_t match_block(__m128i x, __m128i y)
88 	{
89 		return (uint64_t)_mm_movemask_epi8(_mm_cmpeq_epi8(x, y));
90 	}
matchByte_finger_print_4891 	unsigned match(const Byte_finger_print_48 &rhs) const
92 	{
93 		return popcount64(match_block(r3, rhs.r3) << 32 | match_block(r1, rhs.r1) << 16 | match_block(r2, rhs.r2));
94 	}
95 	alignas(16) __m128i r1, r2, r3;
96 };
97 
98 #else
99 
100 struct Byte_finger_print_48
101 {
Byte_finger_print_48Byte_finger_print_48102 	Byte_finger_print_48()
103 	{}
Byte_finger_print_48Byte_finger_print_48104 	Byte_finger_print_48(const Letter *q)
105 	{
106 		//printf("%llx\n", q);
107 		memcpy(r, q - 16, 48);
108 #ifdef SEQ_MASK
109 		for (int i = 0; i < 48; ++i)
110 			r[i] &= LETTER_MASK;
111 #endif
112 	}
matchByte_finger_print_48113 	unsigned match(const Byte_finger_print_48 &rhs) const
114 	{
115 		unsigned n = 0;
116 		for (unsigned i = 0; i < 48; ++i)
117 			if (r[i] == rhs.r[i])
118 				++n;
119 		return n;
120 	}
121 	Letter r[48];
122 	//char r[32];
123 };
124 
125 #endif
126 
127 #ifdef __AVX2__
128 typedef Byte_finger_print_48 FingerPrint;
129 #else
130 typedef Byte_finger_print_48 FingerPrint;
131 #endif