sequtil_manip.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:18k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: sequtil_manip.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:42:20  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: sequtil_manip.cpp,v 1000.1 2004/06/01 19:42:20 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Mati Shomrat
  35.  *
  36.  * File Description:
  37.  * 
  38.  */   
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbistd.hpp>
  41. #include <corelib/ncbistr.hpp>
  42. #include <vector>
  43. #include <algorithm>
  44. #include <util/sequtil/sequtil.hpp>
  45. #include <util/sequtil/sequtil_expt.hpp>
  46. #include <util/sequtil/sequtil_manip.hpp>
  47. #include <util/sequtil/sequtil_convert.hpp>
  48. #include "sequtil_shared.hpp"
  49. #include "sequtil_tables.hpp"
  50. BEGIN_NCBI_SCOPE
  51. /////////////////////////////////////////////////////////////////////////////
  52. //
  53. // Reverse
  54. // When reversing a sequence the packed formats ncbi2na and ncbi4na 
  55. // get "special" treatment, since the requesetd interval might not
  56. // fall on a byte boundry.
  57. // Other formats perform a simple conversion on the sequence. Note that
  58. // if the original sequnece is erroneous (e.g. lower case) the reverse
  59. // isn't "fixed". 
  60. static SIZE_TYPE s_2naReverse
  61. (const char* src,
  62.  TSeqPos pos,
  63.  TSeqPos length,
  64.  char* dst)
  65. {
  66.     const char* begin = src + (pos / 4);
  67.     const char* end   = src + ((pos + length - 1) / 4) + 1;
  68.     const char* iter = end;
  69.     size_t offset = (pos + length - 1) % 4;
  70.     const Uint1* table = C2naReverse::GetTable(offset);
  71.     if ( offset == 3 ) { // byte boundry when viewed from the end
  72.         for ( ; iter != begin; ++dst ) {
  73.             *dst = table[static_cast<Uint1>(*--iter)];
  74.         }
  75.         --dst;
  76.     } else {
  77.         --iter;
  78.         for ( size_t count = length / 4;  count; --count, ++dst ) {
  79.             *dst = 
  80.                 table[static_cast<Uint1>(*iter) * 2 + 1] |
  81.                 table[static_cast<Uint1>(*(iter - 1)) * 2];
  82.             --iter;
  83.         }
  84.         // handle the overhang
  85.         if ( length % 4 != 0 ) {
  86.             *dst = table[static_cast<Uint1>(*iter) * 2 + 1];
  87.             if ( iter != begin ) {
  88.                 --iter;
  89.                 *dst |= table[static_cast<Uint1>(*iter) * 2];
  90.             }
  91.         }
  92.     }
  93.     // now, take care of the last byte
  94.     *dst &= (0xFF << ((4 - (length % 4)) % 4) * 2);
  95.     return length;
  96. }
  97. static SIZE_TYPE s_4naReverse
  98. (const char* src,
  99.  TSeqPos pos,
  100.  TSeqPos length,
  101.  char* dst)
  102. {
  103.     size_t start_offset = (pos + length - 1) % 2;
  104.     const Uint1* table = C4naReverse::GetTable();
  105.     
  106.     const char* begin = src + (pos / 2);
  107.     const char* end   = src + ((pos + length - 1) / 2) + 1;
  108.     const char* iter = end;
  109.     switch ( start_offset ) {
  110.     case 1:
  111.         // byte boundry
  112.         {{
  113.             for ( ; iter != begin; ++dst ) {
  114.                 *dst = table[static_cast<Uint1>(*--iter)];
  115.             }
  116.             --dst;
  117.             if ( length % 2 != 0 ) {
  118.                 *dst &= 0xF0;
  119.             }
  120.         }}
  121.         break;
  122.     case 0:
  123.         {{
  124.             for ( size_t count = length / 2; count; --count, ++dst ) {
  125.                 --iter;
  126.                 *dst = (static_cast<Uint1>(*iter) & 0xF0) |
  127.                          (static_cast<Uint1>(*(iter - 1)) & 0x0F);
  128.             }
  129.             if ( length % 2 != 0 ) {
  130.                 --iter;
  131.                 *dst = static_cast<Uint1>(*iter) & 0xF0;
  132.             }
  133.         }}
  134.         break;
  135.     }
  136.     return length;
  137. }
  138. template <typename SrcCont, typename DstCont>
  139. SIZE_TYPE s_Reverse
  140. (const SrcCont& src, 
  141.  CSeqUtil::TCoding src_coding,
  142.  TSeqPos pos,
  143.  TSeqPos length,
  144.  DstCont& dst)
  145. {
  146.     _ASSERT(!OutOfRange(pos, src, src_coding));
  147.     if ( src.empty()  ||  (length == 0) ) {
  148.         return 0;
  149.     }
  150.     
  151.     AdjustLength(src, src_coding, pos, length);
  152.     ResizeDst(dst, src_coding, length);
  153.     return CSeqManip::Reverse(&*src.begin(), src_coding,
  154.                               pos, length, &*dst.begin());
  155. }
  156. SIZE_TYPE CSeqManip::Reverse
  157. (const string& src,
  158.  TCoding src_coding,
  159.  TSeqPos pos,
  160.  TSeqPos length,
  161.  string& dst)
  162. {
  163.     // call the templated version
  164.     return s_Reverse(src, src_coding, pos, length, dst);
  165. }
  166. SIZE_TYPE CSeqManip::Reverse
  167. (const vector<char>& src,
  168.  TCoding coding,
  169.  TSeqPos pos,
  170.  TSeqPos length,
  171.  vector<char>& dst)
  172. {
  173.     // call the templated version
  174.     return s_Reverse(src, coding,pos, length, dst);
  175. }
  176. SIZE_TYPE CSeqManip::Reverse
  177. (const char* src,
  178.  TCoding src_coding,
  179.  TSeqPos pos,
  180.  TSeqPos length,
  181.  char* dst)
  182. {
  183.     _ASSERT((dst != 0)  &&  (src != 0));
  184.     switch ( src_coding ) {
  185.     // "special" treatment
  186.     case CSeqUtil::e_Ncbi2na:
  187.         return s_2naReverse(src, pos, length, dst);
  188.     case CSeqUtil::e_Ncbi4na:
  189.         return s_4naReverse(src, pos, length, dst);
  190.     // a simple reverse
  191.     default:
  192.         reverse_copy(src + pos, src + pos + length, dst);
  193.         return length;
  194.     }
  195.     NCBI_THROW(CSeqUtilException, eInvalidCoding, "Unknown coding");
  196. }
  197. /////////////////////////////////////////////////////////////////////////////
  198. //
  199. // Complement
  200. template <typename SrcCont, typename DstCont>
  201. SIZE_TYPE s_Complement
  202. (const SrcCont& src, 
  203.  CSeqUtil::TCoding src_coding,
  204.  TSeqPos pos,
  205.  TSeqPos length,
  206.  DstCont& dst)
  207. {
  208.     _ASSERT(!OutOfRange(pos, src, src_coding));
  209.     if ( src.empty()  ||  (length == 0) ) {
  210.         return 0;
  211.     }
  212.     
  213.     AdjustLength(src, src_coding, pos, length);
  214.     ResizeDst(dst, src_coding, length);
  215.     return CSeqManip::Complement(&*src.begin(), src_coding,
  216.                                  pos, length, &*dst.begin());
  217. }
  218. SIZE_TYPE CSeqManip::Complement
  219. (const string& src,
  220.  TCoding coding,
  221.  TSeqPos pos,
  222.  TSeqPos length,
  223.  string& dst)
  224. {
  225.     // call the templated version
  226.     return s_Complement(src, coding,pos, length, dst);
  227. }
  228. SIZE_TYPE CSeqManip::Complement
  229. (const vector<char>& src,
  230.  TCoding coding,
  231.  TSeqPos pos,
  232.  TSeqPos length,
  233.  vector<char>& dst)
  234. {
  235.     // call the templated version
  236.     return s_Complement(src, coding,pos, length, dst);
  237. }
  238. static SIZE_TYPE s_Ncbi2naComplement
  239. (const char* src,
  240.  TSeqPos pos,
  241.  TSeqPos length,
  242.  char* dst)
  243. {
  244.     const char* iter = src + (pos / 4);
  245.     const char* end  = src + ((pos + length - 1) / 4) + 1;
  246.     if ( pos % 4 == 0 ) {
  247.         for ( ; iter != end; ++iter, ++dst ) {
  248.             *dst = ~(*iter);
  249.         }
  250.         if ( length % 4 != 0 ) {
  251.             *(--dst) &= (0xFF << (8 - (length % 4) * 2));
  252.         }
  253.     } else {
  254.         const Uint1* table = C2naCmp::GetTable(pos % 4);
  255.         for ( size_t count = length / 4;  count; --count, ++dst, ++iter ) {
  256.             *dst= 
  257.                 table[static_cast<Uint1>(*iter) * 2] |
  258.                 table[static_cast<Uint1>(*(iter + 1)) * 2 + 1];
  259.         }
  260.         // handle the overhang
  261.         if ( length % 4 != 0 ) {
  262.             *dst = table[static_cast<Uint1>(*iter) * 2];
  263.             if ( ++iter != end ) {
  264.                 *dst |= table[static_cast<Uint1>(*iter) * 2 + 1];
  265.             }
  266.         }
  267.     }
  268.     // now, take care of the last byte
  269.     *dst &= (0xFF << ((4 - (length % 4)) % 4) * 2);
  270.     return length;
  271. }
  272. static SIZE_TYPE s_Ncbi2naExpandComplement
  273. (const char* src,
  274.  TSeqPos pos,
  275.  TSeqPos length,
  276.  char* dst)
  277. {
  278.     const char* end  = src + pos + length;
  279.     const char* iter = src + pos;
  280.     for ( ; iter != end; ++iter, ++dst ) {
  281.         *dst = 3 - static_cast<Uint1>(*iter);
  282.     }
  283.     return length;
  284. }
  285. static SIZE_TYPE s_Ncbi4naComplement
  286. (const char* src,
  287.  TSeqPos pos,
  288.  TSeqPos length,
  289.  char* dst)
  290. {
  291.     const char* iter = src + (pos / 2);
  292.     const char* end  = src + (pos + length - 1) / 2 + 1;
  293.     const Uint1* table = C4naCmp::GetTable(pos % 2);
  294.     switch ( pos % 2 ) {
  295.     case 0:
  296.         {{
  297.             for ( ; iter != end; ++iter, ++dst ) {
  298.                 *dst = table[static_cast<Uint1>(*iter)];
  299.             }
  300.             if ( length % 2 != 0 ) {
  301.                 *dst &= 0xF0;
  302.             }
  303.         }}
  304.         break;
  305.     case 1:
  306.         {{
  307.             for ( size_t count = length / 2;  count; --count, ++iter, ++dst ) {
  308.                 *dst =
  309.                     table[static_cast<Uint1>(*iter) * 2] |
  310.                     table[static_cast<Uint1>(*(iter + 1)) * 2 + 1];
  311.             }
  312.             if ( length % 2 != 0 ) {
  313.                 *dst = table[static_cast<Uint1>(*iter) * 2];
  314.             }
  315.         }}
  316.         break;
  317.     }
  318.     return length;
  319. }
  320. SIZE_TYPE CSeqManip::Complement
  321. (const char* src,
  322.  TCoding src_coding,
  323.  TSeqPos pos,
  324.  TSeqPos length,
  325.  char* dst)
  326. {
  327.     _ASSERT((dst != 0)  &&  (src != 0));
  328.     switch ( src_coding ) {
  329.     case CSeqUtil::e_Iupacna:
  330.         return convert_1_to_1(src, pos, length, dst, CIupacnaCmp::GetTable());
  331.     case CSeqUtil::e_Ncbi2na:
  332.         return s_Ncbi2naComplement(src, pos, length, dst);
  333.     case CSeqUtil::e_Ncbi2na_expand:
  334.         return s_Ncbi2naExpandComplement(src, pos, length, dst);
  335.     case CSeqUtil::e_Ncbi4na:
  336.         return s_Ncbi4naComplement(src, pos, length, dst);
  337.     case CSeqUtil::e_Ncbi8na:
  338.     case CSeqUtil::e_Ncbi4na_expand:
  339.         return convert_1_to_1(src, pos, length, dst, C8naCmp::GetTable());
  340.     }
  341.     NCBI_THROW(CSeqUtilException, eInvalidCoding,
  342.         "There is no complement for the specified coding.");
  343. }
  344. /////////////////////////////////////////////////////////////////////////////
  345. //
  346. // ReverseComplement
  347. template <typename SrcCont, typename DstCont>
  348. SIZE_TYPE s_ReverseComplement
  349. (const SrcCont& src, 
  350.  CSeqUtil::TCoding src_coding,
  351.  TSeqPos pos,
  352.  TSeqPos length,
  353.  DstCont& dst)
  354. {
  355.     _ASSERT(!OutOfRange(pos, src, src_coding));
  356.     if ( src.empty()  ||  (length == 0) ) {
  357.         return 0;
  358.     }
  359.     
  360.     AdjustLength(src, src_coding, pos, length);
  361.     ResizeDst(dst, src_coding, length);
  362.     return CSeqManip::ReverseComplement(&*src.begin(), src_coding, 
  363.                                         pos, length, &*dst.begin());
  364. }
  365. SIZE_TYPE CSeqManip::ReverseComplement
  366. (const string& src,
  367.  TCoding coding,
  368.  TSeqPos pos,
  369.  TSeqPos length,
  370.  string& dst)
  371. {
  372.     // call the templated version
  373.     return s_ReverseComplement(src, coding,pos, length, dst);
  374. }
  375. SIZE_TYPE CSeqManip::ReverseComplement
  376. (const vector<char>& src,
  377.  TCoding coding,
  378.  TSeqPos pos,
  379.  TSeqPos length,
  380.  vector<char>& dst)
  381. {
  382.     // call the templated version
  383.     return s_ReverseComplement(src, coding,pos, length, dst);
  384. }
  385. static SIZE_TYPE s_Ncbi2naRevCmp
  386. (const char* src,
  387.  TSeqPos pos,
  388.  TSeqPos length,
  389.  char* dst)
  390. {
  391.     size_t offset = (pos + length - 1) % 4;
  392.     const Uint1* table = C2naRevCmp::GetTable(offset);
  393.     const char* begin = src + (pos / 4);
  394.     const char* iter = src + (pos + length - 1) / 4 + 1;
  395.     switch ( offset ) {
  396.     case 0:
  397.     case 1:
  398.     case 2:
  399.         --iter;
  400.         for ( size_t count = length / 4;  count; --count, ++dst, --iter ) {
  401.             *dst = 
  402.                 table[static_cast<Uint1>(*iter) * 2] |
  403.                 table[static_cast<Uint1>(*(iter - 1)) * 2 + 1];
  404.         }
  405.         // handle the overhang
  406.         if ( length % 4 != 0 ) {
  407.             *dst = table[static_cast<Uint1>(*iter) * 2];
  408.             if ( iter != begin ) {
  409.                 --iter;
  410.                 *dst |= table[static_cast<Uint1>(*iter) * 2 + 1];
  411.             }
  412.         }
  413.         break;
  414.     case 3:
  415.         // aligned operation
  416.         for ( ; iter != begin; ++dst ) {
  417.             *dst = table[static_cast<Uint1>(*--iter)];
  418.         }
  419.         break;
  420.     }
  421.     // zero redundent bits
  422.     *dst &= (0xFF << ((4 - (length % 4)) % 4) * 2);
  423.     return length;
  424. }
  425. static SIZE_TYPE s_Ncbi2naExpandRevCmp
  426. (const char* src,
  427.  TSeqPos pos,
  428.  TSeqPos length,
  429.  char* dst)
  430. {
  431.     const char* begin = src + pos;
  432.     const char* iter  = src + pos + length;
  433.     for ( ; iter != begin; ++dst ) {
  434.         *dst = 3 - static_cast<Uint1>(*--iter);
  435.     }
  436.     return length;
  437. }
  438. static SIZE_TYPE s_Ncbi4naRevCmp
  439. (const char* src,
  440.  TSeqPos pos,
  441.  TSeqPos length,
  442.  char* dst)
  443. {
  444.     const char* begin = src + (pos / 2);
  445.     const char* iter  = src + ((pos + length - 1) / 2) + 1;
  446.     size_t offset = (pos + length - 1) % 2;
  447.     const Uint1* table = C4naRevCmp::GetTable(offset);
  448.     switch ( offset ) {
  449.     case 0:
  450.         {{
  451.             --iter;
  452.             for ( size_t count = length / 2;  count; --count, --iter, ++dst ) {
  453.                 *dst =
  454.                     table[static_cast<Uint1>(*iter) * 2] |
  455.                     table[static_cast<Uint1>(*(iter - 1)) * 2 + 1];
  456.             }
  457.             if ( length % 2 != 0 ) {
  458.                 *dst = table[static_cast<Uint1>(*iter) * 2];
  459.             }
  460.         }}
  461.         break;
  462.     case 1:
  463.         {{
  464.             for ( ; iter != begin; ++dst ) {
  465.                 *dst = table[static_cast<Uint1>(*--iter)];
  466.             }
  467.             if ( length % 2 != 0 ) {
  468.                 *dst &= 0xF0;
  469.             }
  470.         }}
  471.         break;
  472.     }
  473.     return length;
  474. }
  475. SIZE_TYPE CSeqManip::ReverseComplement
  476. (const char* src,
  477.  TCoding src_coding,
  478.  TSeqPos pos,
  479.  TSeqPos length,
  480.  char* dst)
  481. {
  482.     _ASSERT((dst != 0)  &&  (src != 0));
  483.     switch ( src_coding ) {
  484.     case CSeqUtil::e_Iupacna:
  485.         return copy_1_to_1_reverse(src, pos, length, dst, 
  486.                                    CIupacnaCmp::GetTable());
  487.     case CSeqUtil::e_Ncbi2na:
  488.         return s_Ncbi2naRevCmp(src, pos, length, dst);
  489.     case CSeqUtil::e_Ncbi2na_expand:
  490.         return s_Ncbi2naExpandRevCmp(src, pos, length, dst);
  491.     case CSeqUtil::e_Ncbi4na:
  492.         return s_Ncbi4naRevCmp(src, pos, length, dst);
  493.     case CSeqUtil::e_Ncbi8na:
  494.     case CSeqUtil::e_Ncbi4na_expand:
  495.         return copy_1_to_1_reverse(src, pos, length, dst, 
  496.                                    C8naCmp::GetTable());
  497.     }
  498.     NCBI_THROW(CSeqUtilException, eInvalidCoding,
  499.         "There is no complement for the specified coding.");
  500. }
  501. // in place
  502. template <typename SrcCont>
  503. SIZE_TYPE s_ReverseComplement
  504. (SrcCont& src, 
  505.  CSeqUtil::TCoding src_coding,
  506.  TSeqPos pos,
  507.  TSeqPos length)
  508. {
  509.     _ASSERT(!OutOfRange(pos, src, src_coding));
  510.     if ( src.empty()  ||  (length == 0) ) {
  511.         return 0;
  512.     }
  513.     
  514.     AdjustLength(src, src_coding, pos, length);
  515.     return CSeqManip::ReverseComplement(&*src.begin(), src_coding,
  516.                                         pos, length);
  517. }
  518. SIZE_TYPE CSeqManip::ReverseComplement
  519. (string& src,
  520.  TCoding src_coding,
  521.  TSeqPos pos,
  522.  TSeqPos length)
  523. {
  524.     // call the templated version
  525.     return s_ReverseComplement(src, src_coding, pos, length);
  526. }
  527. SIZE_TYPE CSeqManip::ReverseComplement
  528. (vector<char>& src,
  529.  TCoding src_coding,
  530.  TSeqPos pos,
  531.  TSeqPos length)
  532. {
  533.     // call the templated version
  534.     return s_ReverseComplement(src, src_coding, pos, length);
  535. }
  536. static SIZE_TYPE s_Ncbi2naExpandRevCmp
  537. (char* src,
  538.  TSeqPos pos,
  539.  TSeqPos length)
  540. {
  541.     char* first = src + pos;
  542.     char* last  = first + length;
  543.     char temp;
  544.     for ( ; first <= last; ++first, --last ) {
  545.         temp = 3 - *first;
  546.         *first = 3 - *last;
  547.         *last = temp;
  548.     }
  549.     if ( pos != 0 ) {
  550.         copy(src + pos, src + pos + length, src);
  551.     }
  552.     return length;
  553. }
  554. static SIZE_TYPE s_Ncbi2naRevCmp
  555. (char* src,
  556.  TSeqPos pos,
  557.  TSeqPos length)
  558. {
  559.     char* buf = new char(length);
  560.     CSeqConvert::Convert(src, CSeqUtil::e_Ncbi2na, pos, length, 
  561.         buf, CSeqUtil::e_Ncbi2na_expand);
  562.     s_Ncbi2naExpandRevCmp(buf, 0, length);
  563.     CSeqConvert::Convert(buf, CSeqUtil::e_Ncbi2na_expand, 0, length, 
  564.         src, CSeqUtil::e_Ncbi2na);
  565.     delete[] buf;
  566.     return length;
  567. }
  568. static SIZE_TYPE s_Ncbi4naRevCmp
  569. (char* src,
  570.  TSeqPos pos,
  571.  TSeqPos length)
  572. {
  573.     char* buf = new char(length);
  574.     CSeqConvert::Convert(src, CSeqUtil::e_Ncbi4na, pos, length, 
  575.         buf, CSeqUtil::e_Ncbi8na);
  576.     revcmp(buf, pos, length, C8naCmp::GetTable());
  577.     CSeqConvert::Convert(buf, CSeqUtil::e_Ncbi8na, 0, length, 
  578.         src, CSeqUtil::e_Ncbi4na);
  579.     delete[] buf;
  580.     return length;
  581. }
  582. SIZE_TYPE CSeqManip::ReverseComplement
  583. (char* src,
  584.  TCoding src_coding,
  585.  TSeqPos pos,
  586.  TSeqPos length)
  587. {
  588.     _ASSERT(src != 0);
  589.     switch ( src_coding ) {
  590.     case CSeqUtil::e_Iupacna:
  591.         return revcmp(src, pos, length, CIupacnaCmp::GetTable());
  592.     case CSeqUtil::e_Ncbi2na:
  593.         return s_Ncbi2naRevCmp(src, pos, length);
  594.     case CSeqUtil::e_Ncbi2na_expand:
  595.         return s_Ncbi2naExpandRevCmp(src, pos, length);
  596.     case CSeqUtil::e_Ncbi4na:
  597.         return s_Ncbi4naRevCmp(src, pos, length);
  598.     case CSeqUtil::e_Ncbi8na:
  599.     case CSeqUtil::e_Ncbi4na_expand:
  600.         return revcmp(src, pos, length, C8naCmp::GetTable());
  601.     }
  602.     NCBI_THROW(CSeqUtilException, eInvalidCoding,
  603.         "There is no complement for the specified coding.");
  604. }
  605. END_NCBI_SCOPE
  606.  /*
  607. * ===========================================================================
  608. *
  609. * $Log: sequtil_manip.cpp,v $
  610. * Revision 1000.1  2004/06/01 19:42:20  gouriano
  611. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3
  612. *
  613. * Revision 1.3  2004/05/17 21:08:53  gorelenk
  614. * Added include of PCH ncbi_pch.hpp
  615. *
  616. * Revision 1.2  2003/10/14 14:51:14  ucko
  617. * Fix for GCC 2.95, whose operator[] const returns a copy rather than a
  618. * const reference, by substituting *x.begin().
  619. *
  620. * Revision 1.1  2003/10/08 13:35:24  shomrat
  621. * Initial version
  622. *
  623. *
  624. * ===========================================================================
  625. */