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