1 
2 /* ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author:  Christiam Camacho
27  *
28  * ===========================================================================
29  */
30 
31 /// @file blast_options_local_priv.cpp
32 /// Definition of local representation of BLAST options.
33 
34 #include <ncbi_pch.hpp>
35 #include <algo/blast/api/blast_exception.hpp>
36 #include "blast_options_local_priv.hpp"
37 
38 /** @addtogroup AlgoBlast
39  *
40  * @{
41  */
42 
43 BEGIN_NCBI_SCOPE
44 USING_SCOPE(objects);
BEGIN_SCOPE(blast)45 BEGIN_SCOPE(blast)
46 
47 #ifndef SKIP_DOXYGEN_PROCESSING
48 
49 CBlastOptionsLocal::CBlastOptionsLocal()
50 {
51     QuerySetUpOptions* query_setup = NULL;
52     BlastQuerySetUpOptionsNew(&query_setup);
53     m_QueryOpts.Reset(query_setup);
54     m_InitWordOpts.Reset((BlastInitialWordOptions*)calloc(1, sizeof(BlastInitialWordOptions)));
55     m_LutOpts.Reset((LookupTableOptions*)calloc(1, sizeof(LookupTableOptions)));
56     m_ExtnOpts.Reset((BlastExtensionOptions*)calloc(1, sizeof(BlastExtensionOptions)));
57     m_HitSaveOpts.Reset((BlastHitSavingOptions*)calloc(1, sizeof(BlastHitSavingOptions)));
58     m_ScoringOpts.Reset((BlastScoringOptions*)calloc(1, sizeof(BlastScoringOptions)));
59 
60     BlastEffectiveLengthsOptionsNew(&m_EffLenOpts);
61     BlastDatabaseOptionsNew(&m_DbOpts);
62     PSIBlastOptionsNew(&m_PSIBlastOpts);
63     PSIBlastOptionsNew(&m_DeltaBlastOpts);
64     m_Program = eBlastNotSet;
65     m_UseMBIndex = false;
66     m_ForceMBIndex = false;
67     m_MBIndexLoaded = false;
68 }
69 
~CBlastOptionsLocal()70 CBlastOptionsLocal::~CBlastOptionsLocal()
71 {
72 }
73 
CBlastOptionsLocal(const CBlastOptionsLocal & optsLocal)74 CBlastOptionsLocal::CBlastOptionsLocal(const CBlastOptionsLocal& optsLocal)
75 {
76     x_DoDeepCopy(optsLocal);
77 }
78 
operator =(const CBlastOptionsLocal & optsLocal)79 CBlastOptionsLocal& CBlastOptionsLocal::operator=(const CBlastOptionsLocal& optsLocal)
80 {
81     x_DoDeepCopy(optsLocal);
82     return *this;
83 }
84 
x_DoDeepCopy(const CBlastOptionsLocal & optsLocal)85 void CBlastOptionsLocal::x_DoDeepCopy(const CBlastOptionsLocal& optsLocal)
86 {
87     if (&optsLocal != this)
88     {
89         // Copy the contents of various options structures
90         x_Copy_CQuerySetUpOptions(m_QueryOpts,
91                             optsLocal.m_QueryOpts);
92         x_Copy_CLookupTableOptions(m_LutOpts,
93                             optsLocal.m_LutOpts);
94         x_Copy_CBlastInitialWordOptions(m_InitWordOpts,
95                             optsLocal.m_InitWordOpts);
96         x_Copy_CBlastExtensionOptions(m_ExtnOpts,
97                             optsLocal.m_ExtnOpts);
98         x_Copy_CBlastHitSavingOptions(m_HitSaveOpts,
99                             optsLocal.m_HitSaveOpts);
100         x_Copy_CPSIBlastOptions(m_PSIBlastOpts,
101                             optsLocal.m_PSIBlastOpts);
102         x_Copy_CPSIBlastOptions(m_DeltaBlastOpts,
103                             optsLocal.m_DeltaBlastOpts);
104         x_Copy_CBlastDatabaseOptions(m_DbOpts,
105                             optsLocal.m_DbOpts);
106         x_Copy_CBlastScoringOptions(m_ScoringOpts,
107                             optsLocal.m_ScoringOpts);
108         x_Copy_CBlastEffectiveLengthsOptions(m_EffLenOpts,
109                             optsLocal.m_EffLenOpts);
110 
111         // Copy other member variables
112         m_Program = optsLocal.m_Program;
113         m_UseMBIndex = optsLocal.m_UseMBIndex;
114         m_ForceMBIndex = optsLocal.m_ForceMBIndex;
115         m_MBIndexLoaded = optsLocal.m_MBIndexLoaded;
116         m_MBIndexName = optsLocal.m_MBIndexName;
117     }
118 }
119 
x_Copy_CQuerySetUpOptions(CQuerySetUpOptions & queryOptsDst,const CQuerySetUpOptions & queryOptsSrc)120 void CBlastOptionsLocal::x_Copy_CQuerySetUpOptions(
121                           CQuerySetUpOptions& queryOptsDst,
122                           const CQuerySetUpOptions& queryOptsSrc)
123 {
124     QuerySetUpOptions* querySetUpOptionsNew =
125         (QuerySetUpOptions*)BlastMemDup(
126             queryOptsSrc.Get(),
127             sizeof(QuerySetUpOptions));
128 
129     if (queryOptsSrc->filtering_options)
130     {
131         SBlastFilterOptions* blastFilterOptionsNew =
132             (SBlastFilterOptions*)BlastMemDup(
133                 queryOptsSrc->filtering_options,
134                 sizeof(SBlastFilterOptions));
135 
136         SDustOptions*           dustOptionsNew = NULL;
137         SSegOptions*            segOptionsNew = NULL;
138         SRepeatFilterOptions*   repeatFilterOptionsNew = NULL;
139         SWindowMaskerOptions*   windowMaskerOptionsNew = NULL;
140         SReadQualityOptions*    readQualityOptionsNew = NULL;
141 
142         if (queryOptsSrc->filtering_options->dustOptions)
143         {
144             dustOptionsNew =
145                 (SDustOptions*)BlastMemDup(
146                     queryOptsSrc->filtering_options->dustOptions,
147                     sizeof(SDustOptions));
148         }
149         if (queryOptsSrc->filtering_options->segOptions)
150         {
151             segOptionsNew =
152                 (SSegOptions*)BlastMemDup(
153                     queryOptsSrc->filtering_options->segOptions,
154                     sizeof(SSegOptions));
155         }
156         if (queryOptsSrc->filtering_options->repeatFilterOptions)
157         {
158             repeatFilterOptionsNew =
159                 (SRepeatFilterOptions*)BlastMemDup(
160                     queryOptsSrc->filtering_options->repeatFilterOptions,
161                     sizeof(SRepeatFilterOptions));
162             if (queryOptsSrc->filtering_options->repeatFilterOptions->database)
163             {
164                 repeatFilterOptionsNew->database =
165                     strdup(queryOptsSrc->filtering_options->
166                            repeatFilterOptions->database);
167             }
168         }
169         if (queryOptsSrc->filtering_options->windowMaskerOptions)
170         {
171             windowMaskerOptionsNew =
172                 (SWindowMaskerOptions*)BlastMemDup(
173                     queryOptsSrc->filtering_options->windowMaskerOptions,
174                     sizeof(SWindowMaskerOptions));
175             if (queryOptsSrc->filtering_options->windowMaskerOptions->database)
176             {
177                 windowMaskerOptionsNew->database =
178                     strdup(queryOptsSrc->filtering_options->
179                            windowMaskerOptions->database);
180             }
181         }
182         if (queryOptsSrc->filtering_options->readQualityOptions) {
183             readQualityOptionsNew =
184                 (SReadQualityOptions*)BlastMemDup(
185                     queryOptsSrc->filtering_options->readQualityOptions,
186                     sizeof(SReadQualityOptions));
187         }
188 
189         blastFilterOptionsNew->dustOptions = dustOptionsNew;
190         blastFilterOptionsNew->segOptions = segOptionsNew;
191         blastFilterOptionsNew->repeatFilterOptions = repeatFilterOptionsNew;
192         blastFilterOptionsNew->windowMaskerOptions = windowMaskerOptionsNew;
193         blastFilterOptionsNew->readQualityOptions = readQualityOptionsNew;
194 
195         querySetUpOptionsNew->filtering_options = blastFilterOptionsNew;
196     }
197 
198     if (queryOptsSrc->filter_string)
199     {
200         querySetUpOptionsNew->filter_string =
201             strdup(queryOptsSrc->filter_string);
202     }
203 
204     queryOptsDst.Reset(querySetUpOptionsNew);
205 }
206 
x_Copy_CLookupTableOptions(CLookupTableOptions & lutOptsDst,const CLookupTableOptions & lutOptsSrc)207 void CBlastOptionsLocal::x_Copy_CLookupTableOptions(
208                             CLookupTableOptions& lutOptsDst,
209                             const CLookupTableOptions& lutOptsSrc)
210 {
211     LookupTableOptions* lookupTableOptionsNew =
212         (LookupTableOptions*)BlastMemDup(
213             lutOptsSrc.Get(),
214             sizeof(LookupTableOptions));
215 
216     if (lutOptsSrc->phi_pattern)
217     {
218         lookupTableOptionsNew->phi_pattern =
219             strdup(lutOptsSrc->phi_pattern);
220     }
221 
222     lutOptsDst.Reset(lookupTableOptionsNew);
223 }
224 
x_Copy_CBlastInitialWordOptions(CBlastInitialWordOptions & initWordOptsDst,const CBlastInitialWordOptions & initWordOptsSrc)225 void CBlastOptionsLocal::x_Copy_CBlastInitialWordOptions(
226                             CBlastInitialWordOptions& initWordOptsDst,
227                             const CBlastInitialWordOptions& initWordOptsSrc)
228 {
229     BlastInitialWordOptions* blastInitialWordOptionsNew =
230         (BlastInitialWordOptions*)BlastMemDup(
231             initWordOptsSrc.Get(),
232             sizeof(BlastInitialWordOptions));
233 
234     initWordOptsDst.Reset(blastInitialWordOptionsNew);
235 }
236 
x_Copy_CBlastExtensionOptions(CBlastExtensionOptions & extnOptsDst,const CBlastExtensionOptions & extnOptsSrc)237 void CBlastOptionsLocal::x_Copy_CBlastExtensionOptions(
238                             CBlastExtensionOptions& extnOptsDst,
239                             const CBlastExtensionOptions& extnOptsSrc)
240 {
241     BlastExtensionOptions* blastExtensionOptionsNew =
242         (BlastExtensionOptions*)BlastMemDup(
243             extnOptsSrc.Get(),
244             sizeof(BlastExtensionOptions));
245 
246     extnOptsDst.Reset(blastExtensionOptionsNew);
247 }
248 
x_Copy_CBlastHitSavingOptions(CBlastHitSavingOptions & hitSaveOptsDst,const CBlastHitSavingOptions & hitSaveOptsSrc)249 void CBlastOptionsLocal::x_Copy_CBlastHitSavingOptions(
250                             CBlastHitSavingOptions& hitSaveOptsDst,
251                             const CBlastHitSavingOptions& hitSaveOptsSrc)
252 {
253     BlastHitSavingOptions* blastHitSavingOptionsNew =
254         (BlastHitSavingOptions*)BlastMemDup(
255             hitSaveOptsSrc.Get(),
256             sizeof(BlastHitSavingOptions));
257 
258     if (hitSaveOptsSrc->hsp_filt_opt)
259     {
260         BlastHSPFilteringOptions* blastHSPFilteringOptionsNew =
261             (BlastHSPFilteringOptions*)BlastMemDup(
262                 hitSaveOptsSrc->hsp_filt_opt,
263                 sizeof(BlastHSPFilteringOptions));
264 
265         BlastHSPBestHitOptions* blastHSPBestHitOptionsNew = NULL;
266         BlastHSPCullingOptions* blastHSPCullingOptionsNew = NULL;
267 
268         if (hitSaveOptsSrc->hsp_filt_opt->best_hit)
269         {
270             blastHSPBestHitOptionsNew =
271                 (BlastHSPBestHitOptions*)BlastMemDup(
272                     hitSaveOptsSrc->hsp_filt_opt->best_hit,
273                     sizeof(BlastHSPBestHitOptions));
274         }
275         if (hitSaveOptsSrc->hsp_filt_opt->culling_opts)
276         {
277             blastHSPCullingOptionsNew =
278                 (BlastHSPCullingOptions*)BlastMemDup(
279                     hitSaveOptsSrc->hsp_filt_opt->culling_opts,
280                     sizeof(BlastHSPCullingOptions));
281         }
282 
283         blastHSPFilteringOptionsNew->best_hit = blastHSPBestHitOptionsNew;
284         blastHSPFilteringOptionsNew->culling_opts = blastHSPCullingOptionsNew;
285 
286         blastHitSavingOptionsNew->hsp_filt_opt = blastHSPFilteringOptionsNew;
287     }
288 
289     hitSaveOptsDst.Reset(blastHitSavingOptionsNew);
290 }
291 
x_Copy_CPSIBlastOptions(CPSIBlastOptions & psiBlastOptsDst,const CPSIBlastOptions & psiBlastOptsSrc)292 void CBlastOptionsLocal::x_Copy_CPSIBlastOptions(
293                             CPSIBlastOptions& psiBlastOptsDst,
294                             const CPSIBlastOptions& psiBlastOptsSrc)
295 {
296     PSIBlastOptions* psiBlastOptionsNew =
297         (PSIBlastOptions*)BlastMemDup(
298             psiBlastOptsSrc.Get(),
299             sizeof(PSIBlastOptions));
300 
301     psiBlastOptsDst.Reset(psiBlastOptionsNew);
302 }
303 
x_Copy_CBlastDatabaseOptions(CBlastDatabaseOptions & dbOptsDst,const CBlastDatabaseOptions & dbOptsSrc)304 void CBlastOptionsLocal::x_Copy_CBlastDatabaseOptions(
305                             CBlastDatabaseOptions& dbOptsDst,
306                             const CBlastDatabaseOptions& dbOptsSrc)
307 {
308     BlastDatabaseOptions* blastDatabaseOptionsNew =
309         (BlastDatabaseOptions*)BlastMemDup(
310             dbOptsSrc.Get(),
311             sizeof(BlastDatabaseOptions));
312 
313     dbOptsDst.Reset(blastDatabaseOptionsNew);
314 }
315 
x_Copy_CBlastScoringOptions(CBlastScoringOptions & scoringOptsDst,const CBlastScoringOptions & scoringOptsSrc)316 void CBlastOptionsLocal::x_Copy_CBlastScoringOptions(
317                             CBlastScoringOptions& scoringOptsDst,
318                             const CBlastScoringOptions& scoringOptsSrc)
319 {
320     BlastScoringOptions* blastScoringOptionsNew = NULL;
321     BlastScoringOptionsDup(&blastScoringOptionsNew, scoringOptsSrc.Get());
322     scoringOptsDst.Reset(blastScoringOptionsNew);
323 }
324 
x_Copy_CBlastEffectiveLengthsOptions(CBlastEffectiveLengthsOptions & effLenOptsDst,const CBlastEffectiveLengthsOptions & effLenOptsSrc)325 void CBlastOptionsLocal::x_Copy_CBlastEffectiveLengthsOptions(
326                             CBlastEffectiveLengthsOptions& effLenOptsDst,
327                             const CBlastEffectiveLengthsOptions& effLenOptsSrc)
328 {
329     BlastEffectiveLengthsOptions* blastEffectiveLengthsOptionsNew =
330         (BlastEffectiveLengthsOptions*)BlastMemDup(
331             effLenOptsSrc.Get(),
332             sizeof(BlastEffectiveLengthsOptions));
333 
334     if (effLenOptsSrc->num_searchspaces > 0 &&
335         effLenOptsSrc->searchsp_eff)
336     {
337         blastEffectiveLengthsOptionsNew->searchsp_eff =
338         (Int8*)BlastMemDup(
339             effLenOptsSrc->searchsp_eff,
340             effLenOptsSrc->num_searchspaces * sizeof(Int8));
341     }
342 
343     effLenOptsDst.Reset(blastEffectiveLengthsOptionsNew);
344 }
345 
346 void
SetDbGeneticCode(int gc)347 CBlastOptionsLocal::SetDbGeneticCode(int gc)
348 {
349     m_DbOpts->genetic_code = gc;
350 }
351 
352 EBlastProgramType
GetProgramType() const353 CBlastOptionsLocal::GetProgramType() const
354 {
355     return EProgramToEBlastProgramType(m_Program);
356 }
357 
358 static void
s_BlastMessageToException(Blast_Message ** blmsg_ptr,const string & default_msg)359 s_BlastMessageToException(Blast_Message** blmsg_ptr, const string& default_msg)
360 {
361     if (!blmsg_ptr || *blmsg_ptr == NULL)
362         return;
363 
364     Blast_Message* blmsg = *blmsg_ptr;
365     string msg = blmsg ? blmsg->message : default_msg;
366 
367     *blmsg_ptr = Blast_MessageFree(blmsg);
368 
369     if (msg != NcbiEmptyString)
370         NCBI_THROW(CBlastException, eInvalidOptions, msg);
371 }
372 
373 bool
Validate() const374 CBlastOptionsLocal::Validate() const
375 {
376     Blast_Message* blmsg = NULL;
377 
378     if (BLAST_ValidateOptions(GetProgramType(), m_ExtnOpts,
379                                        m_ScoringOpts,
380                                        m_LutOpts,
381                                        m_InitWordOpts,
382                                        m_HitSaveOpts,
383                                        &blmsg)) {
384         s_BlastMessageToException(&blmsg, "Options validation failed");
385         return false;
386     }
387     // Index validation.
388     if( m_UseMBIndex &&
389             (m_Program != eMegablast && m_Program != eBlastn
390              && m_Program != eMapper) ) {
391         NCBI_THROW(CBlastException, eInvalidOptions,
392                 "Database index can be used only with contiguous megablast." );
393     }
394 
395     return true;
396 }
397 
398 void
DebugDump(CDebugDumpContext ddc,unsigned int depth) const399 CBlastOptionsLocal::DebugDump(CDebugDumpContext ddc, unsigned int depth) const
400 {
401     ddc.SetFrame("CBlastOptionsLocal");
402     DebugDumpValue(ddc,"m_Program", m_Program);
403     m_QueryOpts.DebugDump(ddc, depth);
404     m_LutOpts.DebugDump(ddc, depth);
405     m_InitWordOpts.DebugDump(ddc, depth);
406     m_ExtnOpts.DebugDump(ddc, depth);
407     m_HitSaveOpts.DebugDump(ddc, depth);
408     m_PSIBlastOpts.DebugDump(ddc, depth);
409     m_DeltaBlastOpts.DebugDump(ddc, depth);
410     m_DbOpts.DebugDump(ddc, depth);
411     m_ScoringOpts.DebugDump(ddc, depth);
412     m_EffLenOpts.DebugDump(ddc, depth);
413 }
414 
415 inline int
x_safe_strcmp(const char * a,const char * b)416 x_safe_strcmp(const char* a, const char* b)
417 {
418     if (a != b) {
419         if (a != NULL && b != NULL) {
420             return strcmp(a,b);
421         } else {
422             return 1;
423         }
424     }
425     return 0;
426 }
427 
428 inline int
x_safe_memcmp(const void * a,const void * b,size_t size)429 x_safe_memcmp(const void* a, const void* b, size_t size)
430 {
431     if (a != b) {
432         if (a != NULL && b != NULL) {
433             return memcmp(a, b, size);
434         } else {
435             return 1;
436         }
437     }
438     return 0;
439 }
440 
441 bool
x_QuerySetupOptions_cmp(const QuerySetUpOptions * a,const QuerySetUpOptions * b)442 x_QuerySetupOptions_cmp(const QuerySetUpOptions* a, const QuerySetUpOptions* b)
443 {
444     if (x_safe_strcmp(a->filter_string, b->filter_string) != 0) {
445         return false;
446     }
447     if (a->strand_option != b->strand_option) return false;
448     if (a->genetic_code != b->genetic_code) return false;
449     return true;
450 }
451 
452 bool
x_LookupTableOptions_cmp(const LookupTableOptions * a,const LookupTableOptions * b)453 x_LookupTableOptions_cmp(const LookupTableOptions* a,
454                          const LookupTableOptions* b)
455 {
456     if (a->threshold != b->threshold) return false;
457     if (a->lut_type != b->lut_type) return false;
458     if (a->word_size != b->word_size) return false;
459     if (a->mb_template_length != b->mb_template_length) return false;
460     if (a->mb_template_type != b->mb_template_type) return false;
461     if (x_safe_strcmp(a->phi_pattern, b->phi_pattern) != 0) return false;
462     return true;
463 }
464 
465 bool
x_BlastDatabaseOptions_cmp(const BlastDatabaseOptions * a,const BlastDatabaseOptions * b)466 x_BlastDatabaseOptions_cmp(const BlastDatabaseOptions* a,
467                            const BlastDatabaseOptions* b)
468 {
469     if (a->genetic_code != b->genetic_code) return false;
470     return true;
471 }
472 
473 bool
x_BlastScoringOptions_cmp(const BlastScoringOptions * a,const BlastScoringOptions * b)474 x_BlastScoringOptions_cmp(const BlastScoringOptions* a,
475                           const BlastScoringOptions* b)
476 {
477     if (x_safe_strcmp(a->matrix, b->matrix) != 0) return false;
478     if (x_safe_strcmp(a->matrix_path, b->matrix_path) != 0) return false;
479     if (a->reward != b->reward) return false;
480     if (a->penalty != b->penalty) return false;
481     if (a->gapped_calculation != b->gapped_calculation) return false;
482     // Added to support complexity adjusted scoring in RMBlastN -RMH-
483     if (a->complexity_adjusted_scoring != b->complexity_adjusted_scoring) return false;
484     if (a->gap_open != b->gap_open) return false;
485     if (a->gap_extend != b->gap_extend) return false;
486     if (a->is_ooframe != b->is_ooframe) return false;
487     if (a->shift_pen != b->shift_pen) return false;
488     return true;
489 }
490 
491 bool
x_BlastEffectiveLengthsOptions_cmp(const BlastEffectiveLengthsOptions * a,const BlastEffectiveLengthsOptions * b)492 x_BlastEffectiveLengthsOptions_cmp(const BlastEffectiveLengthsOptions* a,
493                                    const BlastEffectiveLengthsOptions* b)
494 {
495     if (a->db_length != b->db_length) return false;
496     if (a->dbseq_num != b->dbseq_num) return false;
497     if (a->num_searchspaces != b->num_searchspaces) return false;
498     if (x_safe_memcmp((void*)a->searchsp_eff,
499                       (void*)b->searchsp_eff,
500                       min(a->num_searchspaces, b->num_searchspaces)) != 0) {
501         return false;
502     }
503     return true;
504 }
505 
506 bool
operator ==(const CBlastOptionsLocal & rhs) const507 CBlastOptionsLocal::operator==(const CBlastOptionsLocal& rhs) const
508 {
509     if (this == &rhs)
510         return true;
511 
512     if (m_Program != rhs.m_Program)
513         return false;
514 
515     if ( !x_QuerySetupOptions_cmp(m_QueryOpts, rhs.m_QueryOpts) )
516         return false;
517 
518     if ( !x_LookupTableOptions_cmp(m_LutOpts, rhs.m_LutOpts) )
519         return false;
520 
521     void *a, *b;
522 
523     a = static_cast<void*>( (BlastInitialWordOptions*) m_InitWordOpts);
524     b = static_cast<void*>( (BlastInitialWordOptions*) rhs.m_InitWordOpts);
525     if ( x_safe_memcmp(a, b, sizeof(BlastInitialWordOptions)) != 0 )
526          return false;
527 
528     a = static_cast<void*>( (BlastExtensionOptions*) m_ExtnOpts);
529     b = static_cast<void*>( (BlastExtensionOptions*) rhs.m_ExtnOpts);
530     if ( x_safe_memcmp(a, b, sizeof(BlastExtensionOptions)) != 0 )
531          return false;
532 
533     a = static_cast<void*>( (BlastHitSavingOptions*) m_HitSaveOpts);
534     b = static_cast<void*>( (BlastHitSavingOptions*) rhs.m_HitSaveOpts);
535     if ( x_safe_memcmp(a, b, sizeof(BlastHitSavingOptions)) != 0 )
536          return false;
537 
538     a = static_cast<void*>( (PSIBlastOptions*) m_PSIBlastOpts);
539     b = static_cast<void*>( (PSIBlastOptions*) rhs.m_PSIBlastOpts);
540     if ( x_safe_memcmp(a, b, sizeof(PSIBlastOptions)) != 0 )
541          return false;
542 
543     a = static_cast<void*>( (PSIBlastOptions*) m_DeltaBlastOpts);
544     b = static_cast<void*>( (PSIBlastOptions*) rhs.m_DeltaBlastOpts);
545     if ( x_safe_memcmp(a, b, sizeof(PSIBlastOptions)) != 0 )
546          return false;
547 
548     if ( !x_BlastDatabaseOptions_cmp(m_DbOpts, rhs.m_DbOpts) )
549         return false;
550 
551     if ( !x_BlastScoringOptions_cmp(m_ScoringOpts, rhs.m_ScoringOpts) )
552         return false;
553 
554     if ( !x_BlastEffectiveLengthsOptions_cmp(m_EffLenOpts, rhs.m_EffLenOpts) )
555         return false;
556 
557     return true;
558 }
559 
560 bool
operator !=(const CBlastOptionsLocal & rhs) const561 CBlastOptionsLocal::operator!=(const CBlastOptionsLocal& rhs) const
562 {
563     return !(*this== rhs);
564 }
565 
566 #endif /* SKIP_DOXYGEN_PROCESSING */
567 
568 END_SCOPE(blast)
569 END_NCBI_SCOPE
570 
571 /* @} */
572