MCPcopy Create free account
hub / github.com/OpenGene/fastp / ReverseComplementImpl

Function ReverseComplementImpl

src/simd.cpp:121–160  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

119}
120
121void ReverseComplementImpl(const char* src, char* dst, int len) {
122 const hn::ScalableTag<uint8_t> d;
123 const int N = hn::Lanes(d);
124
125 // Complement via single table lookup on low nibble of ASCII code.
126 // DNA base low nibbles: A/a=1, C/c=3, T/t=4, G/g=7, N=14.
127 // Uppercase and lowercase share the same low nibble, so one table
128 // handles both. Unmapped nibbles default to 'N'.
129 HWY_ALIGN static const uint8_t kComplement[16] = {
130 'N', 'T', 'N', 'G', 'A', 'N', 'N', 'C',
131 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N'
132 };
133 const auto table = hn::LoadDup128(d, kComplement);
134 const auto vMask = hn::Set(d, static_cast<uint8_t>(0x0F));
135
136 int i = 0;
137 for (; i + N <= len; i += N) {
138 const auto v = hn::LoadU(d, reinterpret_cast<const uint8_t*>(src + i));
139 const auto indices = hn::And(v, vMask);
140 const auto comp = hn::TableLookupBytes(table, indices);
141
142 // Reverse and store at mirrored position
143 const auto revComp = hn::Reverse(d, comp);
144 hn::StoreU(revComp, d, reinterpret_cast<uint8_t*>(dst + len - i - N));
145 }
146
147 // Scalar tail
148 for (; i < len; i++) {
149 char base = src[i];
150 char comp;
151 switch (base) {
152 case 'A': case 'a': comp = 'T'; break;
153 case 'T': case 't': comp = 'A'; break;
154 case 'C': case 'c': comp = 'G'; break;
155 case 'G': case 'g': comp = 'C'; break;
156 default: comp = 'N'; break;
157 }
158 dst[len - 1 - i] = comp;
159 }
160}
161
162int CountAdjacentDiffsImpl(const char* data, int len) {
163 if (len <= 1) return 0;

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected