1 #include <ncbi_pch.hpp>
2 #include "cqueryhash.hpp"
3 #include "chashpopulator.hpp"
4 #include "uinth.hpp"
5 #include "dust.hpp"
6
7 USING_OLIGOFAR_SCOPES;
8
ComputeComplexityNcbi8na(UintH w,int l,int & amb) const9 double CQueryHash::ComputeComplexityNcbi8na( UintH w, int l, int& amb ) const
10 {
11 CComplexityMeasure m;
12 int tripletid = 0;
13 amb = 0;
14 for( int i = 0; i < l; ++i, ( w >>= 4 ), (tripletid <<= 2) ) {
15 CNcbi8naBase b( char(( w.GetLo() ) & 0xf) );
16 amb += int( b.IsAmbiguous() );
17 tripletid |= b.GetSmallestNcbi2na();
18 if( i > 2 ) m.Add( tripletid & 0x3f );
19 }
20 return double( m );
21 }
22
ComputeAmbiguitiesNcbi8na(UintH w,int l) const23 int CQueryHash::ComputeAmbiguitiesNcbi8na( UintH w, int l ) const
24 {
25 int amb = 0;
26 for( int i = 0; i < l; ++i, ( w >>= 4 ) ) {
27 CNcbi8naBase b( char(( w.GetLo() ) & 0xf) );
28 amb += int( b.IsAmbiguous() );
29 }
30 return amb;
31 }
32
ComputeComplexityNcbi2na(Uint8 w,int l) const33 double CQueryHash::ComputeComplexityNcbi2na( Uint8 w, int l ) const
34 {
35 CComplexityMeasure m;
36 for( int i = 3; i < l; ++i, ( w >>= 2 ) ) m.Add( w & 0x3f );
37 return double( m );
38 }
39
PopulateInsertion2(CHashPopulator & dest,const UintH & maskH,const UintH & fwindow,int pos)40 void CQueryHash::PopulateInsertion2( CHashPopulator& dest, const UintH& maskH, const UintH& fwindow, int pos )
41 {
42 UintH ifbase = CBitHacks::InsertBits<UintH, 4, 0x0>( fwindow, pos );
43 ifbase = maskH & CBitHacks::InsertBits<UintH, 4, 0x0>( ifbase, pos );
44 UintH k1 = UintH( 1 ) << (pos*4);
45 UintH k2 = k1 << 4;
46 for( int i = 0; i < 4; ++i ) {
47 UintH b1 = k1 << i;
48 for( int j = 0; j < 4; ++j ) {
49 UintH b2 = k2 << j;
50 UintH ifwindow = b1|b2|ifbase;
51 dest.PopulateHash( ifwindow );
52 }
53 }
54 }
55
PopulateInsertion1(CHashPopulator & dest,const UintH & maskH,const UintH & fwindow,int pos)56 void CQueryHash::PopulateInsertion1( CHashPopulator& dest, const UintH& maskH, const UintH& fwindow, int pos )
57 {
58 UintH ifbase = maskH & CBitHacks::InsertBits<UintH, 4, 0x0>( fwindow, pos );
59 UintH k1 = UintH( 1 ) << (pos*4);
60 for( int i = 0; i < 4; ++i ) {
61 UintH b1 = k1 << i;
62 UintH ifwindow = b1|ifbase;
63 dest.PopulateHash( ifwindow );
64 }
65 }
66
PopulateDeletion2(CHashPopulator & dest,const UintH & maskH,const UintH & fwindow,int pos)67 void CQueryHash::PopulateDeletion2( CHashPopulator& dest, const UintH& maskH, const UintH& fwindow, int pos )
68 {
69 UintH dfwindow = CBitHacks::DeleteBits<UintH, 4>( fwindow, pos );
70 dfwindow = maskH & CBitHacks::DeleteBits<UintH, 4>( dfwindow, pos );
71 dest.PopulateHash( dfwindow );
72 }
73
PopulateDeletion1(CHashPopulator & dest,const UintH & maskH,const UintH & fwindow,int pos)74 void CQueryHash::PopulateDeletion1( CHashPopulator& dest, const UintH& maskH, const UintH& fwindow, int pos )
75 {
76 UintH dfwindow = maskH & CBitHacks::DeleteBits<UintH, 4>( fwindow, pos );
77 dest.PopulateHash( dfwindow );
78 }
79
80 static const int g_IndelMargin = 1;
81
PopulateInsertions(CHashPopulator & dest,const UintH & maskH,const UintH & fwindow)82 void CQueryHash::PopulateInsertions( CHashPopulator& dest, const UintH& maskH, const UintH& fwindow )
83 {
84 int pos0 = 1 - g_IndelMargin;
85 int pos1 = m_windowSize + m_strideSize - GetMaxInsertions() + g_IndelMargin;
86 switch( int ins = GetMaxInsertions() ) {
87 case 2:
88 dest.SetPermutator( m_permutators[min( GetMaxMismatches(), GetMaxDistance() - ins )] );
89 dest.SetIndels( ins, CHashAtom::eInsertion );
90 if( m_indelPos == eIndel_anywhere )
91 for( int pos = pos0; pos < pos1; ++pos ) PopulateInsertion2( dest, maskH, fwindow, pos );
92 else PopulateInsertion2( dest, maskH, fwindow, m_indelPos );
93 --ins;
94 case 1:
95 ++pos1;
96 dest.SetPermutator( m_permutators[min( GetMaxMismatches(), GetMaxDistance() - ins )] );
97 dest.SetIndels( ins, CHashAtom::eInsertion );
98 if( m_indelPos == eIndel_anywhere )
99 for( int pos = pos0; pos < pos1; ++pos ) PopulateInsertion1( dest, maskH, fwindow, pos );
100 else PopulateInsertion1( dest, maskH, fwindow, m_indelPos );
101 --ins;
102 case 0: break;
103 default: THROW( logic_error, "Maximal number of insertions may be only 0, 1, or 2, got " << ins );
104 }
105 }
106
PopulateDeletions(CHashPopulator & dest,const UintH & maskH,const UintH & fwindow)107 void CQueryHash::PopulateDeletions( CHashPopulator& dest, const UintH& maskH, const UintH& fwindow )
108 {
109 int pos0 = 1 - g_IndelMargin;
110 int pos1 = m_windowSize + m_strideSize + g_IndelMargin;
111 switch( int del = GetMaxDeletions() ) {
112 case 2:
113 dest.SetPermutator( m_permutators[min( GetMaxMismatches(), GetMaxDistance() - del )] );
114 dest.SetIndels( del, CHashAtom::eDeletion );
115 if( m_indelPos == eIndel_anywhere )
116 for( int pos = pos0; pos < pos1; ++pos ) PopulateDeletion2( dest, maskH, fwindow, pos );
117 else PopulateDeletion2( dest, maskH, fwindow, m_indelPos );
118 --del;
119 case 1:
120 dest.SetPermutator( m_permutators[min( GetMaxMismatches(), GetMaxDistance() - del )] );
121 dest.SetIndels( del, CHashAtom::eDeletion );
122 if( m_indelPos == eIndel_anywhere )
123 for( int pos = pos0; pos < pos1; ++pos ) PopulateDeletion1( dest, maskH, fwindow, pos );
124 else PopulateDeletion1( dest, maskH, fwindow, m_indelPos );
125 --del;
126 case 0: break;
127 default: THROW( logic_error, "Maximal number of deletions may be only 0, 1, or 2, got " << del );
128 }
129 }
130
PopulateWindow(CHashPopulator & hashPopulator,UintH fwindow,int offset,int ambiguities)131 int CQueryHash::PopulateWindow( CHashPopulator& hashPopulator, UintH fwindow, int offset, int ambiguities )
132 {
133 ASSERT( offset <= CHashAtom::GetMaxOffset() );
134 CompressFwd<UintH,4>( fwindow );
135
136 size_t reserve = size_t(
137 min( Uint8(numeric_limits<size_t>::max() ),
138 m_hashPopulatorReverve * ( Uint8( 1 ) << ( ambiguities * 2 ) ) ) );
139
140 hashPopulator.Reserve( hashPopulator.size() + reserve );
141
142 Uint2 w = m_windowSize + m_strideSize - 1;
143 UintH maskH = CBitHacks::WordFootprint<UintH>( 4 * w );
144
145 if( m_indelPos < w ) {
146 PopulateInsertions( hashPopulator, maskH, fwindow );
147 PopulateDeletions( hashPopulator, maskH, fwindow );
148 }
149
150 // no indels, just mismatches
151 hashPopulator.SetIndels( 0, CHashAtom::eNone );
152 hashPopulator.SetPermutator( m_permutators[GetMaxMismatches()] );
153 hashPopulator.PopulateHash( fwindow );
154 // hashPopulator.Unique();
155
156 // ITERATE( CHashPopulator, h, hashPopulator ) m_hashTable.AddEntry( h->first, h->second );
157
158 return hashPopulator.size();
159 }
160
x_AddQuery(CQuery * query,int component)161 int CQueryHash::x_AddQuery( CQuery * query, int component )
162 {
163 ASSERT( component == 0 || component == 1 );
164
165 int off = max(0, m_windowStart);
166 int maxWinCnt = m_skipPositions.size() ? 1 : m_maxWindowCount;
167 int wstep = GetHasherWindowStep();
168
169 return x_AddQuery( query, component, off, maxWinCnt, wstep );
170 }
171
x_AddQuery(CQuery * query,int component,int off,int maxWinCnt,int wstep)172 int CQueryHash::x_AddQuery( CQuery * query, int component, int off, int maxWinCnt, int wstep )
173 {
174 int len = query->GetLength( component );
175 if( len == 0 ) return 0;
176
177 if( len < m_windowLength ) {
178 query->SetRejectAsShort( component );
179 return 0; // too short read
180 }
181
182 int ret = 0;
183 for( int i = 0; i < maxWinCnt; ++i, (off += wstep) ) {
184 if( len - off < m_windowLength ) continue;
185
186 UintH fwindow = 0;
187 int offset = GetNcbi4na( fwindow, query->GetCoding(), (unsigned char*)query->GetData( component, off ), len - off );
188
189 if( offset < 0 ) {
190 query->SetRejectAsLoQual( component );
191 continue;
192 }
193 if( offset > CHashAtom::GetMaxOffset() ) break;
194
195 query->ClearRejectFlags( component );
196 int ambiguities = 0; //ComputeAmbiguitiesNcbi8na( fwindow, m_windowLength );
197 if( ComputeComplexityNcbi8na( fwindow, m_windowLength, ambiguities ) > m_maxSimplicity ) {
198 query->SetRejectAsLoCompl( component );
199 offset = -1;
200 }
201 if( ambiguities > m_maxAmb ) { query->SetRejectAsLoQual( component ); continue; }
202 if( offset < 0 ) continue;
203
204 offset += off;
205 if( offset >= CHashAtom::GetMaxOffset() ) break;
206 off = offset; // restart from this place - we don't know how far we should travel
207
208 CHashPopulator populator( m_windowSize, m_wordSize, m_strideSize, query,
209 m_strands, offset, component, CHashAtom::eConvEq,
210 m_wbmAccess );
211
212 if( m_nahso3mode ) {
213 if( query->GetCoding() != CSeqCoding::eCoding_colorsp ) {
214 UintH tcwin = x_Convert4tc( fwindow, m_windowLength );
215 UintH agwin = x_Convert4ag( fwindow, m_windowLength );
216 if( tcwin != agwin ) {
217 populator.SetConv( CHashAtom::eConvTC );
218 PopulateWindow( populator, tcwin, offset, ambiguities );
219 populator.SetConv( CHashAtom::eConvAG );
220 PopulateWindow( populator, agwin, offset, ambiguities );
221 } else {
222 populator.SetConv( CHashAtom::eConvEq );
223 PopulateWindow( populator, fwindow, offset, ambiguities );
224 }
225 } else {
226 populator.SetConv( CHashAtom::eConvEq );
227 PopulateWindow( populator, fwindow, offset, ambiguities );
228 }
229 } else {
230 populator.SetConv( CHashAtom::eNoConv );
231 PopulateWindow( populator, fwindow, offset, ambiguities );
232 }
233
234 populator.Unique();
235 // int loComplCount = 0;
236 // ITERATE( CHashPopulator, item, populator ) {
237 // double simpl = ComputeComplexityNcbi2na( item->first, m_windowLength );
238 // if( simpl > m_maxSimplicity ) loComplCount++;
239 // }
240 // if( loComplCount == 0 ) {
241 ITERATE( CHashPopulator, item, populator )
242 m_hashTable.AddEntry( item->first, item->second );
243 ret += populator.size();
244 // } else {
245 // query->SetRejectAsLoCompl( component );
246 // }
247 }
248
249 if( ret ) query->ClearRejectFlags( component );
250 return ret;
251 }
252
253 // this procedure tries to trim left ambiguity characters unless this introduces more severe ambiguities
x_GetNcbi4na_ncbi8na(UintH & window,const unsigned char * data,unsigned length)254 int CQueryHash::x_GetNcbi4na_ncbi8na( UintH& window, const unsigned char * data, unsigned length )
255 {
256 int off = 0;
257 const unsigned char * t = data;
258 unsigned wlen = m_windowLength;
259
260 ASSERT( wlen <= 32 );
261
262 for( int left = length - wlen; CanOptimizeOffset() && left > 0; --left, ++off, ++t ) {
263 if( CNcbi8naBase( t[0] ).GetAltCount() <= CNcbi8naBase( t[wlen] ).GetAltCount() )
264 break; // there is no benefit in shifting right
265 }
266 window = 0;
267
268 for( unsigned i = 0; i < wlen; ++i ) {
269 CNcbi8naBase b( t[i] );
270 UintH mask( b );
271 UintH smask( mask << int(i*4) );
272 window |= UintH( t[i] & 0x0f ) << int(i*4);
273 }
274 return off;
275 }
276
x_GetNcbi4na_colorsp(UintH & window,const unsigned char * data,unsigned length)277 int CQueryHash::x_GetNcbi4na_colorsp( UintH& window, const unsigned char * data, unsigned length )
278 {
279 // this encoding does not support ambiguities,
280 int off = 0;
281 const unsigned char * t = data;
282 unsigned wlen = m_windowLength;
283
284 ASSERT( wlen <= 32 );
285
286 for( int left = length - wlen; CanOptimizeOffset() && left > 0; --left, ++off, ++t ) {
287 if( CNcbi8naBase( t[0] ).GetAltCount() <= CNcbi8naBase( t[wlen] ).GetAltCount() )
288 break; // there is no benefit in shifting right
289 }
290 window = 0;
291 // to provide uniform hashing algo, conver colors to 4-channel 1-bit per channel sets
292 for( unsigned x = 0; x < wlen; ++x )
293 window |= UintH( "\x1\x2\x4\x8"[CColorTwoBase( data[x+1] ).GetColorOrd()] ) << int(x*4);
294
295 return 1; // always has offset of 1
296 }
297
298 // this procedure tries to perform optimization on number of alternatives
299 // if one is out of allowed range
x_GetNcbi4na_ncbipna(UintH & window,const unsigned char * data,unsigned length)300 int CQueryHash::x_GetNcbi4na_ncbipna( UintH& window, const unsigned char * data, unsigned length )
301 {
302 return x_GetNcbi4na_quality( window, data, length, x_Ncbipna2Ncbi4na, 5, m_ncbipnaToNcbi4naScore, x_UpdateNcbipnaScore );
303 }
304
x_GetNcbi4na_ncbiqna(UintH & window,const unsigned char * data,unsigned length)305 int CQueryHash::x_GetNcbi4na_ncbiqna( UintH& window, const unsigned char * data, unsigned length )
306 {
307 return x_GetNcbi4na_quality( window, data, length, x_Ncbiqna2Ncbi4na, 1, m_ncbiqnaToNcbi4naScore, x_UpdateNcbiqnaScore );
308 }
309
ComputeAlternatives(UintH w,int l) const310 UintH CQueryHash::ComputeAlternatives( UintH w, int l ) const
311 {
312 UintH alternatives = 1;
313 for( int i = 0; i < l; ++i, ( w >>= 4 ) ) {
314 CNcbi8naBase b( char(( w.GetLo() ) & 0xf) );
315 alternatives *= Uint1( b.GetAltCount() );
316 }
317 return alternatives;
318 }
319
x_GetNcbi4na_quality(UintH & window,const unsigned char * data,unsigned length,TCvt * fun,int incr,unsigned short score,TDecr * decr)320 int CQueryHash::x_GetNcbi4na_quality( UintH& window, const unsigned char * data, unsigned length, TCvt * fun, int incr, unsigned short score, TDecr * decr )
321 {
322 int off = 0;
323 const unsigned char * t = data;
324 int left = length - m_windowLength;
325 if( left < 0 ) return -1;
326
327 unsigned wlen = m_windowLength;
328 ASSERT( wlen <= 32 );
329
330 window = fun( t, wlen, score );
331 UintH ac = ComputeAlternatives( window, wlen );
332 UintH maxAlt = Uint8( 1 ) << ( m_maxAmb * 4 );
333
334 while( ac > maxAlt ) {
335 UintH aco = ~UintH(0);
336 UintH acm = ~UintH(0);
337 UintH owin = 0;
338 UintH mwin = 0;
339 if( CanOptimizeOffset() && left > 0 ) {
340 owin = fun( t + incr, wlen, score );
341 aco = ComputeAlternatives( owin, wlen );
342 }
343 if( score ) {
344 mwin = fun( t, wlen, decr( score ) );
345 acm = ComputeAlternatives( mwin, wlen );
346 }
347 if( aco == ~UintH(0) && acm == ~UintH(0) ) return off;
348 if( aco < maxAlt ) {
349 if( acm < maxAlt ) {
350 if( acm >= aco ) {
351 window = mwin;
352 return off;
353 } else {
354 window = owin;
355 return off + 1;
356 }
357 } else {
358 window = owin;
359 return off + 1;
360 }
361 } else if( acm < maxAlt ) {
362 window = mwin;
363 return off;
364 } else if( acm <= aco ) {
365 score = decr( score );
366 window = mwin;
367 ac = acm;
368 } else {
369 ++off;
370 if( --left < 0 ) return off;
371 t += incr;
372 window = owin;
373 ac = aco;
374 }
375 }
376
377 return off;
378 }
379
GetNcbi4na(UintH & window,CSeqCoding::ECoding coding,const unsigned char * data,unsigned length)380 int CQueryHash::GetNcbi4na( UintH& window, CSeqCoding::ECoding coding,
381 const unsigned char * data, unsigned length )
382 {
383 switch( coding ) {
384 case CSeqCoding::eCoding_ncbi8na: return x_GetNcbi4na_ncbi8na( window, data, length );
385 case CSeqCoding::eCoding_ncbiqna: return x_GetNcbi4na_ncbiqna( window, data, length );
386 case CSeqCoding::eCoding_ncbipna: return x_GetNcbi4na_ncbipna( window, data, length );
387 case CSeqCoding::eCoding_colorsp: return x_GetNcbi4na_colorsp( window, data, length );
388 default: THROW( logic_error, "Invalid query coding " << coding );
389 }
390 }
391
x_Ncbipna2Ncbi4na(const unsigned char * data,int len,unsigned short score)392 UintH CQueryHash::x_Ncbipna2Ncbi4na( const unsigned char * data, int len, unsigned short score )
393 {
394 UintH ret = 0;
395
396 for( int x = 0; x < len; ++x )
397 ret |= UintH( CNcbi8naBase( CNcbipnaBase( data + 5*x ), score ) ) << (x*4);
398
399 return ret;
400 }
401
x_Ncbiqna2Ncbi4na(const unsigned char * data,int len,unsigned short score)402 UintH CQueryHash::x_Ncbiqna2Ncbi4na( const unsigned char * data, int len, unsigned short score )
403 {
404 UintH ret = 0;
405
406 for( int x = 0; x < len; ++x )
407 ret |= UintH( CNcbi8naBase( CNcbiqnaBase( data[x] ), score ) ) << (x*4);
408
409 return ret;
410 }
411
Freeze()412 void CQueryHash::Freeze()
413 {
414 CheckConstraints();
415 ComputeScannerWindowLength();
416 m_hashTable.Sort();
417 m_status = eStatus_ready;
418 }
419
CheckConstraints()420 void CQueryHash::CheckConstraints()
421 {
422 if( m_wbmAccess ) {
423 if( m_wbmAccess->GetWordStep() > (Uint4)GetStrideSize() )
424 THROW( runtime_error, "Oops... hash word bitmap should have same stride size as query hash" );
425 if( GetWindowStep() % m_wbmAccess->GetWordStep() != 0 )
426 THROW( runtime_error, "Oops... hash word bitmap should have same stride size as query window step" );
427 if( m_windowStart && ( m_windowStart % m_wbmAccess->GetWordStep() != 0 ) )
428 THROW( runtime_error, "Oops... hash word bitmap should have same stride size as query window step" );
429 }
430 }
431
432 const unsigned char * CQueryHash::s_convert2eq = (const unsigned char *)
433 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
434 "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
435 "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
436 "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
437 "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
438 "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
439 "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
440 "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
441 "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
442 "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
443 "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
444 "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
445 "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
446 "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
447 "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
448 "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
449
450 const unsigned char * CQueryHash::s_convert2tc = (const unsigned char *)
451 "\x00\x01\x02\x01\x04\x05\x06\x05\x08\x09\x0a\x09\x04\x05\x06\x05"
452 "\x10\x11\x12\x11\x14\x15\x16\x15\x18\x19\x1a\x19\x14\x15\x16\x15"
453 "\x20\x21\x22\x21\x24\x25\x26\x25\x28\x29\x2a\x29\x24\x25\x26\x25"
454 "\x10\x11\x12\x11\x14\x15\x16\x15\x18\x19\x1a\x19\x14\x15\x16\x15"
455 "\x40\x41\x42\x41\x44\x45\x46\x45\x48\x49\x4a\x49\x44\x45\x46\x45"
456 "\x50\x51\x52\x51\x54\x55\x56\x55\x58\x59\x5a\x59\x54\x55\x56\x55"
457 "\x60\x61\x62\x61\x64\x65\x66\x65\x68\x69\x6a\x69\x64\x65\x66\x65"
458 "\x50\x51\x52\x51\x54\x55\x56\x55\x58\x59\x5a\x59\x54\x55\x56\x55"
459 "\x80\x81\x82\x81\x84\x85\x86\x85\x88\x89\x8a\x89\x84\x85\x86\x85"
460 "\x90\x91\x92\x91\x94\x95\x96\x95\x98\x99\x9a\x99\x94\x95\x96\x95"
461 "\xa0\xa1\xa2\xa1\xa4\xa5\xa6\xa5\xa8\xa9\xaa\xa9\xa4\xa5\xa6\xa5"
462 "\x90\x91\x92\x91\x94\x95\x96\x95\x98\x99\x9a\x99\x94\x95\x96\x95"
463 "\x40\x41\x42\x41\x44\x45\x46\x45\x48\x49\x4a\x49\x44\x45\x46\x45"
464 "\x50\x51\x52\x51\x54\x55\x56\x55\x58\x59\x5a\x59\x54\x55\x56\x55"
465 "\x60\x61\x62\x61\x64\x65\x66\x65\x68\x69\x6a\x69\x64\x65\x66\x65"
466 "\x50\x51\x52\x51\x54\x55\x56\x55\x58\x59\x5a\x59\x54\x55\x56\x55";
467
468 const unsigned char * CQueryHash::s_convert2ag = (const unsigned char *)
469 "\xaa\xa9\xaa\xab\xa6\xa5\xa6\xa7\xaa\xa9\xaa\xab\xae\xad\xae\xaf"
470 "\x9a\x99\x9a\x9b\x96\x95\x96\x97\x9a\x99\x9a\x9b\x9e\x9d\x9e\x9f"
471 "\xaa\xa9\xaa\xab\xa6\xa5\xa6\xa7\xaa\xa9\xaa\xab\xae\xad\xae\xaf"
472 "\xba\xb9\xba\xbb\xb6\xb5\xb6\xb7\xba\xb9\xba\xbb\xbe\xbd\xbe\xbf"
473 "\x6a\x69\x6a\x6b\x66\x65\x66\x67\x6a\x69\x6a\x6b\x6e\x6d\x6e\x6f"
474 "\x5a\x59\x5a\x5b\x56\x55\x56\x57\x5a\x59\x5a\x5b\x5e\x5d\x5e\x5f"
475 "\x6a\x69\x6a\x6b\x66\x65\x66\x67\x6a\x69\x6a\x6b\x6e\x6d\x6e\x6f"
476 "\x7a\x79\x7a\x7b\x76\x75\x76\x77\x7a\x79\x7a\x7b\x7e\x7d\x7e\x7f"
477 "\xaa\xa9\xaa\xab\xa6\xa5\xa6\xa7\xaa\xa9\xaa\xab\xae\xad\xae\xaf"
478 "\x9a\x99\x9a\x9b\x96\x95\x96\x97\x9a\x99\x9a\x9b\x9e\x9d\x9e\x9f"
479 "\xaa\xa9\xaa\xab\xa6\xa5\xa6\xa7\xaa\xa9\xaa\xab\xae\xad\xae\xaf"
480 "\xba\xb9\xba\xbb\xb6\xb5\xb6\xb7\xba\xb9\xba\xbb\xbe\xbd\xbe\xbf"
481 "\xea\xe9\xea\xeb\xe6\xe5\xe6\xe7\xea\xe9\xea\xeb\xee\xed\xee\xef"
482 "\xda\xd9\xda\xdb\xd6\xd5\xd6\xd7\xda\xd9\xda\xdb\xde\xdd\xde\xdf"
483 "\xea\xe9\xea\xeb\xe6\xe5\xe6\xe7\xea\xe9\xea\xeb\xee\xed\xee\xef"
484 "\xfa\xf9\xfa\xfb\xf6\xf5\xf6\xf7\xfa\xf9\xfa\xfb\xfe\xfd\xfe\xff";
485