From 0d4771a1177b4e06b2f87ac24cdd1f374c4f3069 Mon Sep 17 00:00:00 2001 From: sacha schutz Date: Sun, 21 Jan 2018 17:47:02 +0100 Subject: [PATCH] first commit --- bamviewer.cpp | 48 + bamviewer.h | 31 + bamviewer.pro | 39 + main.cpp | 11 + mainwindow.cpp | 18 + mainwindow.h | 20 + mainwindow.ui | 24 + seqan/LICENSE | 27 + seqan/align.h | 224 + seqan/align/align_base.h | 740 +++ seqan/align/align_cols.h | 429 ++ seqan/align/align_config.h | 395 ++ seqan/align/align_interface_wrapper.h | 179 + seqan/align/align_iterator_base.h | 527 ++ seqan/align/align_metafunctions.h | 115 + seqan/align/align_traceback.h | 161 + seqan/align/alignment_algorithm_tags.h | 165 + seqan/align/alignment_operations.h | 149 + seqan/align/dp_algorithm_impl.h | 1599 ++++++ seqan/align/dp_align_simd_helper.h | 517 ++ seqan/align/dp_band.h | 384 ++ seqan/align/dp_cell.h | 283 + seqan/align/dp_cell_affine.h | 208 + seqan/align/dp_cell_dynamic.h | 249 + seqan/align/dp_cell_linear.h | 125 + seqan/align/dp_context.h | 187 + seqan/align/dp_formula.h | 220 + seqan/align/dp_formula_affine.h | 636 +++ seqan/align/dp_formula_dynamic.h | 689 +++ seqan/align/dp_formula_linear.h | 291 + seqan/align/dp_matrix.h | 644 +++ seqan/align/dp_matrix_navigator.h | 230 + .../align/dp_matrix_navigator_score_matrix.h | 407 ++ .../dp_matrix_navigator_score_matrix_sparse.h | 369 ++ .../align/dp_matrix_navigator_trace_matrix.h | 517 ++ seqan/align/dp_matrix_sparse.h | 150 + seqan/align/dp_meta_info.h | 485 ++ seqan/align/dp_profile.h | 571 ++ seqan/align/dp_scout.h | 340 ++ seqan/align/dp_scout_simd.h | 454 ++ seqan/align/dp_setup.h | 332 ++ seqan/align/dp_trace_segment.h | 341 ++ seqan/align/dp_traceback_adaptor.h | 321 ++ seqan/align/dp_traceback_impl.h | 611 +++ seqan/align/evaluate_alignment.h | 331 ++ seqan/align/fragment.h | 571 ++ seqan/align/gap_anchor.h | 380 ++ seqan/align/gapped_value_type.h | 87 + seqan/align/gaps_anchor.h | 938 ++++ seqan/align/gaps_array.h | 917 ++++ seqan/align/gaps_base.h | 1234 +++++ seqan/align/gaps_iterator_anchor.h | 781 +++ seqan/align/gaps_iterator_array.h | 783 +++ seqan/align/gaps_iterator_base.h | 525 ++ seqan/align/global_alignment_banded.h | 786 +++ .../align/global_alignment_hirschberg_impl.h | 694 +++ .../global_alignment_myers_hirschberg_impl.h | 762 +++ seqan/align/global_alignment_myers_impl.h | 201 + seqan/align/global_alignment_specialized.h | 201 + seqan/align/global_alignment_unbanded.h | 841 +++ seqan/align/local_alignment_banded.h | 298 + ...al_alignment_banded_waterman_eggert_impl.h | 601 ++ seqan/align/local_alignment_enumeration.h | 220 + .../local_alignment_enumeration_banded.h | 126 + .../local_alignment_enumeration_unbanded.h | 122 + seqan/align/local_alignment_unbanded.h | 381 ++ .../local_alignment_waterman_eggert_impl.h | 751 +++ seqan/align/matrix_base.h | 1103 ++++ seqan/align_extend.h | 48 + seqan/align_extend/align_extend.h | 647 +++ seqan/align_extend/align_extend_base.h | 201 + seqan/align_extend/dp_scout_xdrop.h | 206 + seqan/align_profile.h | 57 + seqan/align_profile/add_to_profile.h | 165 + seqan/align_profile/score_profile_seq.h | 536 ++ seqan/align_split.h | 55 + seqan/align_split/align_split_interface.h | 751 +++ seqan/align_split/dp_scout_split.h | 137 + seqan/alignment_free.h | 63 + seqan/alignment_free/af_d2.h | 124 + seqan/alignment_free/af_d2star.h | 224 + seqan/alignment_free/af_d2z.h | 631 +++ seqan/alignment_free/af_n2.h | 641 +++ seqan/alignment_free/alignment_free_base.h | 340 ++ .../alignment_free_comparison.h | 106 + seqan/alignment_free/kmer_functions.h | 965 ++++ seqan/arg_parse.h | 79 + seqan/arg_parse/arg_parse_argument.h | 1164 ++++ seqan/arg_parse/arg_parse_ctd_support.h | 594 ++ seqan/arg_parse/arg_parse_doc.h | 1056 ++++ seqan/arg_parse/arg_parse_exceptions.h | 89 + seqan/arg_parse/arg_parse_option.h | 492 ++ seqan/arg_parse/arg_parse_parse.h | 395 ++ seqan/arg_parse/arg_parse_type_support.h | 236 + seqan/arg_parse/arg_parse_version_check.h | 480 ++ seqan/arg_parse/argument_parser.h | 1192 ++++ seqan/arg_parse/tool_doc.h | 1613 ++++++ seqan/arg_parse/xml_support.h | 95 + seqan/bam_io.h | 96 + seqan/bam_io/bam_alignment_record.h | 612 +++ seqan/bam_io/bam_alignment_record_util.h | 253 + seqan/bam_io/bam_file.h | 363 ++ seqan/bam_io/bam_header_record.h | 483 ++ seqan/bam_io/bam_index_bai.h | 794 +++ seqan/bam_io/bam_io_context.h | 353 ++ seqan/bam_io/bam_sam_conversion.h | 369 ++ seqan/bam_io/bam_scanner_cache.h | 309 ++ seqan/bam_io/bam_tags_dict.h | 890 +++ seqan/bam_io/cigar.h | 696 +++ seqan/bam_io/read_bam.h | 279 + seqan/bam_io/read_sam.h | 399 ++ seqan/bam_io/write_bam.h | 276 + seqan/bam_io/write_sam.h | 221 + seqan/basic.h | 112 + seqan/basic/aggregate_concept.h | 132 + seqan/basic/allocator_chunkpool.h | 245 + seqan/basic/allocator_interface.h | 432 ++ seqan/basic/allocator_multipool.h | 262 + seqan/basic/allocator_simple.h | 239 + seqan/basic/allocator_singlepool.h | 250 + seqan/basic/allocator_to_std.h | 206 + seqan/basic/alphabet_adapt_builtins.h | 236 + seqan/basic/alphabet_bio.h | 101 + seqan/basic/alphabet_concept.h | 586 ++ seqan/basic/alphabet_math.h | 294 + seqan/basic/alphabet_profile.h | 382 ++ seqan/basic/alphabet_qualities.h | 129 + seqan/basic/alphabet_residue.h | 1493 +++++ seqan/basic/alphabet_residue_funcs.h | 87 + seqan/basic/alphabet_residue_tabs.h | 461 ++ seqan/basic/alphabet_simple_type.h | 1092 ++++ seqan/basic/alphabet_storage.h | 291 + seqan/basic/array_construct_destruct.h | 1272 +++++ seqan/basic/basic_aggregate.h | 62 + seqan/basic/basic_allocator.h | 64 + seqan/basic/basic_alphabet.h | 98 + seqan/basic/basic_concept.h | 67 + seqan/basic/basic_container.h | 59 + seqan/basic/basic_debug.h | 60 + seqan/basic/basic_device.h | 152 + seqan/basic/basic_exception.h | 378 ++ seqan/basic/basic_functors.h | 214 + seqan/basic/basic_fundamental.h | 88 + seqan/basic/basic_iterator.h | 92 + seqan/basic/basic_math.h | 58 + seqan/basic/basic_metaprogramming.h | 64 + seqan/basic/basic_parallelism.h | 76 + seqan/basic/basic_proxy.h | 59 + seqan/basic/basic_simd_vector.h | 1671 ++++++ seqan/basic/basic_smart_pointer.h | 59 + seqan/basic/basic_stream.h | 1303 +++++ seqan/basic/basic_tangle.h | 166 + seqan/basic/basic_type.h | 543 ++ seqan/basic/basic_view.h | 190 + seqan/basic/boost_preprocessor_subset.h | 4850 +++++++++++++++++ seqan/basic/builtin_functions.h | 63 + seqan/basic/concept_checking.h | 731 +++ seqan/basic/container_concept.h | 633 +++ seqan/basic/debug_helper.h | 243 + seqan/basic/debug_test_system.h | 2392 ++++++++ seqan/basic/fundamental_chunking.h | 148 + seqan/basic/fundamental_comparison.h | 149 + seqan/basic/fundamental_concepts.h | 1018 ++++ seqan/basic/fundamental_conversion.h | 154 + seqan/basic/fundamental_metafunctions.h | 314 ++ seqan/basic/fundamental_tags.h | 658 +++ seqan/basic/fundamental_transport.h | 244 + seqan/basic/holder_base.h | 443 ++ seqan/basic/holder_simple.h | 297 + seqan/basic/holder_tristate.h | 955 ++++ seqan/basic/hosted_type_interface.h | 291 + seqan/basic/iterator_adapt_pointer.h | 96 + seqan/basic/iterator_adapt_std.h | 601 ++ seqan/basic/iterator_adaptor.h | 759 +++ seqan/basic/iterator_base.h | 375 ++ seqan/basic/iterator_concept.h | 866 +++ seqan/basic/iterator_counting.h | 359 ++ seqan/basic/iterator_interface.h | 512 ++ seqan/basic/iterator_position.h | 276 + seqan/basic/iterator_range.h | 398 ++ seqan/basic/iterator_zip.h | 657 +++ seqan/basic/macro_deprecated.h | 78 + seqan/basic/math_functions.h | 206 + seqan/basic/math_log_space_value.h | 481 ++ seqan/basic/metaprogramming_control.h | 280 + seqan/basic/metaprogramming_enable_if.h | 363 ++ seqan/basic/metaprogramming_logic.h | 536 ++ seqan/basic/metaprogramming_math.h | 187 + seqan/basic/metaprogramming_type.h | 338 ++ seqan/basic/metaprogramming_type_algebra.h | 274 + seqan/basic/pair_base.h | 482 ++ seqan/basic/pair_bit_compressed.h | 174 + seqan/basic/pair_packed.h | 180 + seqan/basic/profiling.h | 604 ++ seqan/basic/property_map_concept.h | 169 + seqan/basic/proxy_base.h | 475 ++ seqan/basic/proxy_iterator.h | 335 ++ seqan/basic/test_system.h | 419 ++ seqan/basic/triple_base.h | 533 ++ seqan/basic/triple_packed.h | 184 + seqan/basic/tuple_base.h | 625 +++ seqan/basic/tuple_bit_compressed.h | 549 ++ seqan/basic/volatile_ptr.h | 225 + seqan/bed_io.h | 59 + seqan/bed_io/bed_file.h | 127 + seqan/bed_io/bed_record.h | 432 ++ seqan/bed_io/read_bed.h | 279 + seqan/bed_io/write_bed.h | 148 + seqan/blast.h | 73 + seqan/blast/blast_base.h | 426 ++ seqan/blast/blast_io_context.h | 286 + seqan/blast/blast_record.h | 464 ++ seqan/blast/blast_report_out.h | 865 +++ seqan/blast/blast_statistics.h | 1167 ++++ seqan/blast/blast_tabular.h | 689 +++ seqan/blast/blast_tabular_in.h | 1010 ++++ seqan/blast/blast_tabular_lowlevel.h | 325 ++ seqan/blast/blast_tabular_out.h | 746 +++ seqan/consensus.h | 70 + seqan/consensus/consensus_aligner.h | 186 + seqan/consensus/consensus_aligner_interface.h | 150 + seqan/consensus/consensus_alignment_options.h | 145 + seqan/consensus/consensus_base.h | 1871 +++++++ seqan/consensus/consensus_builder.h | 494 ++ seqan/consensus/consensus_library.h | 574 ++ seqan/consensus/consensus_realign.h | 794 +++ seqan/consensus/consensus_score.h | 541 ++ seqan/consensus/overlap_info_computation.h | 425 ++ seqan/consensus/overlapper.h | 395 ++ seqan/file.h | 94 + seqan/file/file_base.h | 645 +++ seqan/file/file_cstyle.h | 278 + seqan/file/file_forwards.h | 57 + seqan/file/file_interface.h | 335 ++ seqan/file/file_mapping.h | 790 +++ seqan/file/file_page.h | 1583 ++++++ seqan/file/string_external.h | 2210 ++++++++ seqan/file/string_mmap.h | 712 +++ seqan/find.h | 106 + seqan/find/find_abndm.h | 649 +++ seqan/find/find_ahocorasick.h | 311 ++ seqan/find/find_base.h | 1004 ++++ seqan/find/find_begin.h | 400 ++ seqan/find/find_bndm.h | 254 + seqan/find/find_bom.h | 215 + seqan/find/find_hamming_simple.h | 259 + seqan/find/find_horspool.h | 454 ++ seqan/find/find_lambda.h | 239 + seqan/find/find_multi.h | 150 + seqan/find/find_multiple_bfam.h | 365 ++ seqan/find/find_multiple_shiftand.h | 427 ++ seqan/find/find_myers_ukkonen.h | 1660 ++++++ seqan/find/find_pattern_base.h | 471 ++ seqan/find/find_pex.h | 737 +++ seqan/find/find_score.h | 467 ++ seqan/find/find_set_horspool.h | 259 + seqan/find/find_shiftand.h | 239 + seqan/find/find_shiftor.h | 278 + seqan/find/find_simple.h | 135 + seqan/find/find_wild_shiftand.h | 642 +++ seqan/find/find_wumanber.h | 441 ++ seqan/gff_io.h | 56 + seqan/gff_io/gff_file.h | 165 + seqan/gff_io/gff_io_base.h | 655 +++ seqan/graph_algorithms.h | 72 + .../all_pairs_shortest_path.h | 202 + seqan/graph_algorithms/bellman_ford.h | 136 + seqan/graph_algorithms/bipartite_matching.h | 116 + seqan/graph_algorithms/breadth_first_search.h | 138 + seqan/graph_algorithms/connected_components.h | 150 + seqan/graph_algorithms/depth_first_search.h | 177 + seqan/graph_algorithms/dijkstra.h | 144 + seqan/graph_algorithms/floyd_warshall.h | 122 + seqan/graph_algorithms/ford_fulkerson.h | 220 + .../graph_algorithm_heap_tree.h | 490 ++ seqan/graph_algorithms/graph_algorithm_hmm.h | 1171 ++++ .../graph_algorithm_lis_his.h | 449 ++ seqan/graph_algorithms/kruskal.h | 137 + seqan/graph_algorithms/path_growing.h | 134 + seqan/graph_algorithms/prim.h | 194 + .../single_source_shortest_path.h | 233 + .../strongly_connected_compnents.h | 180 + seqan/graph_algorithms/topological_sort.h | 120 + seqan/graph_algorithms/transitive_closure.h | 107 + .../weakly_connected_components.h | 121 + .../weighted_bipartite_matching.h | 323 ++ seqan/graph_align.h | 69 + .../graph_algorithm_refine_align.h | 195 + .../graph_algorithm_refine_aligngraph.h | 289 + .../graph_algorithm_refine_annotation.h | 355 ++ .../graph_algorithm_refine_exact.h | 555 ++ .../graph_algorithm_refine_exact_iterative.h | 683 +++ .../graph_algorithm_refine_fragment.h | 201 + .../graph_algorithm_refine_inexact.h | 331 ++ .../graph_algorithm_refine_scoring.h | 52 + seqan/graph_align/graph_impl_align.h | 2109 +++++++ seqan/graph_align/graph_impl_align_adapt.h | 409 ++ seqan/graph_msa.h | 54 + seqan/graph_msa/graph_align_tcoffee_base.h | 1075 ++++ .../graph_msa/graph_align_tcoffee_distance.h | 213 + .../graph_msa/graph_align_tcoffee_guidetree.h | 898 +++ seqan/graph_msa/graph_align_tcoffee_io.h | 1140 ++++ seqan/graph_msa/graph_align_tcoffee_kmer.h | 153 + seqan/graph_msa/graph_align_tcoffee_library.h | 1086 ++++ seqan/graph_msa/graph_align_tcoffee_msa.h | 660 +++ .../graph_align_tcoffee_progressive.h | 485 ++ .../graph_align_tcoffee_refinement.h | 516 ++ seqan/graph_types.h | 82 + seqan/graph_types/graph_base.h | 321 ++ seqan/graph_types/graph_drawing.h | 914 ++++ seqan/graph_types/graph_edgestump.h | 1031 ++++ seqan/graph_types/graph_idmanager.h | 458 ++ seqan/graph_types/graph_impl_automaton.h | 961 ++++ seqan/graph_types/graph_impl_directed.h | 1034 ++++ seqan/graph_types/graph_impl_hmm.h | 983 ++++ seqan/graph_types/graph_impl_oracle.h | 233 + seqan/graph_types/graph_impl_tree.h | 1085 ++++ seqan/graph_types/graph_impl_trie.h | 232 + seqan/graph_types/graph_impl_undirected.h | 835 +++ seqan/graph_types/graph_impl_wordgraph.h | 327 ++ seqan/graph_types/graph_interface.h | 760 +++ seqan/graph_types/graph_iterator.h | 95 + seqan/graph_types/graph_iterator_adjacency.h | 340 ++ seqan/graph_types/graph_iterator_bfs.h | 298 + seqan/graph_types/graph_iterator_dfs.h | 302 + seqan/graph_types/graph_iterator_edge.h | 465 ++ seqan/graph_types/graph_iterator_outedge.h | 1152 ++++ seqan/graph_types/graph_iterator_vertex.h | 345 ++ seqan/graph_types/graph_utility_parsing.h | 94 + seqan/graph_types/property_map_generic.h | 223 + seqan/graph_types/property_map_internal.h | 227 + .../property_map_internal_pointer.h | 232 + seqan/index.h | 243 + seqan/index/find2_backtracking.h | 1359 +++++ seqan/index/find2_base.h | 241 + seqan/index/find2_functors.h | 200 + seqan/index/find2_index.h | 266 + seqan/index/find2_index_multi.h | 455 ++ seqan/index/find2_vstree_factory.h | 325 ++ seqan/index/find_backtracking.h | 1375 +++++ seqan/index/find_index.h | 294 + seqan/index/find_index_approx.h | 331 ++ seqan/index/find_index_binary.h | 1912 +++++++ seqan/index/find_index_esa.h | 105 + seqan/index/find_index_lambda.h | 276 + seqan/index/find_index_qgram.h | 108 + seqan/index/find_pigeonhole.h | 1256 +++++ seqan/index/find_quasar.h | 115 + seqan/index/find_swift.h | 2234 ++++++++ seqan/index/index_base.h | 1624 ++++++ seqan/index/index_bidirectional.h | 208 + seqan/index/index_bidirectional_stree.h | 487 ++ seqan/index/index_bifm.h | 81 + seqan/index/index_bifm_stree.h | 114 + seqan/index/index_bwt.h | 312 ++ seqan/index/index_childtab.h | 297 + seqan/index/index_device.h | 430 ++ seqan/index/index_dfi.h | 692 +++ seqan/index/index_esa_algs.h | 1069 ++++ seqan/index/index_esa_algs_multi.h | 752 +++ seqan/index/index_esa_base.h | 569 ++ seqan/index/index_esa_drawing.h | 112 + seqan/index/index_esa_stree.h | 2892 ++++++++++ seqan/index/index_fm.h | 548 ++ seqan/index/index_fm_compressed_sa.h | 588 ++ seqan/index/index_fm_compressed_sa_iterator.h | 167 + seqan/index/index_fm_dox.h | 576 ++ seqan/index/index_fm_lf_table.h | 816 +++ seqan/index/index_fm_rank_dictionary_base.h | 462 ++ seqan/index/index_fm_rank_dictionary_levels.h | 1846 +++++++ seqan/index/index_fm_rank_dictionary_naive.h | 236 + seqan/index/index_fm_rank_dictionary_wt.h | 472 ++ .../index/index_fm_right_array_binary_tree.h | 436 ++ ...ndex_fm_right_array_binary_tree_iterator.h | 854 +++ seqan/index/index_fm_sparse_string.h | 596 ++ seqan/index/index_fm_stree.h | 557 ++ seqan/index/index_forwards.h | 69 + seqan/index/index_lcp.h | 535 ++ seqan/index/index_lcp_tree.h | 179 + seqan/index/index_pizzachili.h | 389 ++ seqan/index/index_pizzachili_find.h | 161 + seqan/index/index_pizzachili_string.h | 750 +++ seqan/index/index_qgram.h | 2886 ++++++++++ seqan/index/index_qgram_bucketrefinement.h | 634 +++ seqan/index/index_qgram_openaddressing.h | 402 ++ seqan/index/index_qgram_stree.h | 382 ++ seqan/index/index_sa_btree.h | 134 + seqan/index/index_sa_bwtwalk.h | 657 +++ seqan/index/index_sa_lss.h | 451 ++ seqan/index/index_sa_mm.h | 200 + seqan/index/index_sa_qsort.h | 271 + seqan/index/index_sa_stree.h | 699 +++ seqan/index/index_sa_truncated.h | 163 + seqan/index/index_shawarma.h | 100 + seqan/index/index_shims.h | 968 ++++ seqan/index/index_skew3.h | 594 ++ seqan/index/index_skew7.h | 925 ++++ seqan/index/index_skew7_multi.h | 446 ++ seqan/index/index_view.h | 860 +++ seqan/index/index_wotd.h | 2126 ++++++++ seqan/index/pipe_merger3.h | 168 + seqan/index/pipe_merger7.h | 556 ++ seqan/index/pizzachili_api.h | 222 + seqan/index/pump_extender3.h | 141 + seqan/index/pump_extender7.h | 518 ++ seqan/index/pump_lcp_core.h | 388 ++ seqan/index/pump_separator7.h | 85 + seqan/index/radix.h | 195 + seqan/index/repeat_base.h | 594 ++ seqan/index/shape_base.h | 975 ++++ seqan/index/shape_gapped.h | 698 +++ seqan/index/shape_minimizer.h | 179 + seqan/index/shape_onegapped.h | 396 ++ seqan/index/shape_predefined.h | 128 + seqan/index/shape_threshold.h | 1179 ++++ seqan/journaled_set.h | 79 + .../journal_alignment_interface.h | 254 + .../journal_alignment_traceback_adaptor.h | 126 + seqan/journaled_set/journaled_set_base.h | 205 + seqan/journaled_set/journaled_set_impl.h | 280 + seqan/journaled_set/journaled_set_join.h | 130 + .../journaled_set/journaled_set_join_config.h | 160 + .../journaled_set_join_global_align_compact.h | 85 + ...ournaled_set_join_global_align_manhatten.h | 81 + .../journaled_set_journal_trace_descriptor.h | 457 ++ seqan/journaled_set/score_biaffine.h | 299 + seqan/journaled_string_tree.h | 93 + seqan/journaled_string_tree/delta_map.h | 1057 ++++ seqan/journaled_string_tree/delta_map_entry.h | 459 ++ .../delta_map_iterator.h | 600 ++ seqan/journaled_string_tree/delta_store.h | 572 ++ .../journaled_string_tree_base.h | 145 + .../journaled_string_tree_impl.h | 674 +++ .../journaled_string_tree_sequence_buffer.h | 561 ++ .../journaled_string_tree_traverser.h | 523 ++ .../journaled_string_tree_traverser_node.h | 132 + .../journaled_string_tree_traverser_util.h | 1045 ++++ .../jst_extension_base.h | 317 ++ .../jst_extension_horspool.h | 105 + .../jst_extension_myers_ukkonen.h | 277 + .../jst_extension_shiftand.h | 184 + .../jst_extension_shiftor.h | 179 + seqan/journaled_string_tree/observable.h | 183 + seqan/journaled_string_tree/stack_observer.h | 122 + seqan/map.h | 62 + seqan/map/map_adapter_stl.h | 710 +++ seqan/map/map_base.h | 276 + seqan/map/map_chooser.h | 66 + seqan/map/map_skiplist.h | 1127 ++++ seqan/map/map_vector.h | 513 ++ seqan/map/sumlist.h | 214 + seqan/map/sumlist_mini.h | 976 ++++ seqan/map/sumlist_skip.h | 1124 ++++ seqan/math.h | 55 + seqan/math/math_common_factor.h | 524 ++ seqan/math/math_operators.h | 911 ++++ seqan/math/math_rational.h | 584 ++ seqan/misc/accumulators.h | 349 ++ seqan/misc/base.h | 113 + seqan/misc/bit_twiddling.h | 686 +++ seqan/misc/bit_twiddling_functors.h | 140 + seqan/misc/dequeue.h | 401 ++ seqan/misc/edit_environment.h | 1237 +++++ seqan/misc/interval_tree.h | 1914 +++++++ seqan/misc/map.h | 88 + seqan/misc/memset.h | 212 + seqan/misc/name_store_cache.h | 437 ++ seqan/misc/priority_type_base.h | 81 + seqan/misc/priority_type_heap.h | 371 ++ seqan/misc/set.h | 608 +++ seqan/misc/svg.h | 512 ++ seqan/misc/terminal.h | 215 + seqan/misc/union_find.h | 390 ++ seqan/modifier.h | 82 + seqan/modifier/cyclic_shape.h | 622 +++ seqan/modifier/modifier_alphabet.h | 728 +++ seqan/modifier/modifier_alphabet_expansion.h | 512 ++ seqan/modifier/modifier_cyclic_shape.h | 709 +++ seqan/modifier/modifier_functors.h | 298 + seqan/modifier/modifier_iterator.h | 643 +++ seqan/modifier/modifier_padding.h | 425 ++ seqan/modifier/modifier_position.h | 451 ++ seqan/modifier/modifier_reverse.h | 630 +++ seqan/modifier/modifier_shortcuts.h | 464 ++ seqan/modifier/modifier_string.h | 897 +++ seqan/modifier/modifier_view.h | 451 ++ seqan/parallel.h | 93 + seqan/parallel/parallel_algorithms.h | 838 +++ seqan/parallel/parallel_atomic_misc.h | 130 + seqan/parallel/parallel_atomic_primitives.h | 461 ++ seqan/parallel/parallel_lock.h | 308 ++ seqan/parallel/parallel_macros.h | 136 + seqan/parallel/parallel_queue.h | 803 +++ seqan/parallel/parallel_queue_suspendable.h | 463 ++ seqan/parallel/parallel_resource_pool.h | 114 + seqan/parallel/parallel_sequence.h | 190 + seqan/parallel/parallel_serializer.h | 219 + seqan/parallel/parallel_splitting.h | 320 ++ seqan/parallel/parallel_tags.h | 86 + seqan/parse_lm.h | 60 + seqan/parse_lm/local_match_store.h | 418 ++ seqan/parse_lm/parse_blastn_tabular.h | 184 + seqan/parse_lm/parse_lastz_general.h | 216 + seqan/parse_lm/parse_stellar_gff.h | 223 + seqan/pipe.h | 80 + seqan/pipe/pipe_base.h | 1038 ++++ seqan/pipe/pipe_caster.h | 112 + seqan/pipe/pipe_counter.h | 110 + seqan/pipe/pipe_echoer.h | 159 + seqan/pipe/pipe_edit_environment.h | 355 ++ seqan/pipe/pipe_filter.h | 139 + seqan/pipe/pipe_iterator.h | 264 + seqan/pipe/pipe_joiner.h | 133 + seqan/pipe/pipe_namer.h | 149 + seqan/pipe/pipe_sampler.h | 647 +++ seqan/pipe/pipe_shifter.h | 171 + seqan/pipe/pipe_source.h | 420 ++ seqan/pipe/pipe_tupler.h | 482 ++ seqan/pipe/pool_base.h | 1410 +++++ seqan/pipe/pool_mapper.h | 636 +++ seqan/pipe/pool_sorter.h | 469 ++ seqan/platform.h | 465 ++ seqan/random.h | 63 + seqan/random/random_base.h | 119 + seqan/random/random_beta.h | 351 ++ seqan/random/random_util.h | 133 + seqan/realign.h | 57 + seqan/realign/realign_base.h | 1823 +++++++ seqan/realign/realign_helper_functions.h | 205 + seqan/reduced_aminoacid.h | 55 + .../reduced_aminoacid_base.h | 131 + .../reduced_aminoacid_base_late.h | 107 + .../reduced_aminoacid_cluster_red_base.h | 135 + ...aminoacid_cluster_red_tables_20_to_n_b62.h | 1853 +++++++ ...aminoacid_cluster_red_tables_22_to_n_b62.h | 2074 +++++++ ...aminoacid_cluster_red_tables_24_to_n_b62.h | 2296 ++++++++ .../reduced_aminoacid_murphy10_base.h | 122 + .../reduced_aminoacid_murphy10_tables.h | 154 + seqan/rna_io.h | 73 + seqan/rna_io/bpseq_read_write.h | 240 + seqan/rna_io/connect_read_write.h | 302 + seqan/rna_io/dot_bracket_read_write.h | 409 ++ seqan/rna_io/ebpseq_read_write.h | 672 +++ seqan/rna_io/rna_header.h | 121 + seqan/rna_io/rna_io_context.h | 134 + seqan/rna_io/rna_record.h | 279 + seqan/rna_io/rna_struct_file.h | 347 ++ seqan/rna_io/stockholm_read_write.h | 339 ++ seqan/rna_io/vienna_read_write.h | 280 + seqan/roi_io.h | 59 + seqan/roi_io/read_roi.h | 252 + seqan/roi_io/roi_file.h | 147 + seqan/roi_io/roi_io_context.h | 71 + seqan/roi_io/roi_record.h | 119 + seqan/roi_io/write_roi.h | 122 + seqan/score.h | 56 + seqan/score/score_base.h | 344 ++ seqan/score/score_edit.h | 133 + seqan/score/score_matrix.h | 217 + seqan/score/score_matrix_data.h | 945 ++++ seqan/score/score_matrix_dyn.h | 240 + seqan/score/score_matrix_io.h | 329 ++ seqan/score/score_simd_wrapper.h | 183 + seqan/score/score_simple.h | 291 + seqan/seeds.h | 90 + seqan/seeds/banded_chain_alignment.h | 474 ++ seqan/seeds/banded_chain_alignment_impl.h | 1288 +++++ seqan/seeds/banded_chain_alignment_profile.h | 267 + seqan/seeds/banded_chain_alignment_scout.h | 370 ++ .../seeds/banded_chain_alignment_traceback.h | 393 ++ seqan/seeds/basic_iter_indirect.h | 180 + seqan/seeds/seeds_base.h | 42 + seqan/seeds/seeds_combination.h | 461 ++ seqan/seeds/seeds_extension.h | 873 +++ seqan/seeds/seeds_global_chaining.h | 291 + seqan/seeds/seeds_global_chaining_base.h | 44 + seqan/seeds/seeds_global_chaining_gusfield.h | 48 + seqan/seeds/seeds_seed_base.h | 670 +++ seqan/seeds/seeds_seed_chained.h | 503 ++ seqan/seeds/seeds_seed_diagonal.h | 187 + seqan/seeds/seeds_seed_set_base.h | 301 + seqan/seeds/seeds_seed_set_non_scored.h | 56 + seqan/seeds/seeds_seed_set_scored.h | 56 + seqan/seeds/seeds_seed_set_unordered.h | 385 ++ seqan/seeds/seeds_seed_simple.h | 278 + seqan/seq_io.h | 75 + seqan/seq_io/bam_sam.h | 554 ++ seqan/seq_io/fai_index.h | 695 +++ seqan/seq_io/fasta_fastq.h | 497 ++ seqan/seq_io/genomic_region.h | 283 + seqan/seq_io/read_embl.h | 223 + seqan/seq_io/read_genbank.h | 248 + seqan/seq_io/sequence_file.h | 556 ++ seqan/sequence.h | 142 + seqan/sequence/adapt_array_pointer.h | 771 +++ seqan/sequence/adapt_stl_container.h | 1335 +++++ seqan/sequence/container_view.h | 724 +++ seqan/sequence/container_view_zip.h | 295 + seqan/sequence/iter_concat_virtual.h | 563 ++ seqan/sequence/segment_base.h | 839 +++ seqan/sequence/segment_infix.h | 699 +++ seqan/sequence/segment_prefix.h | 642 +++ seqan/sequence/segment_suffix.h | 649 +++ seqan/sequence/segment_utils.h | 130 + seqan/sequence/sequence_concatenator.h | 288 + seqan/sequence/sequence_forwards.h | 199 + seqan/sequence/sequence_interface.h | 1293 +++++ seqan/sequence/sequence_lexical.h | 763 +++ seqan/sequence/sequence_shortcuts.h | 257 + seqan/sequence/string_alloc.h | 446 ++ seqan/sequence/string_array.h | 289 + seqan/sequence/string_base.h | 2083 +++++++ seqan/sequence/string_block.h | 545 ++ seqan/sequence/string_cstyle.h | 853 +++ seqan/sequence/string_packed.h | 2039 +++++++ seqan/sequence/string_packed_old.h | 1278 +++++ seqan/sequence/string_set_base.h | 1844 +++++++ seqan/sequence/string_set_concat_direct.h | 700 +++ .../sequence/string_set_dependent_generous.h | 332 ++ seqan/sequence/string_set_dependent_tight.h | 378 ++ seqan/sequence/string_set_owner.h | 437 ++ seqan/sequence/string_set_segment.h | 511 ++ seqan/sequence/string_set_view.h | 96 + seqan/sequence_journaled.h | 63 + .../journal_entries_sorted_array.h | 750 +++ seqan/sequence_journaled/journal_entry.h | 161 + seqan/sequence_journaled/sequence_journaled.h | 1105 ++++ .../sequence_journaled_iterator.h | 1236 +++++ .../sequence_journaled_iterator_fast.h | 383 ++ seqan/simple_intervals_io.h | 54 + .../simple_intervals_file.h | 176 + .../simple_intervals_io/simple_intervals_io.h | 161 + seqan/statistics.h | 49 + seqan/statistics/statistics_base.h | 489 ++ seqan/statistics/statistics_markov_model.h | 879 +++ seqan/store.h | 72 + seqan/store/store_align.h | 1415 +++++ seqan/store/store_align_intervals.h | 359 ++ seqan/store/store_all.h | 2459 +++++++++ seqan/store/store_annotation.h | 1218 +++++ seqan/store/store_base.h | 47 + seqan/store/store_contig.h | 218 + seqan/store/store_intervaltree.h | 196 + seqan/store/store_io.h | 1297 +++++ seqan/store/store_io_gff.h | 596 ++ seqan/store/store_io_sam.h | 1123 ++++ seqan/store/store_io_ucsc.h | 308 ++ seqan/store/store_library.h | 97 + seqan/store/store_matepair.h | 124 + seqan/store/store_read.h | 101 + seqan/stream.h | 115 + seqan/stream/adapt_ios.h | 402 ++ seqan/stream/buffered_stream.h | 246 + seqan/stream/file_stream.h | 1309 +++++ seqan/stream/formatted_file.h | 957 ++++ seqan/stream/guess_format.h | 224 + seqan/stream/iostream_bgzf.h | 910 ++++ seqan/stream/iostream_bzip2.h | 302 + seqan/stream/iostream_bzip2_impl.h | 429 ++ seqan/stream/iostream_zip.h | 383 ++ seqan/stream/iostream_zip_impl.h | 386 ++ seqan/stream/iostream_zutil.h | 229 + seqan/stream/iter_stream.h | 738 +++ seqan/stream/lexical_cast.h | 287 + seqan/stream/stream_base.h | 232 + seqan/stream/stream_compressor.h | 489 ++ seqan/stream/tokenization.h | 688 +++ seqan/stream/virtual_stream.h | 692 +++ seqan/system.h | 91 + seqan/system/file_async.h | 1259 +++++ seqan/system/file_directory.h | 315 ++ seqan/system/file_forwards.h | 162 + seqan/system/file_sync.h | 495 ++ seqan/system/system_base.h | 65 + seqan/system/system_event_win.h | 236 + seqan/system/system_forwards.h | 81 + seqan/tabix_io.h | 59 + seqan/tabix_io/tabix_index_tbi.h | 532 ++ seqan/translation.h | 48 + seqan/translation/translation.h | 682 +++ seqan/translation/translation_tables.h | 884 +++ seqan/ucsc_io.h | 45 + seqan/ucsc_io/ucsc_file.h | 182 + seqan/ucsc_io/ucsc_io.h | 446 ++ seqan/ucsc_io/ucsc_record.h | 163 + seqan/vcf_io.h | 64 + seqan/vcf_io/read_vcf.h | 276 + seqan/vcf_io/vcf_file.h | 236 + seqan/vcf_io/vcf_header.h | 62 + seqan/vcf_io/vcf_header_record.h | 114 + seqan/vcf_io/vcf_io_context.h | 226 + seqan/vcf_io/vcf_record.h | 202 + seqan/vcf_io/write_vcf.h | 154 + seqan/version.h | 48 + 694 files changed, 321506 insertions(+) create mode 100644 bamviewer.cpp create mode 100644 bamviewer.h create mode 100644 bamviewer.pro create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 mainwindow.ui create mode 100644 seqan/LICENSE create mode 100644 seqan/align.h create mode 100644 seqan/align/align_base.h create mode 100644 seqan/align/align_cols.h create mode 100644 seqan/align/align_config.h create mode 100644 seqan/align/align_interface_wrapper.h create mode 100644 seqan/align/align_iterator_base.h create mode 100644 seqan/align/align_metafunctions.h create mode 100644 seqan/align/align_traceback.h create mode 100644 seqan/align/alignment_algorithm_tags.h create mode 100644 seqan/align/alignment_operations.h create mode 100644 seqan/align/dp_algorithm_impl.h create mode 100644 seqan/align/dp_align_simd_helper.h create mode 100644 seqan/align/dp_band.h create mode 100644 seqan/align/dp_cell.h create mode 100644 seqan/align/dp_cell_affine.h create mode 100644 seqan/align/dp_cell_dynamic.h create mode 100644 seqan/align/dp_cell_linear.h create mode 100644 seqan/align/dp_context.h create mode 100644 seqan/align/dp_formula.h create mode 100644 seqan/align/dp_formula_affine.h create mode 100644 seqan/align/dp_formula_dynamic.h create mode 100644 seqan/align/dp_formula_linear.h create mode 100644 seqan/align/dp_matrix.h create mode 100644 seqan/align/dp_matrix_navigator.h create mode 100644 seqan/align/dp_matrix_navigator_score_matrix.h create mode 100644 seqan/align/dp_matrix_navigator_score_matrix_sparse.h create mode 100644 seqan/align/dp_matrix_navigator_trace_matrix.h create mode 100644 seqan/align/dp_matrix_sparse.h create mode 100644 seqan/align/dp_meta_info.h create mode 100644 seqan/align/dp_profile.h create mode 100644 seqan/align/dp_scout.h create mode 100644 seqan/align/dp_scout_simd.h create mode 100644 seqan/align/dp_setup.h create mode 100644 seqan/align/dp_trace_segment.h create mode 100644 seqan/align/dp_traceback_adaptor.h create mode 100644 seqan/align/dp_traceback_impl.h create mode 100644 seqan/align/evaluate_alignment.h create mode 100644 seqan/align/fragment.h create mode 100644 seqan/align/gap_anchor.h create mode 100644 seqan/align/gapped_value_type.h create mode 100644 seqan/align/gaps_anchor.h create mode 100644 seqan/align/gaps_array.h create mode 100644 seqan/align/gaps_base.h create mode 100644 seqan/align/gaps_iterator_anchor.h create mode 100644 seqan/align/gaps_iterator_array.h create mode 100644 seqan/align/gaps_iterator_base.h create mode 100644 seqan/align/global_alignment_banded.h create mode 100644 seqan/align/global_alignment_hirschberg_impl.h create mode 100644 seqan/align/global_alignment_myers_hirschberg_impl.h create mode 100644 seqan/align/global_alignment_myers_impl.h create mode 100644 seqan/align/global_alignment_specialized.h create mode 100644 seqan/align/global_alignment_unbanded.h create mode 100644 seqan/align/local_alignment_banded.h create mode 100644 seqan/align/local_alignment_banded_waterman_eggert_impl.h create mode 100644 seqan/align/local_alignment_enumeration.h create mode 100644 seqan/align/local_alignment_enumeration_banded.h create mode 100644 seqan/align/local_alignment_enumeration_unbanded.h create mode 100644 seqan/align/local_alignment_unbanded.h create mode 100644 seqan/align/local_alignment_waterman_eggert_impl.h create mode 100644 seqan/align/matrix_base.h create mode 100644 seqan/align_extend.h create mode 100644 seqan/align_extend/align_extend.h create mode 100644 seqan/align_extend/align_extend_base.h create mode 100644 seqan/align_extend/dp_scout_xdrop.h create mode 100644 seqan/align_profile.h create mode 100644 seqan/align_profile/add_to_profile.h create mode 100644 seqan/align_profile/score_profile_seq.h create mode 100644 seqan/align_split.h create mode 100644 seqan/align_split/align_split_interface.h create mode 100644 seqan/align_split/dp_scout_split.h create mode 100644 seqan/alignment_free.h create mode 100644 seqan/alignment_free/af_d2.h create mode 100644 seqan/alignment_free/af_d2star.h create mode 100644 seqan/alignment_free/af_d2z.h create mode 100644 seqan/alignment_free/af_n2.h create mode 100644 seqan/alignment_free/alignment_free_base.h create mode 100644 seqan/alignment_free/alignment_free_comparison.h create mode 100644 seqan/alignment_free/kmer_functions.h create mode 100644 seqan/arg_parse.h create mode 100644 seqan/arg_parse/arg_parse_argument.h create mode 100644 seqan/arg_parse/arg_parse_ctd_support.h create mode 100644 seqan/arg_parse/arg_parse_doc.h create mode 100644 seqan/arg_parse/arg_parse_exceptions.h create mode 100644 seqan/arg_parse/arg_parse_option.h create mode 100644 seqan/arg_parse/arg_parse_parse.h create mode 100644 seqan/arg_parse/arg_parse_type_support.h create mode 100644 seqan/arg_parse/arg_parse_version_check.h create mode 100644 seqan/arg_parse/argument_parser.h create mode 100644 seqan/arg_parse/tool_doc.h create mode 100644 seqan/arg_parse/xml_support.h create mode 100644 seqan/bam_io.h create mode 100644 seqan/bam_io/bam_alignment_record.h create mode 100644 seqan/bam_io/bam_alignment_record_util.h create mode 100644 seqan/bam_io/bam_file.h create mode 100644 seqan/bam_io/bam_header_record.h create mode 100644 seqan/bam_io/bam_index_bai.h create mode 100644 seqan/bam_io/bam_io_context.h create mode 100644 seqan/bam_io/bam_sam_conversion.h create mode 100644 seqan/bam_io/bam_scanner_cache.h create mode 100644 seqan/bam_io/bam_tags_dict.h create mode 100644 seqan/bam_io/cigar.h create mode 100644 seqan/bam_io/read_bam.h create mode 100644 seqan/bam_io/read_sam.h create mode 100644 seqan/bam_io/write_bam.h create mode 100644 seqan/bam_io/write_sam.h create mode 100644 seqan/basic.h create mode 100644 seqan/basic/aggregate_concept.h create mode 100644 seqan/basic/allocator_chunkpool.h create mode 100644 seqan/basic/allocator_interface.h create mode 100644 seqan/basic/allocator_multipool.h create mode 100644 seqan/basic/allocator_simple.h create mode 100644 seqan/basic/allocator_singlepool.h create mode 100644 seqan/basic/allocator_to_std.h create mode 100644 seqan/basic/alphabet_adapt_builtins.h create mode 100644 seqan/basic/alphabet_bio.h create mode 100644 seqan/basic/alphabet_concept.h create mode 100644 seqan/basic/alphabet_math.h create mode 100644 seqan/basic/alphabet_profile.h create mode 100644 seqan/basic/alphabet_qualities.h create mode 100644 seqan/basic/alphabet_residue.h create mode 100644 seqan/basic/alphabet_residue_funcs.h create mode 100644 seqan/basic/alphabet_residue_tabs.h create mode 100644 seqan/basic/alphabet_simple_type.h create mode 100644 seqan/basic/alphabet_storage.h create mode 100644 seqan/basic/array_construct_destruct.h create mode 100644 seqan/basic/basic_aggregate.h create mode 100644 seqan/basic/basic_allocator.h create mode 100644 seqan/basic/basic_alphabet.h create mode 100644 seqan/basic/basic_concept.h create mode 100644 seqan/basic/basic_container.h create mode 100644 seqan/basic/basic_debug.h create mode 100644 seqan/basic/basic_device.h create mode 100644 seqan/basic/basic_exception.h create mode 100644 seqan/basic/basic_functors.h create mode 100644 seqan/basic/basic_fundamental.h create mode 100644 seqan/basic/basic_iterator.h create mode 100644 seqan/basic/basic_math.h create mode 100644 seqan/basic/basic_metaprogramming.h create mode 100644 seqan/basic/basic_parallelism.h create mode 100644 seqan/basic/basic_proxy.h create mode 100644 seqan/basic/basic_simd_vector.h create mode 100644 seqan/basic/basic_smart_pointer.h create mode 100644 seqan/basic/basic_stream.h create mode 100644 seqan/basic/basic_tangle.h create mode 100644 seqan/basic/basic_type.h create mode 100644 seqan/basic/basic_view.h create mode 100644 seqan/basic/boost_preprocessor_subset.h create mode 100644 seqan/basic/builtin_functions.h create mode 100644 seqan/basic/concept_checking.h create mode 100644 seqan/basic/container_concept.h create mode 100644 seqan/basic/debug_helper.h create mode 100644 seqan/basic/debug_test_system.h create mode 100644 seqan/basic/fundamental_chunking.h create mode 100644 seqan/basic/fundamental_comparison.h create mode 100644 seqan/basic/fundamental_concepts.h create mode 100644 seqan/basic/fundamental_conversion.h create mode 100644 seqan/basic/fundamental_metafunctions.h create mode 100644 seqan/basic/fundamental_tags.h create mode 100644 seqan/basic/fundamental_transport.h create mode 100644 seqan/basic/holder_base.h create mode 100644 seqan/basic/holder_simple.h create mode 100644 seqan/basic/holder_tristate.h create mode 100644 seqan/basic/hosted_type_interface.h create mode 100644 seqan/basic/iterator_adapt_pointer.h create mode 100644 seqan/basic/iterator_adapt_std.h create mode 100644 seqan/basic/iterator_adaptor.h create mode 100644 seqan/basic/iterator_base.h create mode 100644 seqan/basic/iterator_concept.h create mode 100644 seqan/basic/iterator_counting.h create mode 100644 seqan/basic/iterator_interface.h create mode 100644 seqan/basic/iterator_position.h create mode 100644 seqan/basic/iterator_range.h create mode 100644 seqan/basic/iterator_zip.h create mode 100644 seqan/basic/macro_deprecated.h create mode 100644 seqan/basic/math_functions.h create mode 100644 seqan/basic/math_log_space_value.h create mode 100644 seqan/basic/metaprogramming_control.h create mode 100644 seqan/basic/metaprogramming_enable_if.h create mode 100644 seqan/basic/metaprogramming_logic.h create mode 100644 seqan/basic/metaprogramming_math.h create mode 100644 seqan/basic/metaprogramming_type.h create mode 100644 seqan/basic/metaprogramming_type_algebra.h create mode 100644 seqan/basic/pair_base.h create mode 100644 seqan/basic/pair_bit_compressed.h create mode 100644 seqan/basic/pair_packed.h create mode 100644 seqan/basic/profiling.h create mode 100644 seqan/basic/property_map_concept.h create mode 100644 seqan/basic/proxy_base.h create mode 100644 seqan/basic/proxy_iterator.h create mode 100644 seqan/basic/test_system.h create mode 100644 seqan/basic/triple_base.h create mode 100644 seqan/basic/triple_packed.h create mode 100644 seqan/basic/tuple_base.h create mode 100644 seqan/basic/tuple_bit_compressed.h create mode 100644 seqan/basic/volatile_ptr.h create mode 100644 seqan/bed_io.h create mode 100644 seqan/bed_io/bed_file.h create mode 100644 seqan/bed_io/bed_record.h create mode 100644 seqan/bed_io/read_bed.h create mode 100644 seqan/bed_io/write_bed.h create mode 100644 seqan/blast.h create mode 100644 seqan/blast/blast_base.h create mode 100644 seqan/blast/blast_io_context.h create mode 100644 seqan/blast/blast_record.h create mode 100644 seqan/blast/blast_report_out.h create mode 100644 seqan/blast/blast_statistics.h create mode 100644 seqan/blast/blast_tabular.h create mode 100644 seqan/blast/blast_tabular_in.h create mode 100644 seqan/blast/blast_tabular_lowlevel.h create mode 100644 seqan/blast/blast_tabular_out.h create mode 100644 seqan/consensus.h create mode 100644 seqan/consensus/consensus_aligner.h create mode 100644 seqan/consensus/consensus_aligner_interface.h create mode 100644 seqan/consensus/consensus_alignment_options.h create mode 100644 seqan/consensus/consensus_base.h create mode 100644 seqan/consensus/consensus_builder.h create mode 100644 seqan/consensus/consensus_library.h create mode 100644 seqan/consensus/consensus_realign.h create mode 100644 seqan/consensus/consensus_score.h create mode 100644 seqan/consensus/overlap_info_computation.h create mode 100644 seqan/consensus/overlapper.h create mode 100644 seqan/file.h create mode 100644 seqan/file/file_base.h create mode 100644 seqan/file/file_cstyle.h create mode 100644 seqan/file/file_forwards.h create mode 100644 seqan/file/file_interface.h create mode 100644 seqan/file/file_mapping.h create mode 100644 seqan/file/file_page.h create mode 100644 seqan/file/string_external.h create mode 100644 seqan/file/string_mmap.h create mode 100644 seqan/find.h create mode 100644 seqan/find/find_abndm.h create mode 100644 seqan/find/find_ahocorasick.h create mode 100644 seqan/find/find_base.h create mode 100644 seqan/find/find_begin.h create mode 100644 seqan/find/find_bndm.h create mode 100644 seqan/find/find_bom.h create mode 100644 seqan/find/find_hamming_simple.h create mode 100644 seqan/find/find_horspool.h create mode 100644 seqan/find/find_lambda.h create mode 100644 seqan/find/find_multi.h create mode 100644 seqan/find/find_multiple_bfam.h create mode 100644 seqan/find/find_multiple_shiftand.h create mode 100644 seqan/find/find_myers_ukkonen.h create mode 100644 seqan/find/find_pattern_base.h create mode 100644 seqan/find/find_pex.h create mode 100644 seqan/find/find_score.h create mode 100644 seqan/find/find_set_horspool.h create mode 100644 seqan/find/find_shiftand.h create mode 100644 seqan/find/find_shiftor.h create mode 100644 seqan/find/find_simple.h create mode 100644 seqan/find/find_wild_shiftand.h create mode 100644 seqan/find/find_wumanber.h create mode 100644 seqan/gff_io.h create mode 100644 seqan/gff_io/gff_file.h create mode 100644 seqan/gff_io/gff_io_base.h create mode 100644 seqan/graph_algorithms.h create mode 100644 seqan/graph_algorithms/all_pairs_shortest_path.h create mode 100644 seqan/graph_algorithms/bellman_ford.h create mode 100644 seqan/graph_algorithms/bipartite_matching.h create mode 100644 seqan/graph_algorithms/breadth_first_search.h create mode 100644 seqan/graph_algorithms/connected_components.h create mode 100644 seqan/graph_algorithms/depth_first_search.h create mode 100644 seqan/graph_algorithms/dijkstra.h create mode 100644 seqan/graph_algorithms/floyd_warshall.h create mode 100644 seqan/graph_algorithms/ford_fulkerson.h create mode 100644 seqan/graph_algorithms/graph_algorithm_heap_tree.h create mode 100644 seqan/graph_algorithms/graph_algorithm_hmm.h create mode 100644 seqan/graph_algorithms/graph_algorithm_lis_his.h create mode 100644 seqan/graph_algorithms/kruskal.h create mode 100644 seqan/graph_algorithms/path_growing.h create mode 100644 seqan/graph_algorithms/prim.h create mode 100644 seqan/graph_algorithms/single_source_shortest_path.h create mode 100644 seqan/graph_algorithms/strongly_connected_compnents.h create mode 100644 seqan/graph_algorithms/topological_sort.h create mode 100644 seqan/graph_algorithms/transitive_closure.h create mode 100644 seqan/graph_algorithms/weakly_connected_components.h create mode 100644 seqan/graph_algorithms/weighted_bipartite_matching.h create mode 100644 seqan/graph_align.h create mode 100644 seqan/graph_align/graph_algorithm_refine_align.h create mode 100644 seqan/graph_align/graph_algorithm_refine_aligngraph.h create mode 100644 seqan/graph_align/graph_algorithm_refine_annotation.h create mode 100644 seqan/graph_align/graph_algorithm_refine_exact.h create mode 100644 seqan/graph_align/graph_algorithm_refine_exact_iterative.h create mode 100644 seqan/graph_align/graph_algorithm_refine_fragment.h create mode 100644 seqan/graph_align/graph_algorithm_refine_inexact.h create mode 100644 seqan/graph_align/graph_algorithm_refine_scoring.h create mode 100644 seqan/graph_align/graph_impl_align.h create mode 100644 seqan/graph_align/graph_impl_align_adapt.h create mode 100644 seqan/graph_msa.h create mode 100644 seqan/graph_msa/graph_align_tcoffee_base.h create mode 100644 seqan/graph_msa/graph_align_tcoffee_distance.h create mode 100644 seqan/graph_msa/graph_align_tcoffee_guidetree.h create mode 100644 seqan/graph_msa/graph_align_tcoffee_io.h create mode 100644 seqan/graph_msa/graph_align_tcoffee_kmer.h create mode 100644 seqan/graph_msa/graph_align_tcoffee_library.h create mode 100644 seqan/graph_msa/graph_align_tcoffee_msa.h create mode 100644 seqan/graph_msa/graph_align_tcoffee_progressive.h create mode 100644 seqan/graph_msa/graph_align_tcoffee_refinement.h create mode 100644 seqan/graph_types.h create mode 100644 seqan/graph_types/graph_base.h create mode 100644 seqan/graph_types/graph_drawing.h create mode 100644 seqan/graph_types/graph_edgestump.h create mode 100644 seqan/graph_types/graph_idmanager.h create mode 100644 seqan/graph_types/graph_impl_automaton.h create mode 100644 seqan/graph_types/graph_impl_directed.h create mode 100644 seqan/graph_types/graph_impl_hmm.h create mode 100644 seqan/graph_types/graph_impl_oracle.h create mode 100644 seqan/graph_types/graph_impl_tree.h create mode 100644 seqan/graph_types/graph_impl_trie.h create mode 100644 seqan/graph_types/graph_impl_undirected.h create mode 100644 seqan/graph_types/graph_impl_wordgraph.h create mode 100644 seqan/graph_types/graph_interface.h create mode 100644 seqan/graph_types/graph_iterator.h create mode 100644 seqan/graph_types/graph_iterator_adjacency.h create mode 100644 seqan/graph_types/graph_iterator_bfs.h create mode 100644 seqan/graph_types/graph_iterator_dfs.h create mode 100644 seqan/graph_types/graph_iterator_edge.h create mode 100644 seqan/graph_types/graph_iterator_outedge.h create mode 100644 seqan/graph_types/graph_iterator_vertex.h create mode 100644 seqan/graph_types/graph_utility_parsing.h create mode 100644 seqan/graph_types/property_map_generic.h create mode 100644 seqan/graph_types/property_map_internal.h create mode 100644 seqan/graph_types/property_map_internal_pointer.h create mode 100644 seqan/index.h create mode 100644 seqan/index/find2_backtracking.h create mode 100644 seqan/index/find2_base.h create mode 100644 seqan/index/find2_functors.h create mode 100644 seqan/index/find2_index.h create mode 100644 seqan/index/find2_index_multi.h create mode 100644 seqan/index/find2_vstree_factory.h create mode 100644 seqan/index/find_backtracking.h create mode 100644 seqan/index/find_index.h create mode 100644 seqan/index/find_index_approx.h create mode 100644 seqan/index/find_index_binary.h create mode 100644 seqan/index/find_index_esa.h create mode 100644 seqan/index/find_index_lambda.h create mode 100644 seqan/index/find_index_qgram.h create mode 100644 seqan/index/find_pigeonhole.h create mode 100644 seqan/index/find_quasar.h create mode 100644 seqan/index/find_swift.h create mode 100644 seqan/index/index_base.h create mode 100644 seqan/index/index_bidirectional.h create mode 100644 seqan/index/index_bidirectional_stree.h create mode 100644 seqan/index/index_bifm.h create mode 100644 seqan/index/index_bifm_stree.h create mode 100644 seqan/index/index_bwt.h create mode 100644 seqan/index/index_childtab.h create mode 100644 seqan/index/index_device.h create mode 100644 seqan/index/index_dfi.h create mode 100644 seqan/index/index_esa_algs.h create mode 100644 seqan/index/index_esa_algs_multi.h create mode 100644 seqan/index/index_esa_base.h create mode 100644 seqan/index/index_esa_drawing.h create mode 100644 seqan/index/index_esa_stree.h create mode 100644 seqan/index/index_fm.h create mode 100644 seqan/index/index_fm_compressed_sa.h create mode 100644 seqan/index/index_fm_compressed_sa_iterator.h create mode 100644 seqan/index/index_fm_dox.h create mode 100644 seqan/index/index_fm_lf_table.h create mode 100644 seqan/index/index_fm_rank_dictionary_base.h create mode 100644 seqan/index/index_fm_rank_dictionary_levels.h create mode 100644 seqan/index/index_fm_rank_dictionary_naive.h create mode 100644 seqan/index/index_fm_rank_dictionary_wt.h create mode 100644 seqan/index/index_fm_right_array_binary_tree.h create mode 100644 seqan/index/index_fm_right_array_binary_tree_iterator.h create mode 100644 seqan/index/index_fm_sparse_string.h create mode 100644 seqan/index/index_fm_stree.h create mode 100644 seqan/index/index_forwards.h create mode 100644 seqan/index/index_lcp.h create mode 100644 seqan/index/index_lcp_tree.h create mode 100644 seqan/index/index_pizzachili.h create mode 100644 seqan/index/index_pizzachili_find.h create mode 100644 seqan/index/index_pizzachili_string.h create mode 100644 seqan/index/index_qgram.h create mode 100644 seqan/index/index_qgram_bucketrefinement.h create mode 100644 seqan/index/index_qgram_openaddressing.h create mode 100644 seqan/index/index_qgram_stree.h create mode 100644 seqan/index/index_sa_btree.h create mode 100644 seqan/index/index_sa_bwtwalk.h create mode 100644 seqan/index/index_sa_lss.h create mode 100644 seqan/index/index_sa_mm.h create mode 100644 seqan/index/index_sa_qsort.h create mode 100644 seqan/index/index_sa_stree.h create mode 100644 seqan/index/index_sa_truncated.h create mode 100644 seqan/index/index_shawarma.h create mode 100644 seqan/index/index_shims.h create mode 100644 seqan/index/index_skew3.h create mode 100644 seqan/index/index_skew7.h create mode 100644 seqan/index/index_skew7_multi.h create mode 100644 seqan/index/index_view.h create mode 100644 seqan/index/index_wotd.h create mode 100644 seqan/index/pipe_merger3.h create mode 100644 seqan/index/pipe_merger7.h create mode 100644 seqan/index/pizzachili_api.h create mode 100644 seqan/index/pump_extender3.h create mode 100644 seqan/index/pump_extender7.h create mode 100644 seqan/index/pump_lcp_core.h create mode 100644 seqan/index/pump_separator7.h create mode 100644 seqan/index/radix.h create mode 100644 seqan/index/repeat_base.h create mode 100644 seqan/index/shape_base.h create mode 100644 seqan/index/shape_gapped.h create mode 100644 seqan/index/shape_minimizer.h create mode 100644 seqan/index/shape_onegapped.h create mode 100644 seqan/index/shape_predefined.h create mode 100644 seqan/index/shape_threshold.h create mode 100644 seqan/journaled_set.h create mode 100644 seqan/journaled_set/journal_alignment_interface.h create mode 100644 seqan/journaled_set/journal_alignment_traceback_adaptor.h create mode 100644 seqan/journaled_set/journaled_set_base.h create mode 100644 seqan/journaled_set/journaled_set_impl.h create mode 100644 seqan/journaled_set/journaled_set_join.h create mode 100644 seqan/journaled_set/journaled_set_join_config.h create mode 100644 seqan/journaled_set/journaled_set_join_global_align_compact.h create mode 100644 seqan/journaled_set/journaled_set_join_global_align_manhatten.h create mode 100644 seqan/journaled_set/journaled_set_journal_trace_descriptor.h create mode 100644 seqan/journaled_set/score_biaffine.h create mode 100644 seqan/journaled_string_tree.h create mode 100644 seqan/journaled_string_tree/delta_map.h create mode 100644 seqan/journaled_string_tree/delta_map_entry.h create mode 100644 seqan/journaled_string_tree/delta_map_iterator.h create mode 100644 seqan/journaled_string_tree/delta_store.h create mode 100644 seqan/journaled_string_tree/journaled_string_tree_base.h create mode 100644 seqan/journaled_string_tree/journaled_string_tree_impl.h create mode 100644 seqan/journaled_string_tree/journaled_string_tree_sequence_buffer.h create mode 100644 seqan/journaled_string_tree/journaled_string_tree_traverser.h create mode 100644 seqan/journaled_string_tree/journaled_string_tree_traverser_node.h create mode 100644 seqan/journaled_string_tree/journaled_string_tree_traverser_util.h create mode 100644 seqan/journaled_string_tree/jst_extension_base.h create mode 100644 seqan/journaled_string_tree/jst_extension_horspool.h create mode 100644 seqan/journaled_string_tree/jst_extension_myers_ukkonen.h create mode 100644 seqan/journaled_string_tree/jst_extension_shiftand.h create mode 100644 seqan/journaled_string_tree/jst_extension_shiftor.h create mode 100644 seqan/journaled_string_tree/observable.h create mode 100644 seqan/journaled_string_tree/stack_observer.h create mode 100644 seqan/map.h create mode 100644 seqan/map/map_adapter_stl.h create mode 100644 seqan/map/map_base.h create mode 100644 seqan/map/map_chooser.h create mode 100644 seqan/map/map_skiplist.h create mode 100644 seqan/map/map_vector.h create mode 100644 seqan/map/sumlist.h create mode 100644 seqan/map/sumlist_mini.h create mode 100644 seqan/map/sumlist_skip.h create mode 100644 seqan/math.h create mode 100644 seqan/math/math_common_factor.h create mode 100644 seqan/math/math_operators.h create mode 100644 seqan/math/math_rational.h create mode 100644 seqan/misc/accumulators.h create mode 100644 seqan/misc/base.h create mode 100644 seqan/misc/bit_twiddling.h create mode 100644 seqan/misc/bit_twiddling_functors.h create mode 100644 seqan/misc/dequeue.h create mode 100644 seqan/misc/edit_environment.h create mode 100644 seqan/misc/interval_tree.h create mode 100644 seqan/misc/map.h create mode 100644 seqan/misc/memset.h create mode 100644 seqan/misc/name_store_cache.h create mode 100644 seqan/misc/priority_type_base.h create mode 100644 seqan/misc/priority_type_heap.h create mode 100644 seqan/misc/set.h create mode 100644 seqan/misc/svg.h create mode 100644 seqan/misc/terminal.h create mode 100644 seqan/misc/union_find.h create mode 100644 seqan/modifier.h create mode 100644 seqan/modifier/cyclic_shape.h create mode 100644 seqan/modifier/modifier_alphabet.h create mode 100644 seqan/modifier/modifier_alphabet_expansion.h create mode 100644 seqan/modifier/modifier_cyclic_shape.h create mode 100644 seqan/modifier/modifier_functors.h create mode 100644 seqan/modifier/modifier_iterator.h create mode 100644 seqan/modifier/modifier_padding.h create mode 100644 seqan/modifier/modifier_position.h create mode 100644 seqan/modifier/modifier_reverse.h create mode 100644 seqan/modifier/modifier_shortcuts.h create mode 100644 seqan/modifier/modifier_string.h create mode 100644 seqan/modifier/modifier_view.h create mode 100755 seqan/parallel.h create mode 100644 seqan/parallel/parallel_algorithms.h create mode 100644 seqan/parallel/parallel_atomic_misc.h create mode 100644 seqan/parallel/parallel_atomic_primitives.h create mode 100644 seqan/parallel/parallel_lock.h create mode 100644 seqan/parallel/parallel_macros.h create mode 100644 seqan/parallel/parallel_queue.h create mode 100644 seqan/parallel/parallel_queue_suspendable.h create mode 100644 seqan/parallel/parallel_resource_pool.h create mode 100644 seqan/parallel/parallel_sequence.h create mode 100644 seqan/parallel/parallel_serializer.h create mode 100644 seqan/parallel/parallel_splitting.h create mode 100644 seqan/parallel/parallel_tags.h create mode 100644 seqan/parse_lm.h create mode 100644 seqan/parse_lm/local_match_store.h create mode 100644 seqan/parse_lm/parse_blastn_tabular.h create mode 100644 seqan/parse_lm/parse_lastz_general.h create mode 100644 seqan/parse_lm/parse_stellar_gff.h create mode 100644 seqan/pipe.h create mode 100644 seqan/pipe/pipe_base.h create mode 100644 seqan/pipe/pipe_caster.h create mode 100644 seqan/pipe/pipe_counter.h create mode 100644 seqan/pipe/pipe_echoer.h create mode 100644 seqan/pipe/pipe_edit_environment.h create mode 100644 seqan/pipe/pipe_filter.h create mode 100644 seqan/pipe/pipe_iterator.h create mode 100644 seqan/pipe/pipe_joiner.h create mode 100644 seqan/pipe/pipe_namer.h create mode 100644 seqan/pipe/pipe_sampler.h create mode 100644 seqan/pipe/pipe_shifter.h create mode 100644 seqan/pipe/pipe_source.h create mode 100644 seqan/pipe/pipe_tupler.h create mode 100644 seqan/pipe/pool_base.h create mode 100644 seqan/pipe/pool_mapper.h create mode 100644 seqan/pipe/pool_sorter.h create mode 100644 seqan/platform.h create mode 100644 seqan/random.h create mode 100644 seqan/random/random_base.h create mode 100644 seqan/random/random_beta.h create mode 100644 seqan/random/random_util.h create mode 100644 seqan/realign.h create mode 100644 seqan/realign/realign_base.h create mode 100644 seqan/realign/realign_helper_functions.h create mode 100644 seqan/reduced_aminoacid.h create mode 100644 seqan/reduced_aminoacid/reduced_aminoacid_base.h create mode 100644 seqan/reduced_aminoacid/reduced_aminoacid_base_late.h create mode 100644 seqan/reduced_aminoacid/reduced_aminoacid_cluster_red_base.h create mode 100644 seqan/reduced_aminoacid/reduced_aminoacid_cluster_red_tables_20_to_n_b62.h create mode 100644 seqan/reduced_aminoacid/reduced_aminoacid_cluster_red_tables_22_to_n_b62.h create mode 100644 seqan/reduced_aminoacid/reduced_aminoacid_cluster_red_tables_24_to_n_b62.h create mode 100644 seqan/reduced_aminoacid/reduced_aminoacid_murphy10_base.h create mode 100644 seqan/reduced_aminoacid/reduced_aminoacid_murphy10_tables.h create mode 100644 seqan/rna_io.h create mode 100644 seqan/rna_io/bpseq_read_write.h create mode 100644 seqan/rna_io/connect_read_write.h create mode 100644 seqan/rna_io/dot_bracket_read_write.h create mode 100644 seqan/rna_io/ebpseq_read_write.h create mode 100644 seqan/rna_io/rna_header.h create mode 100644 seqan/rna_io/rna_io_context.h create mode 100644 seqan/rna_io/rna_record.h create mode 100644 seqan/rna_io/rna_struct_file.h create mode 100644 seqan/rna_io/stockholm_read_write.h create mode 100644 seqan/rna_io/vienna_read_write.h create mode 100644 seqan/roi_io.h create mode 100644 seqan/roi_io/read_roi.h create mode 100644 seqan/roi_io/roi_file.h create mode 100644 seqan/roi_io/roi_io_context.h create mode 100644 seqan/roi_io/roi_record.h create mode 100644 seqan/roi_io/write_roi.h create mode 100644 seqan/score.h create mode 100644 seqan/score/score_base.h create mode 100644 seqan/score/score_edit.h create mode 100644 seqan/score/score_matrix.h create mode 100644 seqan/score/score_matrix_data.h create mode 100644 seqan/score/score_matrix_dyn.h create mode 100644 seqan/score/score_matrix_io.h create mode 100644 seqan/score/score_simd_wrapper.h create mode 100644 seqan/score/score_simple.h create mode 100644 seqan/seeds.h create mode 100644 seqan/seeds/banded_chain_alignment.h create mode 100644 seqan/seeds/banded_chain_alignment_impl.h create mode 100644 seqan/seeds/banded_chain_alignment_profile.h create mode 100644 seqan/seeds/banded_chain_alignment_scout.h create mode 100644 seqan/seeds/banded_chain_alignment_traceback.h create mode 100644 seqan/seeds/basic_iter_indirect.h create mode 100644 seqan/seeds/seeds_base.h create mode 100644 seqan/seeds/seeds_combination.h create mode 100644 seqan/seeds/seeds_extension.h create mode 100644 seqan/seeds/seeds_global_chaining.h create mode 100644 seqan/seeds/seeds_global_chaining_base.h create mode 100644 seqan/seeds/seeds_global_chaining_gusfield.h create mode 100644 seqan/seeds/seeds_seed_base.h create mode 100644 seqan/seeds/seeds_seed_chained.h create mode 100644 seqan/seeds/seeds_seed_diagonal.h create mode 100644 seqan/seeds/seeds_seed_set_base.h create mode 100644 seqan/seeds/seeds_seed_set_non_scored.h create mode 100644 seqan/seeds/seeds_seed_set_scored.h create mode 100644 seqan/seeds/seeds_seed_set_unordered.h create mode 100644 seqan/seeds/seeds_seed_simple.h create mode 100644 seqan/seq_io.h create mode 100644 seqan/seq_io/bam_sam.h create mode 100644 seqan/seq_io/fai_index.h create mode 100644 seqan/seq_io/fasta_fastq.h create mode 100644 seqan/seq_io/genomic_region.h create mode 100644 seqan/seq_io/read_embl.h create mode 100644 seqan/seq_io/read_genbank.h create mode 100644 seqan/seq_io/sequence_file.h create mode 100644 seqan/sequence.h create mode 100644 seqan/sequence/adapt_array_pointer.h create mode 100644 seqan/sequence/adapt_stl_container.h create mode 100644 seqan/sequence/container_view.h create mode 100644 seqan/sequence/container_view_zip.h create mode 100644 seqan/sequence/iter_concat_virtual.h create mode 100644 seqan/sequence/segment_base.h create mode 100644 seqan/sequence/segment_infix.h create mode 100644 seqan/sequence/segment_prefix.h create mode 100644 seqan/sequence/segment_suffix.h create mode 100644 seqan/sequence/segment_utils.h create mode 100644 seqan/sequence/sequence_concatenator.h create mode 100644 seqan/sequence/sequence_forwards.h create mode 100644 seqan/sequence/sequence_interface.h create mode 100644 seqan/sequence/sequence_lexical.h create mode 100644 seqan/sequence/sequence_shortcuts.h create mode 100644 seqan/sequence/string_alloc.h create mode 100644 seqan/sequence/string_array.h create mode 100644 seqan/sequence/string_base.h create mode 100644 seqan/sequence/string_block.h create mode 100644 seqan/sequence/string_cstyle.h create mode 100644 seqan/sequence/string_packed.h create mode 100644 seqan/sequence/string_packed_old.h create mode 100644 seqan/sequence/string_set_base.h create mode 100644 seqan/sequence/string_set_concat_direct.h create mode 100644 seqan/sequence/string_set_dependent_generous.h create mode 100644 seqan/sequence/string_set_dependent_tight.h create mode 100644 seqan/sequence/string_set_owner.h create mode 100644 seqan/sequence/string_set_segment.h create mode 100644 seqan/sequence/string_set_view.h create mode 100644 seqan/sequence_journaled.h create mode 100644 seqan/sequence_journaled/journal_entries_sorted_array.h create mode 100644 seqan/sequence_journaled/journal_entry.h create mode 100644 seqan/sequence_journaled/sequence_journaled.h create mode 100644 seqan/sequence_journaled/sequence_journaled_iterator.h create mode 100644 seqan/sequence_journaled/sequence_journaled_iterator_fast.h create mode 100644 seqan/simple_intervals_io.h create mode 100644 seqan/simple_intervals_io/simple_intervals_file.h create mode 100644 seqan/simple_intervals_io/simple_intervals_io.h create mode 100644 seqan/statistics.h create mode 100644 seqan/statistics/statistics_base.h create mode 100644 seqan/statistics/statistics_markov_model.h create mode 100644 seqan/store.h create mode 100644 seqan/store/store_align.h create mode 100644 seqan/store/store_align_intervals.h create mode 100644 seqan/store/store_all.h create mode 100644 seqan/store/store_annotation.h create mode 100644 seqan/store/store_base.h create mode 100644 seqan/store/store_contig.h create mode 100644 seqan/store/store_intervaltree.h create mode 100644 seqan/store/store_io.h create mode 100644 seqan/store/store_io_gff.h create mode 100644 seqan/store/store_io_sam.h create mode 100644 seqan/store/store_io_ucsc.h create mode 100644 seqan/store/store_library.h create mode 100644 seqan/store/store_matepair.h create mode 100644 seqan/store/store_read.h create mode 100644 seqan/stream.h create mode 100644 seqan/stream/adapt_ios.h create mode 100644 seqan/stream/buffered_stream.h create mode 100644 seqan/stream/file_stream.h create mode 100644 seqan/stream/formatted_file.h create mode 100644 seqan/stream/guess_format.h create mode 100644 seqan/stream/iostream_bgzf.h create mode 100644 seqan/stream/iostream_bzip2.h create mode 100644 seqan/stream/iostream_bzip2_impl.h create mode 100644 seqan/stream/iostream_zip.h create mode 100644 seqan/stream/iostream_zip_impl.h create mode 100644 seqan/stream/iostream_zutil.h create mode 100644 seqan/stream/iter_stream.h create mode 100644 seqan/stream/lexical_cast.h create mode 100644 seqan/stream/stream_base.h create mode 100644 seqan/stream/stream_compressor.h create mode 100644 seqan/stream/tokenization.h create mode 100644 seqan/stream/virtual_stream.h create mode 100644 seqan/system.h create mode 100644 seqan/system/file_async.h create mode 100644 seqan/system/file_directory.h create mode 100644 seqan/system/file_forwards.h create mode 100644 seqan/system/file_sync.h create mode 100644 seqan/system/system_base.h create mode 100644 seqan/system/system_event_win.h create mode 100644 seqan/system/system_forwards.h create mode 100644 seqan/tabix_io.h create mode 100644 seqan/tabix_io/tabix_index_tbi.h create mode 100644 seqan/translation.h create mode 100644 seqan/translation/translation.h create mode 100644 seqan/translation/translation_tables.h create mode 100644 seqan/ucsc_io.h create mode 100644 seqan/ucsc_io/ucsc_file.h create mode 100755 seqan/ucsc_io/ucsc_io.h create mode 100644 seqan/ucsc_io/ucsc_record.h create mode 100644 seqan/vcf_io.h create mode 100644 seqan/vcf_io/read_vcf.h create mode 100644 seqan/vcf_io/vcf_file.h create mode 100644 seqan/vcf_io/vcf_header.h create mode 100644 seqan/vcf_io/vcf_header_record.h create mode 100644 seqan/vcf_io/vcf_io_context.h create mode 100644 seqan/vcf_io/vcf_record.h create mode 100644 seqan/vcf_io/write_vcf.h create mode 100644 seqan/version.h diff --git a/bamviewer.cpp b/bamviewer.cpp new file mode 100644 index 0000000..5723d47 --- /dev/null +++ b/bamviewer.cpp @@ -0,0 +1,48 @@ +#include "bamviewer.h" + +BamViewer::BamViewer(QObject *parent) +{ + + + +} + +void BamViewer::setFilename(const QString &filename) +{ + QFileInfo info(filename); + mFilename = info.absoluteFilePath(); + + QString s = "/home/sacha/exemple.sam"; + qDebug()< +#include +#include +#include + +#include "seqan/bam_io.h" +#include + +#define SEQAN_HAS_ZLIB 1 + +using namespace seqan; + +class BamViewer : public QAbstractScrollArea +{ +public: + BamViewer(QObject * parent = nullptr); + + void setFilename(const QString& filename); + +protected: + + void paintEvent(QPaintEvent * event) override; + +private: + QString mFilename; + +}; + +#endif // BAMVIEWER_H diff --git a/bamviewer.pro b/bamviewer.pro new file mode 100644 index 0000000..e32f43c --- /dev/null +++ b/bamviewer.pro @@ -0,0 +1,39 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2018-01-21T16:57:25 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = bamviewer +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +CONFIG+= c++14 + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + bamviewer.cpp + +HEADERS += \ + mainwindow.h \ + bamviewer.h + +FORMS += \ + mainwindow.ui + +LIBS+= -lz diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..b48f94e --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "mainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..ea070db --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,18 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent) +{ + + mViewer = new BamViewer; + + mViewer->setFilename("/home/sacha/exemple.bam"); + + + setCentralWidget(mViewer); +} + +MainWindow::~MainWindow() +{ +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..10f3776 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,20 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include "bamviewer.h" + + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +private: + BamViewer * mViewer; +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..6050363 --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,24 @@ + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + + + + + + + + + diff --git a/seqan/LICENSE b/seqan/LICENSE new file mode 100644 index 0000000..3d08d0d --- /dev/null +++ b/seqan/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2006-2016, Knut Reinert, FU Berlin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Knut Reinert or the FU Berlin nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + diff --git a/seqan/align.h b/seqan/align.h new file mode 100644 index 0000000..8e5858e --- /dev/null +++ b/seqan/align.h @@ -0,0 +1,224 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_H_ + +// TODO(holtgrew): Usage of gapped value in align module is not consistent, need proxies in many places, reference not cleanly implemented everywhere yet. +// TODO(holtgrew): The Author: tag at the top has to be corrected in the headers of this module. +// TODO(holtgrew): Anchor Gaps must be integrated completely. +// TODO(holtgrew): Local alignments & Fragments don't work nicely together at the moment, multiLocalAlignments() needs an equivalent in the new align module. +// TODO(holtgrew): Align<>, AlignCol<> need some love and documentation. +// TODO(holtgrew): Gaps need better documentation. +// TODO(holtgrew): refinement should become graph_align and also host Graph> +// TODO(holtgrew): graph_msa should become align_msa, or so, see whitepaper. +// TODO(holtgrew): The documentation and Tutorial need heavy updates, clipping alignments howto can go away. + +// ============================================================================ +// Prerequisites +// ============================================================================ + +#include +#include + +#include +#include // ModifiedAlphabet<>. +#include +#include // TODO(holtgrew): We should not have to depend on this. + +// TODO(holtgrew): Why not use priority queue from STL? +#include +#include + +// ============================================================================ +// Support +// ============================================================================ + +#include +#include +#include +#include + +// ============================================================================ +// Gaps & Gaps Iterator Data Structures +// ============================================================================ + +#include + +#include +#include + +#include +#include + +#include +#include +#include + +// ============================================================================ +// Alignment Data Structures and Columns +// ============================================================================ + +#include +#include + +// ============================================================================ +// Alignment Algorithm Implementations. +// ============================================================================ + +//################################################################################ +// New module +//################################################################################ + +// The tags have to be available everywhere so we define them centrally. +#include + +// Defines all tags needed for the DP alignment. +#include + +// The DP Band +#include + +// Stores the score value of a particular cell in the dp matrix. +// If affine gap costs are selected one cell stores the three values +// for all three dp matrices. +#include +#include +#include +#include + +// The DP Scout +#include + +// Stores the actual trace segment that was detected during traceback. +// The trace segments can be adapted into any alignment representation +// form. +#include +#include + +// Implements the different recursion formula of the alignment algorithms. +#include +#include +#include +#include + +// Defines meta informations which determine how to compute a column and a +// certain cell for different profiles. +#include + +// Actual matrix to store the values. Uses the matrix_base.h definitions +// as a host. +#include +#include + +// The navigator that based on the selected profile and band chooses the +// correct way to navigate through the matrix. +#include +#include +#include +#include + +// Ensures the backwards compatibility for the global interfaces of the +// alignment algorithms. Based on the called function this selects the +// correct parameters for the new alignment module. +#include +#include + +#ifdef SEQAN_SIMD_ENABLED +#include +#include +#endif // SEQAN_SIMD_ENABLED + +// The actual implementations of the traceback and the dynamic programming that +// is used by all different alignment algorithms. +#include +#include + +//################################################################################ +// Old module +//################################################################################ + +// Also, we have an implementation of Hirschberg's algorithm to compute +// alignments. +#include + +// The implementations of Myers' bitvector algorithm for alignments can only +// compute alignment scores. The combination of Hirschberg's and Myers' +// algorithm is limited in the same way. +#include +#include + +// Implementations of the local alignment algorithms with declumping. We also +// use them for the localAlignment() calls and return the best local alignment +// only. +// TODO(rmaerker): Replace this with a new implementation based on the new alignment module. +#include +#include + +// We carry around this implementation of Smith-Waterman because it supports +// aligning into fragment strings and alignment graphs. Eventually, it could +// go away if Waterman-Eggert supports them. +//#include + +// ============================================================================ +// Alignment Algorithm Interfaces +// ============================================================================ + +#include + +// The front-end functions for global alignments. +#include +#include + +// The front-end functions for local alignments. +#include +#include + +// The front-end for enumeration of local alignments. +#include // documentation +#include +#include + +// The front-end functions for the more specialized alignment algorithms such as +// Hirschberg, Myers and Myers-Hirschberg. +#include + +// ============================================================================ +// Operations On Alignments +// ============================================================================ + +#include +#include + +#endif // SEQAN_INCLUDE_SEQAN_ALIGN_H_ diff --git a/seqan/align/align_base.h b/seqan/align/align_base.h new file mode 100644 index 0000000..a23afff --- /dev/null +++ b/seqan/align/align_base.h @@ -0,0 +1,740 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// The Align class provides tabular alignments. It contains multiple +// Gap objects, one for each row of the alignment. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_BASE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_BASE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class Align +// ---------------------------------------------------------------------------- + +/*! + * @class Align + * @implements EqualityComparableConcept + * @headerfile + * @brief Tabular alignment of same-type sequences. + * + * @signature template + * class Align; + * + * @tparam TSequence Type of the underlying sequence. + * @tparam TGapSpec Tag for selecting the @link Gaps @endlink specialization. + * + * The Alignment class is for storing tabular alignments of sequences having the same type. They do so by being a + * container of @link Gaps @endlink objects. The most common use case is storing pairwise alignments that are + * generated by one of the dynamic programming alignment algorithms. + * + * @section Example + * + * Here is an example of using an Align object with @link globalAlignment @endlink. + * + * @include demos/dox/align/align.cpp + * + * The output is as follows: + * + * @include demos/dox/align/align.cpp.stdout + * + * @see globalAlignment + * @see localAlignment + * @see Gaps + */ + +template +class Align +{ +public: + typedef Gaps TGaps; + typedef String TRows; + typedef typename Size::Type TRowsSize; + + TRows data_rows; + + Align() {} + + template + Align(StringSet & stringset) + { + setStrings(*this, stringset); + } + + Align & operator=(Align const & other) + { + data_rows = other.data_rows; + return *this; + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Cols +// ---------------------------------------------------------------------------- + +/*! + * @mfn Align#Cols + * @brief Return the type representing a column in an Align object. + * + * @signature Cols::Type + * + * @tparam TAlign The Align object to get the column type for. + * + * @return Type The resulting column type. + */ + +template +struct Cols > +{ + typedef AlignCols > Type; +}; + +template +struct Cols const> +{ + typedef AlignCols const> Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Value +// ---------------------------------------------------------------------------- + +/*! + * @mfn Align#Value + * @brief Return the value type for an Align object. + * + * @signature Value::Type + * + * @tparam TAlign The Align object to get the value type for. + * + * @return Type The resulting value type. + */ + +template +struct Value >: + Value > +{}; +template +struct Value const>: + Value const> +{}; + +// ---------------------------------------------------------------------------- +// Metafunction GetValue +// ---------------------------------------------------------------------------- + +/*! + * @mfn Align#GetValue + * @brief Return the get-value type for an Align object. + * + * @signature GetValue::Type + * + * @tparam TAlign The Align object to get the get-value type for. + * + * @return Type The resulting get-value type. + */ + +template +struct GetValue >: + GetValue > +{}; +template +struct GetValue const>: + GetValue const> +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Reference +// ---------------------------------------------------------------------------- + +/*! + * @mfn Align#Reference + * @brief Return the reference type for an Align object. + * + * @signature GetValue::Type + * + * @tparam TAlign The Align object to get the reference type for. + * + * @return Type The resulting reference type. + */ + +template +struct Reference >: + Reference > +{}; +template +struct Reference const>: + Reference const> +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Rows +// ---------------------------------------------------------------------------- + +/*! + * @mfn Align#Row + * @brief Return the row type (@link Gaps @endlink specialization). + * + * @signature Row::Type + * + * @tparam TAlign The Align object to get the row type for. + * + * @return Type The resulting row type. + */ + +/*! + * @mfn Align#Rows + * @brief Return the type used for rows in an Align object (a Gaps specialization). + * + * @signature Rows::Type + * + * @tparam TAlign The Align object to get the rows type for. + * + * @return Type The resulting rows type. + */ + +template +struct Rows > +{ + typedef String > Type; +}; +template +struct Rows const> +{ + typedef String > const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Source +// ---------------------------------------------------------------------------- + +/*! + * @mfn Align#Source + * @brief Return the type of the underlying sequence. + * + * @signature Rows::Type; + * + * @tparam TAlign The Align object to get the underlying sequence type for. + * + * @return Type The resulting sequence type. + */ + +template +struct Source > +{ + typedef TSource Type; +}; +template +struct Source const> +{ + typedef TSource Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction StringSetType +// ---------------------------------------------------------------------------- + +/*! + * @mfn Align#StringSetType + * @brief Return the type that would be used for a string set of the sources. + * + * @signature Rows::Type + * + * @tparam TAlign The Align object to get the string set type for. + * + * @return Type The resulting string set type. + */ + +template +struct StringSetType > +{ + typedef StringSet > Type; +}; + +template +struct StringSetType const> +{ + typedef StringSet > Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function move() +// ---------------------------------------------------------------------------- + +template +inline +void move(Align & target, Align & source) +{ + move(target.data_rows, source.data_rows); +} + +// ---------------------------------------------------------------------------- +// Function rows() +// ---------------------------------------------------------------------------- + +/*! + * @fn Align#rows + * @brief Returns the rows of an Align object. + * + * @signature TRows rows(align); + * + * @param[in] align The Align object to get the rows for. + * + * @return TRows A container with the Gaps of the Align object. + */ + +template +inline typename Rows >::Type & +rows(Align & me) +{ + return me.data_rows; +} + +template +inline typename Rows const>::Type & +rows(Align const & me) +{ + return me.data_rows; +} + +// ---------------------------------------------------------------------------- +// Function row() +// ---------------------------------------------------------------------------- + +/*! + * @fn Align#row + * @brief Returns a single row of an Align object. + * + * @signature TRow row(align, pos); + * + * @param[in] align The Align object to get the row of. + * @param[in] pos The number of the row to get. + * + * @return TRow Reference to the given row of align (Metafunction: @link Align#Row @endlink). + */ + +template +inline typename Row >::Type & +row(Align & me, + TPosition _pos) +{ + return value(rows(me), _pos); +} + +template +inline typename Row const>::Type & +row(Align const & me, + TPosition _pos) +{ + return value(rows(me), _pos); +} + +// ---------------------------------------------------------------------------- +// Function cols() +// ---------------------------------------------------------------------------- + +/*! + * @fn Align#cols + * @brief Returns the columns of an Align object. + * + * @signature TCols cols(align); + * + * @param[in] align The Align object to get the cols of. + * + * @return TCols The columns of the Align object (Metafunction: @link Align#Cols @endlink). + */ + +template +inline typename Cols >::Type +cols(Align & me) +{ + return typename Cols >::Type(me); +} + +template +inline typename Cols const>::Type +cols(Align const & me) +{ + return typename Cols const>::Type(me); +} + +// ---------------------------------------------------------------------------- +// Function col() +// ---------------------------------------------------------------------------- + +/*! + * @fn Align#col + * @brief Returns the columns of an Align object. + * + * @signature TCol col(align); + * + * @param[in] align The Align object to get the cols of. + * + * @return TCol The column of the Align object (Metafunction: @link Align#Col @endlink). + */ + +template +inline typename Col >::Type +col(Align & me, + TPosition _pos) +{ + return value(cols(me), _pos); +} + +template +inline typename Col const>::Type +col(Align const & me, + TPosition _pos) +{ + return value(cols(me), _pos); +} + +// ---------------------------------------------------------------------------- +// Function detach() +// ---------------------------------------------------------------------------- + +template +inline void +detach(Align & me) +{ + typedef Align TAlign; + typedef typename Rows::Type TRows; + typedef typename Iterator::Type TRowsIterator; + + TRowsIterator it = begin(rows(me)); + TRowsIterator it_end = end(rows(me)); + + while (it != it_end) + { + detach(*it); + ++it; + } +} + +// ---------------------------------------------------------------------------- +// Function write() +// ---------------------------------------------------------------------------- + +/*! + * @fn Align#write + * @deprecated Old-style I/O. + * @brief Writing of Gaps to Streams in human-readable format. + * + * @signature void write(stream, align); + * + * @param[in,out] stream The Stream to write to. + * @param[in] align The Align object to write out. + */ + +template +inline void +write(TFile & target, + Align const & source) +{ + typedef Align const TAlign; + typedef typename Row::Type TRow; + typedef typename Position::Type>::Type TRowsPosition; + typedef typename Position::Type TPosition; + + TRowsPosition row_count = length(rows(source)); + TPosition begin_ = 0; + TPosition end_ = std::min(length(row(source, 0)), length(row(source, 1))); + + unsigned int baseCount = 0; + unsigned int leftSpace = 6; + while (begin_ < end_) + { + unsigned int windowSize_ = 50; + if ((begin_ + windowSize_) > end_) + windowSize_ = end_ - begin_; + + // Print header line + char buffer[20]; + int len = snprintf(buffer, 20, "%7u", (unsigned)baseCount); + write(target, buffer, len); + baseCount += windowSize_; + writeValue(target, ' '); + for (TPosition i = 1; i <= windowSize_; ++i) + { + if ((i % 10) == 0) + writeValue(target, ':'); + else if ((i % 5) == 0) + writeValue(target, '.'); + else + writeValue(target, ' '); + } + writeValue(target, ' '); + writeValue(target, '\n'); + + // Print sequences + for (TRowsPosition i = 0; i < 2 * row_count - 1; ++i) + { + for (unsigned int j = 0; j < leftSpace + 2; ++j) + writeValue(target, ' '); + if ((i % 2) == 0) + { + TRow & row_ = row(source, i / 2); + typedef typename Iterator::Type const, Standard>::Type TIter; + TIter begin1_ = iter(row_, begin_); + TIter end1_ = iter(row_, begin_ + windowSize_); + for (; begin1_ != end1_; ++begin1_) + { + if (isGap(begin1_)) + writeValue(target, gapValue()); + else + writeValue(target, getValue(begin1_)); + } + } + else + { + for (unsigned int j = 0; j < windowSize_; ++j) + { + if ((!isGap(row(source, (i - 1) / 2), begin_ + j)) && + (!isGap(row(source, (i + 1) / 2), begin_ + j)) && + (row(source, (i - 1) / 2)[begin_ + j] == row(source, (i + 1) / 2)[begin_ + j])) + { + writeValue(target, '|'); + } + else + { + writeValue(target, ' '); + } + } + } + writeValue(target, '\n'); + } + writeValue(target, '\n'); + begin_ += 50; + } + writeValue(target, '\n'); +} + +// ---------------------------------------------------------------------------- +// Function clearClipping() +// ---------------------------------------------------------------------------- + +/*! + * @fn Align#clearClipping + * @brief Clear clipping on all rows. + * + * @signature void clearClipping(align); + * + * @param[in,out] align Align object to clear clippings of. + */ + +// TODO(holtgrew): Undocumented. + +template +inline void +clearClipping(Align & align_) +{ + typedef typename Rows >::Type TRows; + typedef typename Iterator::Type TRowsIterator; + + for (TRowsIterator it = begin(rows(align_)); it != end(rows(align_)); goNext(it)) + clearClipping(*it); +} + +// ---------------------------------------------------------------------------- +// Function operator<<() +// ---------------------------------------------------------------------------- + +/*! + * @fn Align#operator<< + * @brief Stream-output for Align objects. + * + * @signature TStream operator<<(stream, align); + * + * @param[in,out] stream std::ostream to write to. + * @param[in] align Align object to write out. + * + * @return TStream Reference to stream after output of align. + */ + +// stream operators + +template +inline TStream & +operator<<(TStream & target, + Align const & source) +{ + typename DirectionIterator::Type it = directionIterator(target, Output()); + write(it, source); + return target; +} + +// ---------------------------------------------------------------------------- +// Function setStrings() +// ---------------------------------------------------------------------------- + +/*! + * @fn Align#setStrings + * @brief Loads the sequences of a string set into an alignment. + * + * @signature void setStrings(align, stringSet); + * + * @param[in,out] align Align object to set underlying sequence of. + * @param[in] stringSet The @link StringSet @endlink with the data. + */ + +template +inline void +setStrings(Align & me, + StringSet & stringset) +{ + typedef Align TAlign; + typedef StringSet TStringset; + + typedef typename Rows::Type TRows; + typedef typename Iterator::Type TRowsIterator; + typedef typename Size::Type TStringsetSize; + + clear(me.data_rows); + resize(me.data_rows, length(stringset)); + TRowsIterator it = begin(rows(me)); + TStringsetSize stringset_length = length(stringset); + for (TStringsetSize i = 0; i < stringset_length; ++i) + { + setSource(*it, value(stringset, i)); + ++it; + } +} + +// ---------------------------------------------------------------------------- +// Function clearGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn Align#clearGaps + * @brief Clear gaps of all Align rows. + * + * @signature void clearGaps(align); + * + * @param[in] align The Align object to clear all all gaps from. + */ + +template +inline void +clearGaps(Align & me) +{ + typedef Align TAlign; + typedef typename Rows::Type TRows; + typedef typename Iterator::Type TRowsIterator; + + for (TRowsIterator it = begin(rows(me)); it != end(rows(me)); goNext(it)) + clearGaps(*it); +} + +// ---------------------------------------------------------------------------- +// Function stringSet() +// ---------------------------------------------------------------------------- + +/*! + * @fn Align#stringSet + * @brief Return string set with all ungapped sequences. + * + * @signature TStringSet stringSet(align); + * + * @param[in] align Align object to get sequences of. + * + * @return TStringSet The set of ungapped sequences (Metafunction: @link Align#StringSetType @endlink). + */ + +template +inline typename StringSetType >::Type +stringSet(Align & me) +{ + typedef Align TAlign; + typedef typename StringSetType::Type TStringSet; + + typedef typename Rows::Type TRows; + typedef typename Iterator::Type TRowsIterator; + + TStringSet ss; + + for (TRowsIterator it = begin(rows(me)); it != end(rows(me)); goNext(it)) + appendValue(ss, source(*it)); + return ss; +} + +// ---------------------------------------------------------------------------- +// Function operator==() +// ---------------------------------------------------------------------------- + +template +inline bool operator==(Align const & lhs, + Align const & rhs) +{ + if (length(lhs.data_rows) != length(rhs.data_rows)) + return false; + typedef typename Align::TGaps TGaps; + typedef typename Iterator::Type TIter; + for (unsigned i = 0; i < length(rhs.data_rows); ++i) + for (TIter itL = begin(lhs.data_rows[i], Rooted()), itR = begin(rhs.data_rows[i], Rooted()); !atEnd(itL); goNext(itL), goNext(itR)) + if (*itL != *itR) + return false; + return true; +} + +// ---------------------------------------------------------------------------- +// Function operator!=() +// ---------------------------------------------------------------------------- + +template +inline bool operator!=(Align const & lhs, + Align const & rhs) +{ + return !(lhs == rhs); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_BASE_H_ diff --git a/seqan/align/align_cols.h b/seqan/align/align_cols.h new file mode 100644 index 0000000..00b625b --- /dev/null +++ b/seqan/align/align_cols.h @@ -0,0 +1,429 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// AlignCols is a wrapper around Align that allows the virtual access to the +// rows of an alignment. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_COLS_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_COLS_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class AlignCols +// ---------------------------------------------------------------------------- + +/*! + * @class AlignCols + * @implements EqualityComparableConcept + * @implements RandomAccessContainerConcept + * @headerfile + * @brief Pseudo columns container for row-based Align class. + * + * @signature template + * class AlignCols; + * + * @tparam TAlign The Align type. + */ + +template +struct AlignCols +{ + // TODO(holtgrew): Do we need this mutable? + mutable TAlign * data_align; + + AlignCols() : + data_align(0) + {} + + + AlignCols(TAlign & align) : data_align(&align) + {} + + template + inline typename Value::Type + operator[](TPosition _pos) + { + return value(*this, _pos); + } + + template + inline typename Value::Type + operator[](TPosition _pos) const + { + return value(*this, _pos); + } +}; + +// ---------------------------------------------------------------------------- +// Specialization AlignCols +// ---------------------------------------------------------------------------- + +template +struct AlignColIterator; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Host +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Add HostedTypeConcept and make AlignCols object implement the concept. + +template +struct Host > +{ + typedef TAlign Type; +}; +template +struct Host const> +{ + typedef TAlign Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction AlignColIterator +// ---------------------------------------------------------------------------- + +template +struct Iterator, TIteratorSpec> +{ + typedef Iter > Type; +}; +template +struct Iterator const, TIteratorSpec> +{ + typedef Iter > Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Value +// ---------------------------------------------------------------------------- + +// Iterator is also used as Value + +template +struct Value >: + Iterator, Standard> +{}; + +template +struct Value const>: + Iterator const, Standard> +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Size +// ---------------------------------------------------------------------------- + +template +struct Size >: + Size::Type> +{}; + +template +struct Size const>: + Size::Type> +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Position +// ---------------------------------------------------------------------------- + +template +struct Position >: + Position::Type> +{}; + +template +struct Position const>: + Position::Type> +{}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function host() +// ---------------------------------------------------------------------------- + +template +inline typename Host >::Type & +host(AlignCols & me) +{ + SEQAN_ASSERT(me.data_align != 0); + return *me.data_align; +} + +template +inline typename Host const>::Type & +host(AlignCols const & me) +{ + SEQAN_ASSERT(me.data_align != 0); + return *me.data_align; +} + +// ---------------------------------------------------------------------------- +// Function iter() +// ---------------------------------------------------------------------------- + +/*! + * @fn AlignCols#iter + * @headerfile + * @brief Iterator to the item at the given position in the alignment columns. + * + * @signature TIterator iter(cols, pos[, tag]); + * + * @param[in] cols The AlignCols object to get the iterator for. + * @param[in] pos The position to get the iterator for. + * @param[in] tag The tag to pick the type of the iterator. + * + * @return TIterator The resulting iterator. If TTag is the type of tag and TAlignCols the + * type of cols then TIterator is of the type Iterator<TAlignCols, + * TTag>::Type. + * + * @section Remarks + * + * If pos is out of range then the iterator is invalid. + */ + +template +inline typename Iterator, Tag const>::Type +iter(AlignCols & me, + TPosition pos_, + Tag const) +{ + return typename Iterator, Tag const>::Type(host(me), pos_); +} + +template +inline typename Iterator const, Tag const>::Type +iter(AlignCols const & me, + TPosition pos_, + Tag const) +{ + return typename Iterator const, Tag const>::Type(host(me), pos_); +} + +// ---------------------------------------------------------------------------- +// Function value() +// ---------------------------------------------------------------------------- + +/*! + * @fn AlignCols#value + * @headerfile + * @brief Returns AlignCols value at a position. + * + * @signature TColumn value(alignCols, pos); + * + * @return TColumn The column, as determined by Value metafunction. + */ + +template +inline typename Value >::Type +value(AlignCols & me, + TPosition _pos) +{ + return iter(me, _pos); +} + +template +inline typename Value const>::Type +value(AlignCols const & me, + TPosition _pos) +{ + return iter(me, _pos); +} + +// ---------------------------------------------------------------------------- +// Function beginPosition() +// ---------------------------------------------------------------------------- + +template +inline typename Position::Type +_beginPositionAlignCols(TAlignCols const & me) +{ + typedef typename Host::Type TAlign; + typename Position::Type>::Type _i = length(rows(host(me))); + + if (!_i) + { + return 0; + } + + --_i; + typename Position::Type _pos = beginPosition(row(host(me), _i)); + + while (_i > 0) + { + --_i; + typename Position::Type _pos2 = beginPosition(row(host(me), _i)); + if (_pos2 < _pos) + { + _pos = _pos2; + } + } + return _pos; +} + +template +inline typename Position >::Type +beginPosition(AlignCols const & me) +{ + return _beginPositionAlignCols(me); +} + +template +inline typename Position >::Type +beginPosition(AlignCols & me) +{ + return _beginPositionAlignCols(me); +} + +// ---------------------------------------------------------------------------- +// Function begin() +// ---------------------------------------------------------------------------- + +template +inline typename Iterator, Tag const>::Type +begin(AlignCols & me, + Tag const tag_) +{ + return iter(me, beginPosition(me), tag_); +} + +template +inline typename Iterator const, Tag const>::Type +begin(AlignCols const & me, + Tag const tag_) +{ + return iter(me, beginPosition(me), tag_); +} + +// ---------------------------------------------------------------------------- +// Function endPosition() +// ---------------------------------------------------------------------------- + +template +inline typename Position::Type +_endPositionAlignCols(TAlignCols const & me) +{ + typedef typename Host::Type TAlign; + + typename Position::Type>::Type _i = length(rows(host(me))); + typename Position::Type _pos = 0; + + while (_i > 0) + { + --_i; + typename Position::Type _pos2 = endPosition(row(host(me), _i)); + if (_pos2 > _pos) + { + _pos = _pos2; + } + } + return _pos; +} + +template +inline typename Position >::Type +endPosition(AlignCols & me) +{ + return _endPositionAlignCols(me); +} + +template +inline typename Position const>::Type +endPosition(AlignCols const & me) +{ + return _endPositionAlignCols(me); +} + +// ---------------------------------------------------------------------------- +// Function end() +// ---------------------------------------------------------------------------- + +template +inline typename Iterator, Tag const>::Type +end(AlignCols & me, + Tag const tag_) +{ + return iter(me, endPosition(me), tag_); +} + +template +inline typename Iterator const, Tag const>::Type +end(AlignCols const & me, + Tag const tag_) +{ + return iter(me, endPosition(me), tag_); +} + +// ---------------------------------------------------------------------------- +// Function length() +// ---------------------------------------------------------------------------- + +template +inline typename Size >::Type +length(AlignCols const & me) +{ + return endPosition(me) - beginPosition(me); +} + +// ---------------------------------------------------------------------------- +// Function operator==() +// ---------------------------------------------------------------------------- + +template +inline bool +operator==(AlignCols const & left, + AlignCols const & right) +{ + return left.data_align == right.data_align; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_COLS_H_ diff --git a/seqan/align/align_config.h b/seqan/align/align_config.h new file mode 100644 index 0000000..b76e683 --- /dev/null +++ b/seqan/align/align_config.h @@ -0,0 +1,395 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Tobias Rausch +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_CONFIG_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_CONFIG_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class AlignConfig +// ---------------------------------------------------------------------------- + +/*! + * @class AlignConfig + * @headerfile + * @brief Indication of whether begin/end gaps are free for DP alignment algorithms. + * + * @signature template + * struct AlignConfig; + * + * @tparam TOP Whether or not the begin gaps in the vertical sequence are free. + * @tparam LEFT Whether or not the begin gaps in the horizontal sequence are free. + * @tparam RIGHT Whether or not the end gaps in the horizontal sequence are free. + * @tparam BOTTOM Whether or not the end gap sin the vertical sequence are free. + * @tparam TSpec Tag for specializing the AlignConfig object (default: Default). + * + * Used in the DP alignment algorithms to configure the begin/end gap free-nes. + * + * @see globalAlignment + * + * @section Specialization List + * + * The following gives an (incomplete) list of useful AlignConfig specializations. + * + *
+ *
AlignConfig<false, false, false, false>
+ *
ordinary global alignment
+ *
AlignConfig<true, false, false, true>
+ *
semiglobal alignment, free begin and end gaps in second/vertical sequence
+ *
AlignConfig<false, true, true, false>
+ *
semiglobal alignment, free begin and end gaps in first/horizontal sequence
+ *
AlignConfig<false, true, false, true>
+ *
overlap alignment with second/vertical sequence overhanging to the left of first/horizontal
+ *
AlignConfig<true, false, true, false>
+ *
overlap alignment with first/horizontal sequence overhanging to the left of second/vertical
+ *
AlignConfig<false, true, false, false>
+ *
free begin gaps in second/vertical sequence only
+ *
AlignConfig<false, false, true, false>
+ *
free end gaps in second/vertical sequence only
+ *
+ */ + +template +class AlignConfig +{}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// TODO(holtgrew): Make this follow the header structure. + +template +inline void +_initFirstColumn(AlignConfig const, + TElement& element, + TCost const cost) +{ + element = cost; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_initFirstColumn(AlignConfig const, + TElement& element, + TCost const) +{ + element = 0; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_initFirstRow(AlignConfig const, + TElement& element, + TCost const cost) +{ + element = cost; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_initFirstRow(AlignConfig const, + TElement& element, + TCost const) +{ + element = 0; +} + +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_lastRow(AlignConfig const, + TValue1&, + TIndex1&, + TValue2 const, + TIndex2 const) +{ + // Nop +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_lastRow(AlignConfig const, + TValue1& maxValue, + TIndex1& maxIndex, + TValue2 const val, + TIndex2 const index) +{ + if (val > maxValue[0]) { + maxValue[0] = val; + maxIndex[0] = index; + } +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_lastColumn(AlignConfig const, + TValue1& maxValue, + TIndex1&, + TColumn const& column) +{ + maxValue[1] = column[length(column) - 1]; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_lastColumn(AlignConfig const, + TValue1& maxValue, + TIndex1& maxIndex, + TColumn const& column) +{ + typedef typename Size::Type TSize; + typedef typename Iterator::Type TColIter; + TSize limit = length(column) - 1; + maxValue[1] = column[limit]; + TColIter itCol = begin(column, Standard()); + TColIter itColEnd = end(column, Standard()); + for(TSize i = 0;itCol != itColEnd; ++i, ++itCol) { + if (*itCol > maxValue[1]) { + maxValue[1] = *itCol; + maxIndex[1] = i; + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline TScoreValue +_maxOfAlignment(AlignConfig const, + TValue& maxValue, + TIndex&, + TSize const, + TSize const) +{ + return maxValue[1]; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline TScoreValue +_maxOfAlignment(AlignConfig const, + TValue& maxValue, + TIndex& maxIndex, + TSize const len1, + TSize const) +{ + maxIndex[0] = len1; + return maxValue[1]; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline TScoreValue +_maxOfAlignment(AlignConfig const, + TValue& maxValue, + TIndex& maxIndex, + TSize const, + TSize const len2) +{ + maxIndex[1] = len2; + return maxValue[0]; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline TScoreValue +_maxOfAlignment(AlignConfig const, + TValue& maxValue, + TIndex& maxIndex, + TSize const len1, + TSize const len2) +{ + // Find the maximum + if (maxValue[1] > maxValue[0]) maxIndex[0] = len1; + else maxIndex[1] = len2; + return (maxValue[0] > maxValue[1]) ? maxValue[0] : maxValue[1]; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_lastColumn(AlignConfig const, + TValue1& maxValue, + TIndex1& maxIndex, + TValue2 const val, + TIndex2 const row, + TIndex2 const col) +{ + maxValue[1] = val; maxIndex[2] = row; maxIndex[3] = col; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_lastColumn(AlignConfig const, + TValue1& maxValue, + TIndex1& maxIndex, + TValue2 const val, + TIndex2 const row, + TIndex2 const col) +{ + if (val > maxValue[1]) {maxValue[1] = val; maxIndex[2] = row; maxIndex[3] = col; } +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_lastRow(AlignConfig const, + TValue1& maxValue, + TIndex1& maxIndex, + TValue2 const val, + TIndex2 const row, + TIndex2 const col) +{ + maxValue[0] = val; maxIndex[0] = row; maxIndex[1] = col; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +_lastRow(AlignConfig const, + TValue1& maxValue, + TIndex1& maxIndex, + TValue2 const val, + TIndex2 const row, + TIndex2 const col) +{ + if (val > maxValue[0]) {maxValue[0] = val; maxIndex[0] = row; maxIndex[1] = col; } +} + + +////////////////////////////////////////////////////////////////////////////// + +template +inline bool +_configValueTop(AlignConfig const) +{ + return true; +} + +template +inline bool +_configValueTop(AlignConfig const) +{ + return false; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline bool +_configValueLeft(AlignConfig const) +{ + return true; +} + +template +inline bool +_configValueLeft(AlignConfig const) +{ + return false; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline bool +_configValueRight(AlignConfig const) +{ + return true; +} + +template +inline bool +_configValueRight(AlignConfig const) +{ + return false; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline bool +_configValueBottom(AlignConfig const) +{ + return true; +} + +template +inline bool +_configValueBottom(AlignConfig const) +{ + return false; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_CONFIG_H_ diff --git a/seqan/align/align_interface_wrapper.h b/seqan/align/align_interface_wrapper.h new file mode 100644 index 0000000..177d0ae --- /dev/null +++ b/seqan/align/align_interface_wrapper.h @@ -0,0 +1,179 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== + +#ifndef INCLUDE_SEQAN_ALIGN_ALIGN_INTERFACE_WRAPPER_H_ +#define INCLUDE_SEQAN_ALIGN_ALIGN_INTERFACE_WRAPPER_H_ + +namespace seqan +{ + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _alignWrapperSequential(); Score; StringSet vs. StringSet +// ---------------------------------------------------------------------------- + +template +inline auto +_alignWrapperSequential(StringSet const & stringsH, + StringSet const & stringsV, + Score const & scoringScheme, + TAlignConfig const & config, + TGapModel const & /*gaps*/) + +{ + String results; + resize(results, length(stringsV)); + + auto zipCont = makeZipView(results, stringsH, stringsV); + forEach(zipCont, + [&] (auto tuple) + { + using namespace seqan; + DPScoutState_ dpScoutState; + String > traceSegments; // Dummy segments. + std::get<0>(tuple) = _setUpAndRunAlignment(traceSegments, dpScoutState, + std::get<1>(tuple), std::get<2>(tuple), scoringScheme, + config, TGapModel()); + }); + return results; +} + +// ---------------------------------------------------------------------------- +// Function _alignWrapperSequential(); Score; String vs. StringSet +// ---------------------------------------------------------------------------- + +template +inline auto +_alignWrapperSequential(TString1 const & stringH, + StringSet const & stringsV, + Score const & scoringScheme, + TAlignConfig const & config, + TGapModel const & /*gaps*/) + +{ + String results; + resize(results, length(stringsV)); + + auto zipCont = makeZipView(results, stringsV); + forEach(zipCont, + [&] (auto tuple) + { + using namespace seqan; + DPScoutState_ dpScoutState; + String > traceSegments; // Dummy segments. + std::get<0>(tuple) = _setUpAndRunAlignment(traceSegments, dpScoutState, stringH, std::get<1>(tuple), + scoringScheme, config, TGapModel()); + }); + return results; +} + +// ---------------------------------------------------------------------------- +// Function _alignWrapperSequential(); Gaps +// ---------------------------------------------------------------------------- + +template +inline auto +_alignWrapperSequential(StringSet, TSetSpecH> & gapSeqSetH, + StringSet, TSetSpecV> & gapSeqSetV, + Score const & scoringScheme, + TAlignConfig const & config, + TGapModel const & /*gaps*/) + +{ + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + + String results; + resize(results, length(gapSeqSetH)); + + auto zipCont = makeZipView(results, gapSeqSetH, gapSeqSetV); + forEach(zipCont, + [&] (auto tuple) + { + using namespace seqan; + String trace; + DPScoutState_ dpScoutState; + std::get<0>(tuple) = _setUpAndRunAlignment(trace, dpScoutState, source(std::get<1>(tuple)), + source(std::get<2>(tuple)), scoringScheme, config, + TGapModel()); + _adaptTraceSegmentsTo(std::get<1>(tuple), std::get<2>(tuple), trace); + }); + return results; +} + +// ---------------------------------------------------------------------------- +// Function _alignWrapper() +// ---------------------------------------------------------------------------- + +template +inline auto _alignWrapper(TArgs && ...args) +{ +#ifdef SEQAN_SIMD_ENABLED + return _alignWrapperSimd(std::forward(args)...); +#else + return _alignWrapperSequential(std::forward(args)...); +#endif +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_ALIGN_ALIGN_INTERFACE_WRAPPER_H_ diff --git a/seqan/align/align_iterator_base.h b/seqan/align/align_iterator_base.h new file mode 100644 index 0000000..4eef6b5 --- /dev/null +++ b/seqan/align/align_iterator_base.h @@ -0,0 +1,527 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== + +#ifndef SEQAN_HEADER_ALIGN_ITERATOR_BASE_H +#define SEQAN_HEADER_ALIGN_ITERATOR_BASE_H + +namespace seqan +{ + +////////////////////////////////////////////////////////////////////////////// +// Align Iterator for Gaps alignment +////////////////////////////////////////////////////////////////////////////// + +// TODO(holtgrew): Extend class Iter? +/*! + * @class AlignColIterator + * @extends Iter + * @headerfile + * @brief Iterator for alignment columns. + * + * @signature template + * class Iter >; + * + * @tparam TAlign Align object to iterate columns of. + * @tparam TSpec Tag for specializing the class further. + */ + +template +class Iter > +{ +public: + typedef typename Rows::Type TRows; + typedef typename Row::Type TRow; + typedef typename Iterator::Type TRowIterator; + typedef typename Position::Type TRowPosition; + typedef String TIterators; + + TAlign * data_host; + TIterators data_iterators; + +public: + Iter() + { + } + Iter(TAlign & _align): + data_host(& _align) + { + typename Position::Type _i = length(rows(_align)); + resize(data_iterators, _i, Exact()); + } + Iter(TAlign & _align, TRowPosition _pos): + data_host(& _align) + { + typename Position::Type _i = length(rows(_align)); + resize(data_iterators, _i, Exact()); + + while (_i > 0) + { + --_i; + data_iterators[_i] = iter(row(_align, _i), _pos); + } + } + Iter(Iter const & _other): + data_host(_other.data_host), + data_iterators(_other.data_iterators) + { + } + ~Iter() + { + } + + Iter const & + operator = (Iter const & _other) + { + data_host = _other.data_host; + data_iterators = _other.data_iterators; + return *this; + } +//____________________________________________________________________________ +}; + +////////////////////////////////////////////////////////////////////////////// + +// TODO(holtgrew); Document as dox/hosted? + +template +inline TAlign & +host(Iter > & me) +{ + return *me.data_host; +} +template +inline TAlign & +host(Iter > const & me) +{ + return *me.data_host; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +setHost(Iter > & me, TAlign & _host) +{ + me.data_host = & _host; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline typename Cols::Type +container(Iter > & me) +{ + return cols(*me.data_host); +} +template +inline typename Cols::Type +container(Iter > const & me) +{ + return cols(*me.data_host); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +goNext(Iter > & me) +{ + typedef typename Row::Type TRow; + typedef typename Iterator::Type TRowIterator; + typedef String TIterators; + typedef typename Iterator::Type TIteratorsIterator; + + TIteratorsIterator _it = begin(me.data_iterators); + TIteratorsIterator _it_end = end(me.data_iterators); + + while (_it != _it_end) + { + goNext(*_it); + ++_it; + } +} +//____________________________________________________________________________ + +template +inline Iter > & +operator ++(Iter > & me) +{ + goNext(me); + return me; +} +//____________________________________________________________________________ + +template +inline Iter > +operator ++(Iter > & me, int) +{ + Iter > ret = me; + goNext(me); + return ret; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +goPrevious(Iter > & me) +{ + typedef typename Row::Type TRow; + typedef typename Iterator::Type TRowIterator; + typedef String TIterators; + typedef typename Iterator::Type TIteratorsIterator; + + TIteratorsIterator _it = begin(me.data_iterators); + TIteratorsIterator _it_end = end(me.data_iterators); + + while (_it != _it_end) + { + goPrevious(*_it); + ++_it; + } +} +//____________________________________________________________________________ + +template +inline Iter > & +operator --(Iter > & me) +{ + goPrevious(me); + return me; +} +//____________________________________________________________________________ + +template +inline Iter > +operator --(Iter > & me, int) +{ + Iter > ret = me; + goPrevious(me); + return ret; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline bool +operator ==(Iter > & _left, + Iter > & _right) +{ + return getValue(_left.data_iterators, 0) == getValue(_right.data_iterators, 0); +} +template +inline bool +operator ==(Iter > const & _left, + Iter > & _right) +{ + return value(_left.data_iterators, 0) == value(_right.data_iterators, 0); +} +template +inline bool +operator ==(Iter > & _left, + Iter > const & _right) +{ + return value(_left.data_iterators, 0) == value(_right.data_iterators, 0); +} +template +inline bool +operator ==(Iter > const & _left, + Iter > const & _right) +{ + return value(_left.data_iterators, 0) == value(_right.data_iterators, 0); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline bool +operator !=(Iter > & _left, + Iter > & _right) +{ + return value(_left.data_iterators, 0) != value(_right.data_iterators, 0); +} +template +inline bool +operator !=(Iter > const & _left, + Iter > & _right) +{ + return value(_left.data_iterators, 0) != value(_right.data_iterators, 0); +} +template +inline bool +operator !=(Iter > & _left, + Iter > const & _right) +{ + return value(_left.data_iterators, 0) != value(_right.data_iterators, 0); +} +template +inline bool +operator !=(Iter > const & _left, + Iter > const & _right) +{ + return value(_left.data_iterators, 0) != value(_right.data_iterators, 0); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline typename Reference::Type +value(Iter > & me, + TPosition pos_) +{ + return value(me.data_iterators[pos_]); +} +template +inline typename Reference::Type +value(Iter > const & me, + TPosition pos_) +{ + return value(me.data_iterators[pos_]); +} +////////////////////////////////////////////////////////////////////////////// + +template +inline typename GetValue::Type +getValue(Iter > & me, + TPosition pos_) +{ + return getValue(me.data_iterators[pos_]); +} +template +inline typename GetValue::Type +getValue(Iter > const & me, + TPosition pos_) +{ + return getValue(me.data_iterators[pos_]); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +assignValue(Iter > & me, + TPosition pos_, + TValue & val) +{ + return assignValue(me.data_iterators[pos_], val); +} +template +inline void +assignValue(Iter > & me, + TPosition pos_, + TValue const & val) +{ + return assignValue(me.data_iterators[pos_], val); +} +template +inline void +assignValue(Iter > const & me, + TPosition pos_, + TValue & val) +{ + return assignValue(me.data_iterators[pos_], val); +} +template +inline void +assignValue(Iter > const & me, + TPosition pos_, + TValue const & val) +{ + return assignValue(me.data_iterators[pos_], val); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +moveValue(Iter > & me, + TPosition pos_, + TValue & val) +{ + return moveValue(me.data_iterators[pos_], val); +} +template +inline void +moveValue(Iter > & me, + TPosition pos_, + TValue const & val) +{ + return moveValue(me.data_iterators[pos_], val); +} +template +inline void +moveValue(Iter > const & me, + TPosition pos_, + TValue & val) +{ + return moveValue(me.data_iterators[pos_], val); +} +template +inline void +moveValue(Iter > const & me, + TPosition pos_, + TValue const & val) +{ + return moveValue(me.data_iterators[pos_], val); +} + +////////////////////////////////////////////////////////////////////////////// + +//??? TODO +//disabled since GapsIterator has no operator - and + +/* +template +inline Iter > & +operator +=(Iter > & me, + TSize size) +{ + typedef typename Row::Type TRow; + typedef typename Iterator::Type TRowIterator; + typedef String TIterators; + typedef typename Iterator::Type TIteratorsIterator; + + TIteratorsIterator _it = begin(me.data_iterators); + TIteratorsIterator _it_end = end(me.data_iterators); + + while (_it != _it_end) + { + *_it += size; + ++_it; + } + return me; +} + + +////////////////////////////////////////////////////////////////////////////// + +template +inline Iter > +operator +(Iter > & me, + TSize size) +{ + Iter > ret = me; + me += size; + return me; +} +template +inline Iter > +operator +(Iter > const & me, + TSize size) +{ + Iter > ret = me; + me += size; + return me; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline Iter > & +operator -=(Iter > & me, + TSize size) +{ + typedef typename Row::Type TRow; + typedef typename Iterator::Type TRowIterator; + typedef String TIterators; + typedef typename Iterator::Type TIteratorsIterator; + + TIteratorsIterator _it = begin(me.data_iterators); + TIteratorsIterator _it_end = end(me.data_iterators); + + while (_it != _it_end) + { + *_it -= size; + ++_it; + } + return me; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline Iter > +operator -(Iter > & me, + TSize size) +{ + Iter > ret = me; + me -= size; + return me; +} +template +inline Iter > +operator -(Iter > const & me, + TSize size) +{ + Iter > ret = me; + me -= size; + return me; +} + +//____________________________________________________________________________ + +template +inline typename Difference::Type +operator -(Iter > const & left, + Iter > const & right) +{ + SEQAN_ASSERT_GT(length(left.data_iterators), 0u); + SEQAN_ASSERT_GT(length(right.data_iterators), 0u); + + return (left.data_iterators[0] - right.data_iterators[0]); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline typename Position::Type +position(Iter > & me) +{ + return position(me.data_iterators[0], row(host(me), 0)); +} +template +inline typename Position::Type +position(Iter > const & me) +{ + return position(me.data_iterators[0], row(host(me), 0)); +} +*/ +////////////////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////////////////// + +}// namespace seqan + +#endif //#ifndef SEQAN_HEADER_... diff --git a/seqan/align/align_metafunctions.h b/seqan/align/align_metafunctions.h new file mode 100644 index 0000000..5ae233c --- /dev/null +++ b/seqan/align/align_metafunctions.h @@ -0,0 +1,115 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// Align-specific metafunctions. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_METAFUNCTIONS_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_METAFUNCTIONS_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Cols +// ---------------------------------------------------------------------------- + +template +struct Cols; + +// ---------------------------------------------------------------------------- +// Metafunction Col +// ---------------------------------------------------------------------------- + +/*! + * @mfn Align#Col + * @headerfile + * @brief The column type for @link Align @endlink objects. + * + * @signature Col::Type + * + * @tparam TAlign The @link Align @endlink object to query for its column type. + * + * @return Type The resulting type. + */ + +template +struct Col : Value::Type> +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Rows +// ---------------------------------------------------------------------------- + +template +struct Rows; + +// ---------------------------------------------------------------------------- +// Metafunction Row +// ---------------------------------------------------------------------------- + +template +struct Row : Value::Type> +{}; + +template +struct Row +{ + typedef typename Row::Type const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction StringSetType +// ---------------------------------------------------------------------------- + +template +struct StringSetType; + +// ============================================================================ +// Functions +// ============================================================================ + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_METAFUNCTIONS_H_ diff --git a/seqan/align/align_traceback.h b/seqan/align/align_traceback.h new file mode 100644 index 0000000..6b9ea34 --- /dev/null +++ b/seqan/align/align_traceback.h @@ -0,0 +1,161 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// Author: Tobias Rausch +// ========================================================================== +// AlignTraceback object for storing the alignment traceback results. +// +// The _pump* functions for converting from AlignTrace to Gaps and Fragment +// String objects are defined where Gaps / the Alignment Graph spec is +// defined. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_TRACEBACK_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_TRACEBACK_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Specialization TraceBack +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Mark as internal with underscore? + +/*! + * @typedef TraceBack + * @headerfile + * @brief Traceback value. + * + * @signature struct TraceBack_; + * @signature typedef SimpleType TraceBack. + * + * The ValueSize of TraceBack is 3. The values are defined in the following way: + * + *
    + *
  • 0 - Diagonal Move
  • + *
  • 1 - Horizontal Move
  • + *
  • 2 - Vertical Move
  • + *
+ */ + +struct TraceBack_ {}; +typedef SimpleType TraceBack; + +template <> struct ValueSize +{ + typedef uint8_t Type; + static const Type VALUE = 3; +}; + +template <> struct BitsPerValue +{ + typedef uint8_t Type; + static const Type VALUE = 2; +}; + +// ---------------------------------------------------------------------------- +// Helper Class AlignTraceback +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Mark as internal with underscore? + +/*! + * @class AlignTraceback + * @headerfile + * @brief Data structure for storing alignment traceback. + * + * @signature template + * struct AlignTraceback; + * + * @tparam TSize Size type to use in the traceback. + */ + +/*! + * @var TSizes AlignTraceback::sizes + * @brief The traceback lengths. + */ + +/*! + * @var TLengths AlignTraceback::tsv + * @brief The traceback lengths. + */ + +template +struct AlignTraceback +{ + // Run lengths in the align matrix. + String sizes; + // Trace values: 0 = diagonal, 1 = horizontal, 2 = vertical. + String tvs; +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _alignTracePrint() +// ---------------------------------------------------------------------------- + +// _alignTracePrint: this function is called by various alignment algorithm to build up the alignment during traceback + +template +inline void +_alignTracePrint(AlignTraceback & tb, + TSequenceH const &, + TSequenceV const &, + TId const, + TPos const, + TId const, + TPos const, + TPos const segLen, + TTraceValue const tv) +{ + appendValue(tb.sizes, segLen); + appendValue(tb.tvs, tv); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGN_TRACEBACK_H_ diff --git a/seqan/align/alignment_algorithm_tags.h b/seqan/align/alignment_algorithm_tags.h new file mode 100644 index 0000000..741645a --- /dev/null +++ b/seqan/align/alignment_algorithm_tags.h @@ -0,0 +1,165 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// We put the tag definition into its own header so we can include them +// independently from the algorithms. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGNMENT_ALGORITHM_TAGS_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_ALIGNMENT_ALGORITHM_TAGS_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Global Alignment Algorithm Tags +// ---------------------------------------------------------------------------- + +/*! + * @defgroup AlignmentAlgorithmTags Alignment Algorithm Tags + * @brief Tags for selecting algorithms. + */ + +// TODO(holtgrew): Rename MyersBitVector to Myers? Clashes with find module at the moment. + +/*! + * @tag AlignmentAlgorithmTags#Gotoh + * @headerfile + * @brief Tag for selecting Gotoh DP algorithm. + * + * @signature struct Gotoh_; + * @signature typedef Tag Gotoh; + */ + +struct Gotoh_; +typedef Tag Gotoh; + +/*! + * @tag AlignmentAlgorithmTags#NeedlemanWunsch + * @headerfile + * @brief Tag for selecting NeedlemanWunsch DP algorithm. + * + * @signature struct Hirschberg_; + * @signature typedef Tag NeedlemanWunsch; + */ + +struct NeedlemanWunsch_; +typedef Tag NeedlemanWunsch; + +/*! + * @tag AlignmentAlgorithmTags#Hirschberg + * @headerfile + * @brief Tag for selecting Hirschberg's DP algorithm. + * + * @signature struct Hirschberg_; + * @signature typedef Tag Hirschberg; + */ + +struct Hirschberg_; +typedef Tag Hirschberg; + +/*! + * @tag AlignmentAlgorithmTags#MyersBitVector + * @headerfile + * @brief Tag for selecting Myers' bit-vector algorithm. + * + * @signature struct MyersBitVector_; + * @signature typedef Tag MyersBitVector; + */ + +struct MyersBitVector_; +typedef Tag MyersBitVector; + +/*! + * @tag AlignmentAlgorithmTags#MyersHirschberg + * @headerfile + * @brief Tag for selecting a combination of Myers' bit-vector algorithm with Hirschberg's algorithm. + * + * @signature struct MyersHirschberg_; + * @signature typedef Tag MyersHirschberg; + */ + +struct MyersHirschberg_; +typedef Tag MyersHirschberg; + +// ---------------------------------------------------------------------------- +// Local Alignment Algorithm Tags +// ---------------------------------------------------------------------------- + +/*! + * @defgroup PairwiseLocalAlignmentAlgorithms Pairwise Local Alignment Algorithms + * @brief Tags for selecting algorithms. + */ + +/*! + * @tag PairwiseLocalAlignmentAlgorithms#SmithWaterman + * @headerfile + * @brief Tag for selecting the Smith-Waterman algorithm. + * + * @signature struct SmithWaterman_; + * @signature typedef Tag SmithWaterman; + */ + +struct SmithWaterman_; +typedef Tag SmithWaterman; + +/*! + * @tag PairwiseLocalAlignmentAlgorithms#WatermanEggert + * @headerfile + * @brief Tag for selecting the Waterman-Eggert algorithm. + * + * @signature struct WatermanEggert_; + * @signature typedef Tag WatermanEggert; + */ + +struct WatermanEggert_; +typedef Tag WatermanEggert; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGNMENT_ALGORITHM_TAGS_H_ diff --git a/seqan/align/alignment_operations.h b/seqan/align/alignment_operations.h new file mode 100644 index 0000000..fccc61a --- /dev/null +++ b/seqan/align/alignment_operations.h @@ -0,0 +1,149 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Birte Kehr +// ========================================================================== +// Operations on alignments such as integration +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGNMENT_OPERATIONS_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_ALIGNMENT_OPERATIONS_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +template +inline void +integrateGaps(Gaps & targetRow, + Gaps const & sourceRow, + TPos const viewPos) +{ + typedef typename Iterator, Standard>::Type TTargetIt; + typedef typename Iterator const, Standard>::Type TSourceIt; + + // This assertion ensures that the number of sequence characters after viewPos is greater than or equal to + // the number of source characters in the clipped infix row. + SEQAN_ASSERT_GEQ(endPosition(targetRow) - toSourcePosition(targetRow, viewPos), + endPosition(sourceRow) - beginPosition(sourceRow)); + + // init iterators + TTargetIt it = iter(targetRow, viewPos); + + // walk through Gaps containers and copy gaps + for (TSourceIt sIt = begin(sourceRow, Standard()), sItEnd = end(sourceRow, Standard()); sIt != sItEnd;) + { + TPos gapSize = countGaps(sIt); + insertGaps(it, gapSize); + goFurther(it, gapSize+1); + goFurther(sIt, gapSize+1); + } +} + +template +inline void +integrateGaps(Gaps & targetRow, + Gaps const & sourceRow) +{ + typename Position::Type viewPos = beginPosition(source(sourceRow)) // correct for infixes + - beginPosition(source(targetRow)) // ... + + beginPosition(sourceRow); // respect source clipping + + integrateGaps(targetRow, sourceRow, toViewPosition(targetRow, viewPos)); +} + +// ---------------------------------------------------------------------------- +// Function integrateAlign() +// ---------------------------------------------------------------------------- + +/*! + * @fn integrateAlign + * @headerfile + * @brief Integrates an alignment into another by copying the gaps. + * + * @signature void integrateAlign(align1, align2[, positions]); + * + * @param[in,out] align1 Target Alignment object into which align2 is to be integrated. + * @param[in] align2 Alignment object that is to be integrated into align1. + * @param[in] positions The integration positions in align1 for all rows (view positions), String of positions. + * + * @section Examples + * + * @include demos/dox/align/integrate_align.cpp + * + * The output is as follows: + * + * @include demos/dox/align/integrate_align.cpp.stdout + */ + +template +void integrateAlign(Align & align, + Align const & infixAlign, + String const & viewPos) +{ + SEQAN_ASSERT_EQ_MSG(length(rows(infixAlign)), length(rows(align)), "Both align objects need same number of rows."); + typedef typename Size >::Type TSize; + //NOTE(h-2): could be parallelized + for (TSize i = 0; i < length(rows(align)); ++i) + integrateGaps(row(align, i), row(infixAlign, i), viewPos[i]); +} + +template +void integrateAlign(Align & align, + Align const & infixAlign) +{ + SEQAN_ASSERT_EQ_MSG(length(rows(infixAlign)), length(rows(align)), "Both align objects need same number of rows."); + typedef typename Size >::Type TSize; + //NOTE(h-2): could be parallelized + for (TSize i = 0; i < length(rows(align)); ++i) + integrateGaps(row(align, i), row(infixAlign, i)); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_ALIGNMENT_OPERATIONS_H_ diff --git a/seqan/align/dp_algorithm_impl.h b/seqan/align/dp_algorithm_impl.h new file mode 100644 index 0000000..39ae3d8 --- /dev/null +++ b/seqan/align/dp_algorithm_impl.h @@ -0,0 +1,1599 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Implements the core of the dp algorithms. +// This is the crucial part of the refactoring of the alignment algorithms. +// It implements - at the moment only a column wise approach - the core +// loop structure for all alignment profiles. We generally differ between an +// unbanded alignment which is very easy, a banded alignment and a special +// case of the banded alignment the Hamming distance, where upper diagonal +// equals lower diagonal. +// +// The unbanded alignment: +// The computation of the unbanded alignment is divided into three parts. +// In the following we refer to a track as the part where the inner loop +// is iterating (in case of column wise navigation a track is equivalent +// to a column). +// First we compute the initial track. Afterwards we continue with all +// inner tracks of the dp matrix and in the end we compute the last track +// separately. This is because all three types have a special property that +// is different from the other track types. +// Each track itself is further divided into three parts, namely the first cell +// the inner cell and the last cell, corresponding to the initial row, +// all inner rows and the last row of a typical dp matrix. This partition of +// the dp matrix allows us to easily change the behavior of different cells +// according to the chosen dp profile at compile time. +// See alignment_dp_meta_info.h to learn about the different meta objects +// that manage the characteristics of each cell of a particular track type. +// +// The banded alignment: +// In the banded alignment we generally divide the dp matrix into the same +// partition as for the unbanded alignment. The only difference is that we, +// additionally add a specific information of how the current track is +// located within the dp matrix. Since we only consider a band we do not +// necessarily span over the full matrix size for a particular column. +// We distinguish between the locations: PartialColumnTop, +// PartialColumnMiddle, PartialColumnBottom and FullColumn (which is the +// default location for unbanded alignments). Each location of the column +// implies a different composition of the cells contained within a +// particular track. Thus, we are able to set different recursion +// directions and tracking informations for each cell independent from the +// runtime. The only difference is that the outer for-loop (iterating over +// the tracks) is split up into three loops. The first loop then only +// iterates over these tracks that are located at the top of the matrix. +// The second for-loop iterates over the tracks that either are of type +// PartialColumnMiddle or FullColumn (wide bands, where the upper diagonal +// begins behind the track where the lower diagonal crosses the last row of +// the dp matrix). And the last for-loop iterates over the tail of the band +// which is located at the PartialColumnBottom. +// +// The Hamming distance: +// In the special case where upper diagonal equals lower diagonal we only +// have to parse one diagonal of the matrix so we have a special +// implementation for that, though it works for all dp profiles. +// +// Restricitons: +// At the moment we have implemented a restriction such that not all bands +// are accepted. If the dp profile consists of the standard global alignment +// algorithm (NeedlemanWunsch or Gotoh), the band is required to go through +// the sink and the source of the dp matrix. If this is not given the +// alignment algorithm is aborted and the score MinValue::VALUE +// is returned. +// There are no further restrictions. +// +// GapCosts: +// Another detail of the new module is the selection of the gap functions, +// which is also now part of the compile time configuration. Whenever an +// algorithm is implemented it would automatically work for both gap +// functions (linear gaps and affine gaps). +// +// Navigation: +// It is possible to a certain degree to change the behavior of how to parse +// through the dp matrix. Using the new navigators one can implement +// different behaviors for different matrices. At the moment we only support +// column wise navigation for full and sparse score matrices and for full +// traceback matrices. Another detail of this navigators comes into account, +// when we want to compute only the score. We actually create a navigator +// for the dp matrix but implemented it this way that it gets never actually +// called when the traceback is disabled. Thus we do not store the traceback +// matrix if it is not necessary. +// +// Traceback: +// The traceback is now implemented as a single function that is used by all +// alignment profiles. Here we prefer the diagonal direction before the +// vertical before the horizontal direction. +// All tracebacks are first stored within the String object +// and afterwards, when the traceback is finished adapted to its given +// target object such as Align, Graph, Fragments, etc. +// +// Tracing: +// We use now an object called DPScout to keep track of the maximal score. +// This object scouts for the best value and can be overloaded to implement +// different strategies of how the score should be traced. Togehter with +// the meta_info file it only traces thus cells that are allowed to be +// traced given the current dp profile. Since this is also a compile time +// property we do not need to track every cell for the global alignment, +// while we do in the local alignment. +// +// Structure: +// The sequences within the matrix are marked as horizontal and vertical +// sequence to determine there orientation within the matrix. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_ALGORITHM_IMPL_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_ALGORITHM_IMPL_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function prepareAlign() +// ---------------------------------------------------------------------------- + +template +inline void +prepareAlign(StringSet > & align, + TSequence const & strH, + StringSet const & setV) +{ + size_t numAlignments = length(setV); + + SEQAN_ASSERT_EQ(length(align), 0u); + SEQAN_ASSERT_GT(numAlignments, 0u); + + resize(align, numAlignments); + for(size_t i = 0; i < numAlignments; ++i) + { + resize(rows(align[i]), 2); + assignSource(row(align[i], 0), strH); + assignSource(row(align[i], 1), setV[i]); + } +} + +// ---------------------------------------------------------------------------- +// Function _checkBandProperties() +// ---------------------------------------------------------------------------- + +// Checks whether the chosen band fits the dp profile. +template +inline bool _checkBandProperties(TSequenceH const & /*seqH*/, + TSequenceV const & /*seqV*/, + DPBandConfig const & /*band*/, + TAlignmentProfile const & /*alignProfile*/) +{ + return true; +} + +template +inline bool _checkBandProperties(TSequenceH const & seqH, + TSequenceV const & seqV, + DPBandConfig const & band, + TAlignmentProfile const & /*alignProfile*/) +{ + typedef typename MakeSigned::Type>::Type TSignedSize; + + // Check if the intersection between band and DP matrix is empty. + if (upperDiagonal(band) < (0 - static_cast(length(seqV))) || + lowerDiagonal(band) > static_cast(length(seqH))) + { + return false; + } + + // If the band begins before the beginning of the horizontal sequence + // then check if free end-gaps are enabled at the beginning of the vertical sequence. + if (upperDiagonal(band) < 0 && !IsFreeEndGap_::VALUE) + return false; + + // If the band begins before the beginning of the vertical sequence + // then check if free end-gaps are enabled at the beginning of the horizontal sequence. + if (lowerDiagonal(band) > 0 && !IsFreeEndGap_::VALUE) + return false; + + // If the band ends behind the end of the vertical sequence + // then check if free end-gaps are enabled at the end of the horizontal sequence. + if (upperDiagonal(band) + static_cast(length(seqV)) < static_cast(length(seqH)) && + !IsFreeEndGap_::VALUE) + { + return false; + } + + // If the band ends behind the end of the horizontal sequence + // then check if free end-gaps are enabled at the end of the vertical sequence. + if (lowerDiagonal(band) + static_cast(length(seqV)) > static_cast(length(seqH)) && + !IsFreeEndGap_::VALUE) + { + return false; + } + + return true; +} + +// ---------------------------------------------------------------------------- +// Function _invalidDPSettings() +// ---------------------------------------------------------------------------- + + +// Checks if the settings for the dp algorithm are valid. +// Returns true if they are valid, false otherwise. +template +inline bool _isValidDPSettings(TSequenceH const & seqH, + TSequenceV const & seqV, + TBand const & band, + TAlignmentProfile const & alignProfile) +{ + // Check if the sequences are empty. + if (empty(seqH) || empty(seqV)) + { + return false; + } + + return _checkBandProperties(seqH, seqV, band, alignProfile); +} + +// ---------------------------------------------------------------------------- +// Function _isBandEnabled() +// ---------------------------------------------------------------------------- + +// Returns true if a band is selected, otherwise false. +template +inline bool +_isBandEnabled(DPBandConfig const & /*band*/) +{ + return IsSameType::VALUE; +} + +// ---------------------------------------------------------------------------- +// Function _computeCell() +// ---------------------------------------------------------------------------- + +// Computes the score and tracks it if enabled. +template +inline void +_computeCell(TDPScout & scout, + TTraceMatrixNavigator & traceMatrixNavigator, + DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + TColumnDescriptor const &, + TCellDescriptor const &, // One of FirstCell, InnerCell or LastCell. + TDPProfile const &) +{ + typedef DPMetaColumn_ TMetaColumn; + assignValue(traceMatrixNavigator, + _computeScore(activeCell, previousDiagonal, previousHorizontal, previousVertical, seqHVal, seqVVal, + scoringScheme, typename RecursionDirection_::Type(), + TDPProfile())); + + if (TrackingEnabled_::VALUE) + { + typedef typename LastColumnEnabled_::Type TIsLastColumn; + typedef typename LastRowEnabled_::Type TIsLastRow; + _scoutBestScore(scout, activeCell, traceMatrixNavigator, + TIsLastColumn(), TIsLastRow()); + } +} + +// ---------------------------------------------------------------------------- +// Function _precomputeScoreMatrixOffset() +// ---------------------------------------------------------------------------- + +// Default fallback if scoring scheme is not a matrix. +template +inline TSeqValue const & +_precomputeScoreMatrixOffset(TSeqValue const & seqVal, + TScoringScheme const & /*score*/) +{ + return seqVal; +} + +// ---------------------------------------------------------------------------- +// Function _computeTrack() +// ---------------------------------------------------------------------------- + +// Computes one track of the dp algorithm. A track is defined as the area that is filled by the inner loop and +// iterated by the outer loop. For the column-wise navigation the track is equivalent with the column. +template +inline void +_computeTrack(TDPScout & scout, + TDPScoreMatrixNavigator & dpScoreMatrixNavigator, + TDPTraceMatrixNavigator & dpTraceMatrixNavigator, + TSeqHValue const & seqHValue, + TSeqVValue const & seqVValue, + TSeqVIterator const & seqBegin, + TSeqVIterator const & seqEnd, + TScoringScheme const & scoringScheme, + TColumnDescriptor const &, + TDPProfile const &) +{ + // Set the iterator to the begin of the track. + _goNextCell(dpScoreMatrixNavigator, TColumnDescriptor(), FirstCell()); + _goNextCell(dpTraceMatrixNavigator, TColumnDescriptor(), FirstCell()); + + // Precompute the row of the scoring matrix for future look-ups. + TSeqHValue tmpSeqH = _precomputeScoreMatrixOffset(seqHValue, scoringScheme); + + // Initilaize SIMD version with multiple end points. + _preInitScoutVertical(scout); + + // Compute the first cell. + _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), + previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), + previousCellVertical(dpScoreMatrixNavigator), tmpSeqH, seqVValue, scoringScheme, + TColumnDescriptor(), FirstCell(), TDPProfile()); + + TSeqVIterator iter = seqBegin; + TSeqVIterator itEnd = (seqEnd - 1); + // Compute the inner cells of the current track. + for (; iter != itEnd; ++iter) + { + // Set the iterator to the next cell within the track. + _goNextCell(dpScoreMatrixNavigator, TColumnDescriptor(), InnerCell()); + _goNextCell(dpTraceMatrixNavigator, TColumnDescriptor(), InnerCell()); + // Compute the inner cell. + // If we have variable length simd, we need to check if we reached the end of one of the sequences. + // For all other cases, the function returns always false. + if (SEQAN_UNLIKELY(_reachedVerticalEndPoint(scout, iter))) + { + _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), + previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), + previousCellVertical(dpScoreMatrixNavigator), tmpSeqH, + sequenceEntryForScore(scoringScheme, container(iter), position(iter)), scoringScheme, + TColumnDescriptor(), LastCell(), TDPProfile()); + _nextVerticalEndPos(scout); + } + else + { + _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), + previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), + previousCellVertical(dpScoreMatrixNavigator), tmpSeqH, + sequenceEntryForScore(scoringScheme, container(iter), position(iter)), scoringScheme, + TColumnDescriptor(), InnerCell(), TDPProfile()); + } + _incVerticalPos(scout); + } + // Set the iterator to the last cell of the track. + _goNextCell(dpScoreMatrixNavigator, TColumnDescriptor(), LastCell()); + _goNextCell(dpTraceMatrixNavigator, TColumnDescriptor(), LastCell()); + // Compute the last cell. + _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), + previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), + previousCellVertical(dpScoreMatrixNavigator), tmpSeqH, + sequenceEntryForScore(scoringScheme, container(iter), position(iter)), scoringScheme, + TColumnDescriptor(), LastCell(), TDPProfile()); +} + +// ---------------------------------------------------------------------------- +// Function _computeUnbandedAlignmentHelperTerminate() +// ---------------------------------------------------------------------------- + +template +inline bool //TODO(C++11) constexpr +_computeAlignmentHelperCheckTerminate(DPScout_ const & /**/) +{ + return false; +} + +template +inline bool +_computeAlignmentHelperCheckTerminate(DPScout_ > const & s) +{ + return _terminationCriteriumIsMet(s); +} + +// ---------------------------------------------------------------------------- +// Function _computeUnbandedAlignment() +// ---------------------------------------------------------------------------- + +// Computes the standard DP-algorithm. +template +inline void +_computeUnbandedAlignment(TDPScout & scout, + TDPScoreMatrixNavigator & dpScoreMatrixNavigator, + TDPTraceMatrixNavigator & dpTraceMatrixNavigator, + TSequenceH const & seqH, + TSequenceV const & seqV, + TScoringScheme const & scoringScheme, + DPProfile_ const & dpProfile) +{ + typedef typename Iterator::Type TConstSeqHIterator; + typedef typename Iterator::Type TConstSeqVIterator; + + // Initilaize SIMD version with multiple end points. + _preInitScoutHorizontal(scout); + + // ============================================================================ + // PREPROCESSING + // ============================================================================ + + TConstSeqVIterator seqVBegin = begin(seqV, Rooted()); + TConstSeqVIterator seqVEnd = end(seqV, Rooted()); + + SEQAN_ASSERT_GT(length(seqH), 0u); + SEQAN_ASSERT_GT(length(seqV), 0u); + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, 0), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + + // ============================================================================ + // MAIN DP + // ============================================================================ + + TConstSeqHIterator seqHIter = begin(seqH, Rooted()); + TConstSeqHIterator seqHIterEnd = end(seqH, Rooted()) - 1; + for (; seqHIter != seqHIterEnd; ++seqHIter) + { + // We might only select it if SIMD version is available. + if (SEQAN_UNLIKELY(_reachedHorizontalEndPoint(scout, seqHIter))) + { + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + _nextHorizontalEndPos(scout); + } + else + { + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + } + if (_computeAlignmentHelperCheckTerminate(scout)) + { + return; + } + _incHorizontalPos(scout); + } + + // ============================================================================ + // POSTPROCESSING + // ============================================================================ + + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + + // If we compute only the single option. we need to check if there are other possibilities at the end. + // Traceback only from Diagonal, but could also come from vertical or horizontal. + +// for (unsigned i = 0; i < length(recMatrix); ++i) +// { +// std::cout << recMatrix[i]._score << "\t"; +// } +// std::cout << std::endl; +} + +// ---------------------------------------------------------------------------- +// Function _computeBandedAlignment() +// ---------------------------------------------------------------------------- + +// Computes the banded DP-algorithm. +template +inline void +_computeBandedAlignment(TDPScout & scout, + TDPScoreMatrixNavigator & dpScoreMatrixNavigator, + TDPTraceMatrixNavigator & dpTraceMatrixNavigator, + TSequenceH const & seqH, + TSequenceV const & seqV, + TScoringScheme const & scoringScheme, + TBand const & band, + DPProfile_ const & dpProfile) +{ + typedef DPProfile_ TDPProfile; + typedef typename MakeSigned::Type>::Type TSignedSizeSeqH; + typedef typename MakeSigned::Type>::Type TSignedSizeSeqV; + typedef typename Iterator::Type TConstSeqHIterator; + typedef typename Iterator::Type TConstSeqVIterator; + + + // Now we have the problem of not knowing when we are in the last cell. + + // ============================================================================ + // PREPROCESSING + // ============================================================================ + TSignedSizeSeqH seqHlength = static_cast(length(seqH)); + TSignedSizeSeqH seqVlength = static_cast(length(seqV)); + + TConstSeqVIterator seqVBegin = begin(seqV, Rooted()) - _min(0, 1 + upperDiagonal(band)); + TConstSeqVIterator seqVEnd = begin(seqV, Rooted()) - _min(0, _max(-seqVlength, lowerDiagonal(band))); + + // We have to distinguish two band sizes. Some which spans the whole matrix in between and thus who not. + // This can be distinguished, if UpperDiagonal > length(seqV) + LowerDiagonal + + // We start at least at the first position of the horizontal sequence or wherever the lower diagonal begins first. + TConstSeqHIterator seqHIterBegin = begin(seqH, Rooted()) + _max(0, _min(seqHlength - 1, lowerDiagonal(band))); + + // The horizontal initial phase ends after the upper diagonal but at most after the horizontal sequence, or there is no horizontal initialization phase. + TConstSeqHIterator seqHIterEndColumnTop = begin(seqH, Rooted()) + _min(seqHlength - 1, _max(0, upperDiagonal(band))); + + // The middle band phase ends after the lower diagonal crosses the bottom of the alignment matrix or after the horizontal sequence if it is smaller. + TConstSeqHIterator seqHIterEndColumnMiddle = begin(seqH, Rooted()) + _min(seqHlength - 1, _max(0, seqVlength + lowerDiagonal(band))); + // Swap the two iterators if we are in a band that spans over the full column. + if (upperDiagonal(band) > seqVlength + lowerDiagonal(band)) + std::swap(seqHIterEndColumnTop, seqHIterEndColumnMiddle); + + // The bottom band phase ends after the upper diagonal of the band crosses the bottom of the matrix or after the horizontal sequence if it is smaller. + TConstSeqHIterator seqHIterEndColumnBottom = begin(seqH, Rooted()) + _max(0, _min(seqHlength, + upperDiagonal(band) + seqVlength) - 1); + + // The Initial column can be PartialColumnTop which is given if the upper diagonal is >= 0, + // otherwise it only can be PartialColumnMiddle or PartialColumnBottom depending where the lower diagonal is. + + // Check for single initialization cells in InitialColumn and FinalColumn. + if (seqHIterBegin == end(seqH, Rooted()) - 1) + { + // Set the iterator to the begin of the track. + _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + // Only one cell + _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), + previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), + previousCellVertical(dpScoreMatrixNavigator), + sequenceEntryForScore(scoringScheme, seqH, position(seqHIterBegin)), + sequenceEntryForScore(scoringScheme, seqV, 0), scoringScheme, + MetaColumnDescriptor(), FirstCell(), TDPProfile()); + // we might need to additionally track this point. + if (TrackingEnabled_ >, FirstCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator, True(), False()); + return; + } + if (seqHIterEndColumnBottom == begin(seqH, Rooted())) + { + // Set the iterator to the begin of the track. + _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + // Only one cell + _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), + previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), + previousCellVertical(dpScoreMatrixNavigator), + sequenceEntryForScore(scoringScheme, seqH, 0), + sequenceEntryForScore(scoringScheme, seqV, position(seqVBegin)), scoringScheme, + MetaColumnDescriptor(), FirstCell(), TDPProfile()); + // We might need to additionally track this point. + if (TrackingEnabled_ >, LastCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator, False(), True()); + return; + } + + if (upperDiagonal(band) < 0) + { + ++seqVBegin; + if (lowerDiagonal(band) > -seqVlength) + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, 0), + sequenceEntryForScore(scoringScheme, seqV, position(seqVBegin) - 1), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + else + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, 0), + sequenceEntryForScore(scoringScheme, seqV, position(seqVBegin) - 1), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + } + else if (lowerDiagonal(band) >= 0) + { + // Set the iterator to the begin of the track. + _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + // Should we not just compute the cell? + _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), + previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), + previousCellVertical(dpScoreMatrixNavigator), + sequenceEntryForScore(scoringScheme, seqH, position(seqHIterBegin)), + sequenceEntryForScore(scoringScheme, seqV, 0), + scoringScheme, + MetaColumnDescriptor(), FirstCell(), TDPProfile()); + // we might need to additionally track this point. + if (TrackingEnabled_ >, FirstCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator, False(), False()); + } + else // Upper diagonal >= 0 and lower Diagonal < 0 + if (lowerDiagonal(band) <= -seqVlength) // The band is bounded by the top and bottom of the matrix. + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, 0), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + else // The band is bounded by the top but not the bottom of the matrix. + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, 0), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + + if (_computeAlignmentHelperCheckTerminate(scout)) + { + return; + } + + // ============================================================================ + // MAIN DP + // ============================================================================ + + TConstSeqHIterator seqHIter = seqHIterBegin; + // Compute the first part of the band, where the band is bounded by the top but not by the bottom of the matrix. + for (; seqHIter != seqHIterEndColumnTop; ++seqHIter) + { + ++seqVEnd; + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + if (_computeAlignmentHelperCheckTerminate(scout)) + { + return; + } + } + + // TODO(rmaerker): Check if putting the if-statement before the actual algorithm can speedup the code. + // Check whether the band spans over the full column or not at some point. + if (upperDiagonal(band) > seqVlength + lowerDiagonal(band)) + { + // Compute the second part of the band, where the band is bounded by the top and the bottom of the matrix. + // We might want to track the current cell here, since this is the first cell that crosses the bottom but is + // not part of the FullColumn tracks. + if (TrackingEnabled_ >, LastCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator, False(), True()); + for (; seqHIter != seqHIterEndColumnMiddle; ++seqHIter) + { + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + + if (_computeAlignmentHelperCheckTerminate(scout)) + { + return; + } + } + } + else // Compute the second part of the band, where the band is not bounded by the top and bottom of the matrix + { + for (; seqHIter != seqHIterEndColumnMiddle; ++seqHIter) + { + ++seqVBegin; + ++seqVEnd; + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, position(seqVBegin) - 1), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + if (_computeAlignmentHelperCheckTerminate(scout)) + { + return; + } + } // We might want to track the current cell here, since this is the first cell that crosses the bottom. + if (TrackingEnabled_ >, LastCell>::VALUE) + { + if (lowerDiagonal(band) + seqVlength < seqHlength) + { + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator, False(), True()); + } + } + + } + // Compute the third part of the band, where the band, is bounded by the bottom but not by the top of the matrix. + for (; seqHIter != seqHIterEndColumnBottom; ++seqHIter) + { + ++seqVBegin; + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, position(seqVBegin) - 1), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + if (_computeAlignmentHelperCheckTerminate(scout)) + { + return; + } + } + + // ============================================================================ + // POSTPROCESSING + // ============================================================================ + + // Check where the last track of the column is located. + if (seqHIter - begin(seqH, Rooted()) < seqHlength - 1) // Case 1: The band ends before the final column is reached. + { + // Set the iterator to the begin of the track. + _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + + _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), + previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), + previousCellVertical(dpScoreMatrixNavigator), + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, position(seqVBegin)), + scoringScheme, + MetaColumnDescriptor(), FirstCell(), TDPProfile()); + // We might need to additionally track this point. + if (TrackingEnabled_ >, LastCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator, False(), True()); + } + else if (seqHIter == end(seqH, Rooted()) - 1) // Case 2: The band ends somewhere in the final column of the matrix. + { + // Case2a: The band ends in the last cell of the final column. + if (upperDiagonal(band) == seqHlength - seqVlength) + { + // Set the iterator to the begin of the track. + _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + + _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), + previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), + previousCellVertical(dpScoreMatrixNavigator), + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, position(seqVBegin)), + scoringScheme, + MetaColumnDescriptor(), FirstCell(), TDPProfile()); + // we might need to additionally track this point. + if (TrackingEnabled_ >, LastCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator, True(), True()); + } + else // Case2b: At least two cells intersect between the band and the matrix in the final column of the matrix. + { + if (upperDiagonal(band) >= seqHlength) // The band is bounded by the top of the matrix only or by the top and the bottom. + { + if (lowerDiagonal(band) + seqVlength > seqHlength) // The band is bounded by the top of the matrix + { + ++seqVEnd; + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + } + else // The band is bounded by the top and the bottom of the matrix. + { + if (lowerDiagonal(band) + seqVlength + 1 > seqHlength) // We have to go into the last cell. + { + ++seqVEnd; + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + if (TrackingEnabled_ >, LastCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator, True(), True()); + } + else + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, 0), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + } + + } + else // The band is bounded by bottom of matrix or completely unbounded. + { + ++seqVBegin; + if (lowerDiagonal(band) + seqVlength <= seqHlength) // The band is bounded by the bottom of the matrix. + { + if (lowerDiagonal(band) + seqVlength == seqHlength) // We have to go into the last cell. + { + ++seqVEnd; + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, position(seqVBegin) - 1), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + if (TrackingEnabled_ >, LastCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator, True(), True()); + } + else + { + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, position(seqVBegin) - 1), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + } + } + else // The band is unbounded by the matrix. + { + ++seqVEnd; + _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, + sequenceEntryForScore(scoringScheme, seqH, position(seqHIter)), + sequenceEntryForScore(scoringScheme, seqV, position(seqVBegin) - 1), + seqVBegin, seqVEnd, scoringScheme, + MetaColumnDescriptor(), dpProfile); + } + + } + } + } +} + +// TODO(rmaerker): This is denbug code only. +//template +//inline void +//_debugBandedAlignment(TDPScout & scout, +// TDPScoreMatrixNavigator & dpScoreMatrixNavigator, +// TDPTraceMatrixNavigator & dpTraceMatrixNavigator, +// TSequenceH const & seqH, +// TSequenceV const & seqV, +// TScoringScheme const & scoringScheme, +// TBand const & band, +// DPProfile_ const & dpProfile) +//{ +// typedef DPProfile_ TDPProfile; +// typedef typename Value::Type TSeqHValue; +// typedef typename Value::Type TSeqVValue; +// typedef typename Iterator::Type TConstSeqHIterator; +// typedef typename Iterator::Type TConstSeqVIterator; +// +// +// String testMatrix; +// resize(testMatrix, (length(seqH) + 1) * (length(seqV)+1)); +// // Now we have the problem of not knowing when we are in the last cell. +// +// // INITIALIZATION +// TConstSeqVIterator seqVBegin = begin(seqV, Standard()) - _min(0, 1+upperDiagonal(band)); +// TConstSeqVIterator seqVEnd = begin(seqV, Standard()) - _min(0, _max(-static_cast(length(seqV)), lowerDiagonal(band))); +// +//// std::cout << "Begin Pos: " << seqVBegin - begin(seqV) << "\n"; +//// std::cout << "End Pos: " << seqVEnd - begin(seqV) << "\n"; +// +// // We have to distinguish two band sizes. Some which spans the whole matrix in between and thus who not. +// // This can be distinguished, if UpperDiagonal > length(seqV) + LowerDiagonal +// +// // We start at the least at the first sequence or wherever the lower diagonal begins first. +// TConstSeqHIterator seqHIterBegin = begin(seqH, Standard()) + _max(0, _min(static_cast(length(seqH) - 1), lowerDiagonal(band))); +// // TODO(rmaerker): Cehck if this assertion is correct. +//// SEQAN_ASSERT_NEQ(seqHIterBegin, end(seqH, Standard())); // The iterator never points to the end of the horizontal sequence. +// +// // The horizontal initial phase ends after the upper diagonal but at most after the horizontal sequence, or there is no horizontal initialization phase. +// TConstSeqHIterator seqHIterEndColumnTop = begin(seqH, Standard()) + _min(static_cast(length(seqH))-1, _max(0, upperDiagonal(band))); +// +// // The middle band phase ends after the lower diagonal crosses the bottom of the alignment matrix or after the horizontal sequence if it is smaller. +// TConstSeqHIterator seqHIterEndColumnMiddle = begin(seqH, Standard()) + _min(static_cast(length(seqH))-1, _max(0,static_cast(length(seqV)) + lowerDiagonal(band))); +// // Swap the two iterators if we are in a band that spans over the full column. +// if (upperDiagonal(band) > static_cast(length(seqV)) + lowerDiagonal(band)) +// std::swap(seqHIterEndColumnTop, seqHIterEndColumnMiddle); +// +// // The bottom band phase ends after the upper diagonal of the band crosses the bottom of the matrix or after the horizontal sequence if it is smaller. +// TConstSeqHIterator seqHIterEndColumnBottom = begin(seqH, Standard()) + _max(0, _min(static_cast(length(seqH)), +// upperDiagonal(band) + static_cast(length(seqV))) -1); +// +//// std::cout << "seqHIterBegin Pos H: " << seqHIterBegin - begin(seqH) << "\n"; +//// std::cout << "seqHIterEndColumnTop Pos H: " << seqHIterEndColumnTop - begin(seqH) << "\n"; +//// std::cout << "seqHIterEndColumnMiddle Pos H: " << seqHIterEndColumnMiddle - begin(seqH) << "\n"; +//// std::cout << "seqHIterEndColumnBottom Pos H: " << seqHIterEndColumnBottom - begin(seqH) << "\n"; +//// +//// std::cout << "_activeColIterator Pos: " << dpScoreMatrixNavigator._activeColIterator - begin(*dpScoreMatrixNavigator._ptrDataContainer) << "\n"; +//// std::cout << "_prevColIterator Pos: " << dpScoreMatrixNavigator._prevColIterator - begin(*dpScoreMatrixNavigator._ptrDataContainer) << "\n"; +// +// // The Initial column can be PartialColumnTop which is given if the upper diagonal is >= 0, +// // otherwise it only can be PartialColumnMiddle or PartialColumnBottom depending where the lower diagonal is. +// +// // Have to check for single initialization cells in InitialColumn and FinalColumn. +// if (seqHIterBegin == end(seqH)-1) +// { +// // Set the iterator to the begin of the track. +// _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); +// _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); +// // Only one cell +// _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), +// previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), +// previousCellVertical(dpScoreMatrixNavigator), value(seqHIterBegin), TSeqVValue(), scoringScheme, +// MetaColumnDescriptor(), FirstCell(), TDPProfile()); +//// std::cout << _scoreOfCell(value(dpScoreMatrixNavigator)) << "\n"; +// std::stringstream stream; +// stream << _scoreOfCell(value(dpScoreMatrixNavigator)); +// testMatrix[length(seqH) * length(seqV)] = stream.str(); +// // we might need to additionally track this point. +// if (TrackingEnabled_ >, FirstCell>::VALUE) +// _scoutBestScore(scout, _scoreOfCell(value(dpScoreMatrixNavigator)), dpTraceMatrixNavigator); +// return; +// } +// if (seqHIterEndColumnBottom == begin(seqH)) +// { +// // Set the iterator to the begin of the track. +// _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); +// _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); +// // Only one cell +// _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), +// previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), +// previousCellVertical(dpScoreMatrixNavigator), TSeqHValue(), value(seqVBegin), scoringScheme, +// MetaColumnDescriptor(), FirstCell(), TDPProfile()); +//// std::cout << _scoreOfCell(value(dpScoreMatrixNavigator)) << "\n"; +// std::stringstream stream; +// stream << _scoreOfCell(value(dpScoreMatrixNavigator)); +// testMatrix[length(seqH) * length(seqV)] = stream.str(); +// // We might need to additionally track this point. +// if (TrackingEnabled_ >, LastCell>::VALUE) +// _scoutBestScore(scout, _scoreOfCell(value(dpScoreMatrixNavigator)), dpTraceMatrixNavigator); +// return; +// } +// +// if (upperDiagonal(band) < 0) +// { +// ++seqVBegin; +// if (lowerDiagonal(band) > -static_cast(length(seqV))) +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// TSeqHValue(), value(seqVBegin-1), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, 0, seqVBegin - begin(seqV) + 1, testMatrix); +// else +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// TSeqHValue(), value(seqVBegin-1), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, 0, seqVBegin - begin(seqV) + 1, testMatrix); +// } +// else if (lowerDiagonal(band) >= 0) +// { +// // Set the iterator to the begin of the track. +// _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); +// _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); +// // Should we not just compute the cell? +// _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), +// previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), +// previousCellVertical(dpScoreMatrixNavigator), value(seqHIterBegin), TSeqVValue(), scoringScheme, +// MetaColumnDescriptor(), FirstCell(), TDPProfile()); +// // we might need to additionally track this point. +//// std::cout << _scoreOfCell(value(dpScoreMatrixNavigator)) << "\n"; +// int col = lowerDiagonal(band); +// std::stringstream stream; +// stream << _scoreOfCell(value(dpScoreMatrixNavigator)); +// testMatrix[col * (length(seqV) + 1)] = stream.str(); +// if (TrackingEnabled_ >, FirstCell>::VALUE) +// _scoutBestScore(scout, _scoreOfCell(value(dpScoreMatrixNavigator)), dpTraceMatrixNavigator); +// } +// else // Upper diagonal >= 0 and lower Diagonal < 0 +// if (lowerDiagonal(band) <= -static_cast(length(seqV))) // The band is bounded by the top and bottom of the matrix. +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// TSeqHValue(), TSeqVValue(), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, 0, 0, testMatrix); +// else // The band is bounded by the top but not the bottom of the matrix. +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// TSeqHValue(), TSeqVValue(), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, 0,0, testMatrix); +// +// +// // RECURSION +// TConstSeqHIterator seqHIter = seqHIterBegin; +// // Compute the first part of the band, where the band is bounded by the top but not by the bottom of the matrix. +// for (;seqHIter != seqHIterEndColumnTop; ++seqHIter) +// { +//// std::cout << value(seqHIter) << ":\t"; +// ++seqVEnd; +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// value(seqHIter), TSeqVValue(), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, ((seqHIter - begin(seqH)) + 1)*(length(seqV) +1), 0, testMatrix); +// } +// +// // Check whether the band spans over the full column or not at some point. +// if (upperDiagonal(band) > static_cast(length(seqV)) + lowerDiagonal(band)) +// { +// // Compute the second part of the band, where the band is bounded by the top and the bottom of the matrix. +// // We might want to track the current cell here, since this is the first cell that crosses the bottom. +// // TODO(rmaerker): We have to check if the initial column/ row can be tracked!!! +// if (TrackingEnabled_ >, LastCell>::VALUE) +// _scoutBestScore(scout, _scoreOfCell(value(dpScoreMatrixNavigator)), dpTraceMatrixNavigator); +// for (;seqHIter != seqHIterEndColumnMiddle; ++seqHIter) +// { +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// value(seqHIter), TSeqVValue(), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, (seqHIter - begin(seqH) + 1) * (length(seqV) + 1), 0, testMatrix); +// } +// } +// else // Compute the second part of the band, where the band is not bounded by the top and bottom of the matrix +// { +// for (;seqHIter != seqHIterEndColumnMiddle; ++seqHIter) +// { +// ++seqVBegin; +// ++seqVEnd; +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// value(seqHIter), value(seqVBegin-1), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, (seqHIter - begin(seqH) +1) * (length(seqV)+1), seqVBegin - begin(seqV), testMatrix); +// } // We might want to track the current cell here, since this is the first cell that crosses the bottom. +// if (TrackingEnabled_ >, LastCell>::VALUE) +// { +// // TODO(rmaerker): This is only a hot fix. +// if (lowerDiagonal(band) + length(seqV) < length(seqH)) +// _scoutBestScore(scout, _scoreOfCell(value(dpScoreMatrixNavigator)), dpTraceMatrixNavigator); +// } +// } +// // Compute the third part of the band, where the band, is bounded by the bottom but not by the top of the matrix. +// for (;seqHIter != seqHIterEndColumnBottom; ++seqHIter) +// { +// ++seqVBegin; +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// value(seqHIter), value(seqVBegin-1), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, (seqHIter - begin(seqH) + 1) * (length(seqV) + 1), seqVBegin - begin(seqV), testMatrix); +// } +// +// // Where ends the last cell? +// if(seqHIter - begin(seqH) < static_cast(length(seqH))-1) // Case 1: The band ends before the final column is reached. +// { +// // Set the iterator to the begin of the track. +// _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); +// _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); +// +// _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), +// previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), +// previousCellVertical(dpScoreMatrixNavigator), value(seqHIter), value(seqVBegin), scoringScheme, +// MetaColumnDescriptor(), FirstCell(), TDPProfile()); +//// std::cout << _scoreOfCell(value(dpScoreMatrixNavigator)) << "\n"; +// std::stringstream stream; +// stream << _scoreOfCell(value(dpScoreMatrixNavigator)); +// testMatrix[(seqHIter - begin(seqH) + 1) * (length(seqV) + 1) + length(seqV)] = stream.str(); +// // We might need to additionally track this point. +// if (TrackingEnabled_ >, LastCell>::VALUE) +// _scoutBestScore(scout, _scoreOfCell(value(dpScoreMatrixNavigator)), dpTraceMatrixNavigator); +// } +// else if(seqHIter == end(seqH)-1) // Case 2: The band ends somewhere in the final column of the matrix. +// { +// if (upperDiagonal(band) == static_cast(length(seqH))-static_cast(length(seqV))) // Case2a: The band ends in the last cell of the final column. // He should be here.... +// { +// // Set the iterator to the begin of the track. +// _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); +// _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); +// +// _computeCell(scout, dpTraceMatrixNavigator, value(dpScoreMatrixNavigator), +// previousCellDiagonal(dpScoreMatrixNavigator), previousCellHorizontal(dpScoreMatrixNavigator), +// previousCellVertical(dpScoreMatrixNavigator), value(seqHIter), value(seqVBegin), scoringScheme, +// MetaColumnDescriptor(), FirstCell(), TDPProfile()); +//// std::cout << _scoreOfCell(value(dpScoreMatrixNavigator)) << "\n"; +// std::stringstream stream; +// stream << _scoreOfCell(value(dpScoreMatrixNavigator)); +// testMatrix[(length(seqH) * (length(seqV) + 1)) + length(seqV)] = stream.str(); +// // we might need to additionally track this point. +// if (TrackingEnabled_ >, LastCell>::VALUE) +// _scoutBestScore(scout, _scoreOfCell(value(dpScoreMatrixNavigator)), dpTraceMatrixNavigator); +// } +// else // Case2b: At least two cells intersect between the band and the matrix in the final column of the matrix. +// { +// if (upperDiagonal(band) >= static_cast(length(seqH))) // The band is bounded by the top of the matrix only or by the top and the bottom. +// { +// if (lowerDiagonal(band) + static_cast(length(seqV)) > static_cast(length(seqH))) // The band is bounded by the top of the matrix +// { +// ++seqVEnd; +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// value(seqHIter), TSeqVValue(), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, length(seqH) * (length(seqV) + 1), 0, testMatrix); +// } +// else // The band is bounded by the top and the bottom of the matrix. +// { +// if (lowerDiagonal(band) + static_cast(length(seqV)) + 1 > static_cast(length(seqH)) ) +// { +// ++seqVEnd; +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// value(seqHIter), TSeqVValue(), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, length(seqH) * (length(seqV) + 1), 0, testMatrix); +// if (TrackingEnabled_ >, LastCell>::VALUE) +// _scoutBestScore(scout, _scoreOfCell(value(dpScoreMatrixNavigator)), dpTraceMatrixNavigator); +// } +// else +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// value(seqHIter), TSeqVValue(), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, length(seqH) * (length(seqV) +1), 0, testMatrix); +// +// } +// +// } +// else // The band is bounded by bottom of matrix or completely unbounded. +// { +// ++seqVBegin; +// if (lowerDiagonal(band) + length(seqV) <= length(seqH)) // The band is bounded by the bottom of the matrix. +// { +// if (lowerDiagonal(band) + length(seqV) == length(seqH)) +// { +// ++seqVEnd; +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// value(seqHIter), value(seqVBegin-1), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, length(seqH) * (length(seqV)+1), seqVBegin - begin(seqV), testMatrix); +// if (TrackingEnabled_ >, LastCell>::VALUE) +// _scoutBestScore(scout, _scoreOfCell(value(dpScoreMatrixNavigator)), dpTraceMatrixNavigator); +// } +// else +// { +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// value(seqHIter), value(seqVBegin-1), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, length(seqH) * (length(seqV) + 1), seqVBegin - begin(seqV), testMatrix); +// } +// } +// else // The band is unbounded by the matrix. +// { +// ++seqVEnd; +// _computeTrack(scout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, +// value(seqHIter), value(seqVBegin-1), seqVBegin, seqVEnd, scoringScheme, +// MetaColumnDescriptor(), dpProfile, length(seqH) * (length(seqV)+1), seqVBegin - begin(seqV), testMatrix); +// } +// +// } +// } +// } +// +// for (unsigned i = 0; i <= length(seqV); ++i) +// { +// for (unsigned j = 0; j <= length(seqH); ++j) +// { +// unsigned pos = j * (length(seqV) + 1) + i; +// //if (!testMatrix[pos].empty()) +// std::cout << testMatrix[pos] << "\t" << std::flush; +// } +// std::cout << std::endl; +// } +// +//} + +// ---------------------------------------------------------------------------- +// Function _computeHammingDistance() +// ---------------------------------------------------------------------------- + +// Computes the Hamming-Distance if the band-size is 1. +template +inline void +_computeHammingDistance(TDPScout & scout, + TDPScoreMatrixNavigator & dpScoreMatrixNavigator, + TDPTraceMatrixNavigator & dpTraceMatrixNavigator, + TSequenceH const & seqH, + TSequenceV const & seqV, + TScoringScheme const & scoringScheme, + TBand const & band, + DPProfile_ const &) +{ + typedef typename MakeSigned::Type>::Type TSignedSizeSeqH; + typedef typename MakeSigned::Type>::Type TSignedSizeSeqV; + typedef typename Iterator::Type TConstSeqHIterator; + typedef typename Iterator::Type TConstSeqVIterator; + typedef typename Value::Type TDPCell; + typedef DPProfile_ TDPProfile; + + // ============================================================================ + // PREPROCESSING + // ============================================================================ + + TSignedSizeSeqH seqHlength = static_cast(length(seqH)); + TSignedSizeSeqH seqVlength = static_cast(length(seqV)); + + TConstSeqHIterator itH = begin(seqH, Rooted()) + _max(0, _min(seqHlength - 1, upperDiagonal(band))); + TConstSeqHIterator itHEnd = begin(seqH, Rooted()) + _min(seqHlength - 1, upperDiagonal(band) + seqVlength); + + TConstSeqVIterator itV = begin(seqV, Rooted()) + _max(0, _min(seqVlength - 1, -lowerDiagonal(band))); + TConstSeqVIterator itVEnd = begin(seqV, Rooted()) + _min(seqVlength - 1, lowerDiagonal(band) + seqHlength); + + assignValue(dpTraceMatrixNavigator, + _computeScore(value(dpScoreMatrixNavigator), TDPCell(), TDPCell(), TDPCell(), + sequenceEntryForScore(scoringScheme, seqH, position(itH)), + sequenceEntryForScore(scoringScheme, seqV, position(itV)), + scoringScheme, RecursionDirectionZero(), TDPProfile())); + + if (upperDiagonal(band) < 0) + { + if (upperDiagonal(band) == -seqVlength) + { + if (TrackingEnabled_ >, LastCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator); + return; + } + else + { + if (TrackingEnabled_ >, InnerCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator); + } + } + else if (lowerDiagonal(band) > 0) + { + if (lowerDiagonal(band) == seqHlength) + { + if (TrackingEnabled_ >, FirstCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator); + return; + } + else + { + if (TrackingEnabled_ >, FirstCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator); + } + } + else + { + if (TrackingEnabled_ >, FirstCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator); + } + + TDPCell prevDiagonal = value(dpScoreMatrixNavigator); + + // ============================================================================ + // MAIN DP + // ============================================================================ + + while (itH != itHEnd && itV != itVEnd) + { + _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + assignValue(dpTraceMatrixNavigator, + _computeScore(value(dpScoreMatrixNavigator), prevDiagonal, TDPCell(), TDPCell(), + sequenceEntryForScore(scoringScheme, seqH, position(itH)), + sequenceEntryForScore(scoringScheme, seqV, position(itV)), + scoringScheme, RecursionDirectionDiagonal(), TDPProfile())); + if (TrackingEnabled_ >, InnerCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator); + prevDiagonal = value(dpScoreMatrixNavigator); + ++itH; + ++itV; + } + + // ============================================================================ + // POSTPROCESSING + // ============================================================================ + + _goNextCell(dpScoreMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + _goNextCell(dpTraceMatrixNavigator, MetaColumnDescriptor(), FirstCell()); + + assignValue(dpTraceMatrixNavigator, + _computeScore(value(dpScoreMatrixNavigator), prevDiagonal, TDPCell(), TDPCell(), + sequenceEntryForScore(scoringScheme, seqH, position(itH)), + sequenceEntryForScore(scoringScheme, seqV, position(itV)), + scoringScheme, RecursionDirectionDiagonal(), TDPProfile())); + + if (itH == itHEnd) + { + if (itV == itVEnd) // Is in the last cell of final column + { + if (TrackingEnabled_ >, LastCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator); + } + if (TrackingEnabled_ >, LastCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator); + } + else + { + if (TrackingEnabled_ >, InnerCell>::VALUE) + _scoutBestScore(scout, value(dpScoreMatrixNavigator), dpTraceMatrixNavigator); + } +} + +// ---------------------------------------------------------------------------- +// Function _printTracebackMatrix() +// ---------------------------------------------------------------------------- + +template +void _printTracebackMatrix(TTraceMatrix & dpTraceMatrix) +{ + typedef typename Size::Type TSize; + TSize dimH = length(dpTraceMatrix, +DPMatrixDimension_::HORIZONTAL); + TSize dimV = length(dpTraceMatrix, +DPMatrixDimension_::VERTICAL); + + for (unsigned row = 0; row < dimV; ++row) + { + for (unsigned column = 0; column < dimH; ++column) + std::cout << _translateTraceValue(value(dpTraceMatrix, row + column * dimV)) << "\t"; + std::cout << std::endl; + } + std::cout << std::endl; +} + +template +void _printTracebackMatrix(TTraceMatrix & dpTraceMatrix, TPosition const simdLane) +{ + typedef typename Size::Type TSize; + TSize dimH = length(dpTraceMatrix, +DPMatrixDimension_::HORIZONTAL); + TSize dimV = length(dpTraceMatrix, +DPMatrixDimension_::VERTICAL); + + for (unsigned row = 0; row < dimV; ++row) + { + for (unsigned column = 0; column < dimH; ++column) + std::cout << _translateTraceValue(value(dpTraceMatrix, row + column * dimV)[simdLane]) << "\t"; + std::cout << std::endl; + } + std::cout << std::endl; +} + +// ---------------------------------------------------------------------------- +// Function _correctTraceValue() +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, void) +_correctTraceValue(TTraceNavigator &, + DPScout_, TDPScoutSpec> const &) +{ + // Nothing to do. +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +_correctTraceValue(TTraceNavigator &, + DPScout_, TDPScoutSpec> const &) +{ + // Nothing to do. +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, void) +_correctTraceValue(TTraceNavigator & traceNavigator, + DPScout_, TDPScoutSpec> const & dpScout) +{ + _setToPosition(traceNavigator, maxHostPosition(dpScout)); + + if (_verticalScoreOfCell(dpScout._maxScore) == _scoreOfCell(dpScout._maxScore)) + { + value(traceNavigator) &= ~TraceBitMap_::DIAGONAL; + value(traceNavigator) |= TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; + } + else if (_horizontalScoreOfCell(dpScout._maxScore) == _scoreOfCell(dpScout._maxScore)) + { + value(traceNavigator) &= ~TraceBitMap_::DIAGONAL; + value(traceNavigator) |= TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; + } +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +_correctTraceValue(TTraceNavigator & traceNavigator, + DPScout_, TDPScoutSpec> const & dpScout) +{ + _setToPosition(traceNavigator, maxHostPosition(dpScout)); + TScoreValue cmpV = cmpEq(_verticalScoreOfCell(dpScout._maxScore), _scoreOfCell(dpScout._maxScore)); + TScoreValue cmpH = cmpEq(_horizontalScoreOfCell(dpScout._maxScore), _scoreOfCell(dpScout._maxScore)); + value(traceNavigator) = blend(value(traceNavigator), + value(traceNavigator) & ~TraceBitMap_::DIAGONAL, + cmpV | cmpH); + value(traceNavigator) = blend(value(traceNavigator), + value(traceNavigator) | TraceBitMap_::MAX_FROM_VERTICAL_MATRIX, + cmpV); + value(traceNavigator) = blend(value(traceNavigator), + value(traceNavigator) | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + cmpH); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, void) +_correctTraceValue(TTraceNavigator & traceNavigator, + DPScout_, TDPScoutSpec> const & dpScout) +{ + _setToPosition(traceNavigator, maxHostPosition(dpScout)); + if (isGapExtension(dpScout._maxScore, DynamicGapExtensionVertical())) + { + value(traceNavigator) &= ~TraceBitMap_::DIAGONAL; + value(traceNavigator) |= TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; + } + else if (isGapExtension(dpScout._maxScore, DynamicGapExtensionHorizontal())) + { + value(traceNavigator) &= ~TraceBitMap_::DIAGONAL; + value(traceNavigator) |= TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; + } +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +_correctTraceValue(TTraceNavigator & traceNavigator, + DPScout_, TDPScoutSpec> const & dpScout) +{ + _setToPosition(traceNavigator, maxHostPosition(dpScout)); + TScoreValue cmpV = isGapExtension(dpScout._maxScore, DynamicGapExtensionVertical()); + TScoreValue cmpH = isGapExtension(dpScout._maxScore, DynamicGapExtensionHorizontal()); + value(traceNavigator) = blend(value(traceNavigator), + value(traceNavigator) & ~TraceBitMap_::DIAGONAL, + cmpV | cmpH); + value(traceNavigator) = blend(value(traceNavigator), + value(traceNavigator) | TraceBitMap_::MAX_FROM_VERTICAL_MATRIX, + cmpV); + value(traceNavigator) = blend(value(traceNavigator), + value(traceNavigator) | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + cmpH); +} + +// ---------------------------------------------------------------------------- +// Function _finishAlignment() +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not >, TScoreValue) +_finishAlignment(TTraceTarget & /*traceSegments*/, + TTraceMatNavigator & /*dpTraceMatrixNavigator*/, + DPScout_, TDPScoutSpec> & dpScout, + TSeqH const & /*seqH*/, + TSeqV const & /*seqV*/, + DPBandConfig const & /*band*/, + DPProfile_ const & /*dpProfile*/) +{ + return maxScore(dpScout); +} + +template +inline SEQAN_FUNC_ENABLE_IF(And >, IsTracebackEnabled_ >, TScoreValue) +_finishAlignment(TTraceTarget & traceSegments, + TTraceMatNavigator & dpTraceMatrixNavigator, + DPScout_, TDPScoutSpec> & scout, + TSeqH const & seqH, + TSeqV const & seqV, + DPBandConfig const & band, + DPProfile_ const & dpProfile) +{ + typedef typename Size::Type TSize; + + for(TSize i = 0; i < length(traceSegments); ++i) + { + _setSimdLane(dpTraceMatrixNavigator, i); + _setSimdLane(scout, i); + + if (IsSingleTrace_::VALUE) + { + _correctTraceValue(dpTraceMatrixNavigator, scout); + } + _computeTraceback(traceSegments[i], dpTraceMatrixNavigator, scout, _hostLengthH(scout, seqH), + _hostLengthV(scout, seqV), band, dpProfile); + } + return maxScore(scout); +} + +template +inline SEQAN_FUNC_ENABLE_IF(And > >, IsTracebackEnabled_ >, TScoreValue) +_finishAlignment(TTraceTarget & traceSegments, + TTraceMatNavigator & dpTraceMatrixNavigator, + DPScout_, TDPScoutSpec> & dpScout, + TSeqH const & seqH, + TSeqV const & seqV, + DPBandConfig const & band, + DPProfile_ const & dpProfile) +{ + if (IsSingleTrace_::VALUE) + _correctTraceValue(dpTraceMatrixNavigator, dpScout); + + _computeTraceback(traceSegments, dpTraceMatrixNavigator, dpScout, seqH, seqV, band, dpProfile); + return maxScore(dpScout); +} + +// ---------------------------------------------------------------------------- +// Function _computeAligmnment() +// ---------------------------------------------------------------------------- + +template +inline typename Value::Type +_computeAlignment(DPContext & dpContext, + TTraceTarget & traceSegments, + TScoutState & scoutState, + TSequenceH const & seqH, + TSequenceV const & seqV, + TScoreScheme const & scoreScheme, + DPBandConfig const & band, + DPProfile_ const & dpProfile) +{ + typedef typename GetDPScoreMatrix >::Type TDPScoreMatrixHost; + typedef typename Value::Type TDPScoreValue; + + typedef typename GetDPTraceMatrix >::Type TDPTraceMatrixHost; + typedef typename Value::Type TTraceValue; + + typedef typename DefaultScoreMatrixSpec_::Type TScoreMatrixSpec; + + typedef DPMatrix_ TDPScoreMatrix; + typedef DPMatrix_ TDPTraceMatrix; + + typedef DPMatrixNavigator_ TDPScoreMatrixNavigator; + typedef DPMatrixNavigator_, NavigateColumnWise> TDPTraceMatrixNavigator; + + typedef typename ScoutSpecForAlignmentAlgorithm_::Type TDPScoutSpec; + typedef DPScout_ TDPScout; + + // Check if current dp settings are valid. If not return infinity value for dp score value. + if (!_isValidDPSettings(seqH, seqV, band, dpProfile)) + return createVector(MinValue::Type>::VALUE); // NOTE(rrahn): In case of non-simd version, createVector returns just a scalar. + + TDPScoreMatrix dpScoreMatrix; + TDPTraceMatrix dpTraceMatrix; + + // TODO(rmaerker): Check whether the matrix allocation can be reduced if upperDiagonal < 0? + setLength(dpScoreMatrix, +DPMatrixDimension_::HORIZONTAL, length(seqH) + 1 - std::max(0, lowerDiagonal(band))); + setLength(dpTraceMatrix, +DPMatrixDimension_::HORIZONTAL, length(seqH) + 1 - std::max(0, lowerDiagonal(band))); + + if (IsSameType::VALUE) + { + setLength(dpScoreMatrix, +DPMatrixDimension_::VERTICAL, length(seqV) + 1); + setLength(dpTraceMatrix, +DPMatrixDimension_::VERTICAL, length(seqV) + 1); + } + else + { + int bandSize = _min(static_cast(length(seqH)), upperDiagonal(band)) - _max(lowerDiagonal(band), -static_cast(length(seqV))) + 1; + setLength(dpScoreMatrix, +DPMatrixDimension_::VERTICAL, _min(static_cast(length(seqV)) + 1, bandSize)); + setLength(dpTraceMatrix, +DPMatrixDimension_::VERTICAL, _min(static_cast(length(seqV)) + 1, bandSize)); + } + + // We set the host to the score matrix and the dp matrix. + setHost(dpScoreMatrix, getDpScoreMatrix(dpContext)); + setHost(dpTraceMatrix, getDpTraceMatrix(dpContext)); + + resize(dpScoreMatrix); + // We do not need to allocate the memory for the trace matrix if the traceback is disabled. + if (IsTracebackEnabled_::VALUE) + resize(dpTraceMatrix); + + TDPScoreMatrixNavigator dpScoreMatrixNavigator; + TDPTraceMatrixNavigator dpTraceMatrixNavigator; + + _init(dpScoreMatrixNavigator, dpScoreMatrix, band); + _init(dpTraceMatrixNavigator, dpTraceMatrix, band); + + TDPScout dpScout(scoutState); +#if SEQAN_ALIGN_SIMD_PROFILE + profile.preprTimer += sysTime() - timer; + timer = sysTime(); +#endif + // Execute the alignment. + if (!_isBandEnabled(band)) + _computeUnbandedAlignment(dpScout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, seqH, seqV, scoreScheme, dpProfile); + else if (upperDiagonal(band) == lowerDiagonal(band)) + _computeHammingDistance(dpScout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, seqH, seqV, scoreScheme, band, dpProfile); + else + _computeBandedAlignment(dpScout, dpScoreMatrixNavigator, dpTraceMatrixNavigator, seqH, seqV, scoreScheme, + band, dpProfile); +#if SEQAN_ALIGN_SIMD_PROFILE + profile.alignTimer += sysTime() - timer; + timer = sysTime(); +#endif + return _finishAlignment(traceSegments, dpTraceMatrixNavigator, dpScout, seqH, seqV, band, dpProfile); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_ALGORITHM_IMPL_H_ diff --git a/seqan/align/dp_align_simd_helper.h b/seqan/align/dp_align_simd_helper.h new file mode 100644 index 0000000..8fd634a --- /dev/null +++ b/seqan/align/dp_align_simd_helper.h @@ -0,0 +1,517 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== + +#ifndef INCLUDE_SEQAN_ALIGN_DP_ALIGN_SIMD_HELPER_H_ +#define INCLUDE_SEQAN_ALIGN_DP_ALIGN_SIMD_HELPER_H_ + +namespace seqan +{ + +#if SEQAN_ALIGN_SIMD_PROFILE +struct AlignSimdProfile_ +{ + double preprTimer = 0.0; + double alignTimer = 0.0; + double traceTimer = 0.0; + + void clear() + { + preprTimer = 0.0; + alignTimer = 0.0; + traceTimer = 0.0; + } +}; + + double timer = 0.0; + +AlignSimdProfile_ profile; +#endif + +// ============================================================================ +// Forwards +// ============================================================================ + +template +struct VectorLength_; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +template +struct SimdAlignVariableLengthTraits +{ + using TSimdVector = TSimdVector_; + using TSeqH = TSeqH_; + using TSeqV = TSeqV_; +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _createSimdRepImpl() +// ---------------------------------------------------------------------------- + +#define SEQAN_CREATE_SIMD_REP_IMPL_2(data, strPos, chrPos) getValue(data[strPos + 1], chrPos), getValue(data[strPos], chrPos) +#define SEQAN_CREATE_SIMD_REP_IMPL_4(data, strPos, chrPos) SEQAN_CREATE_SIMD_REP_IMPL_2(data, strPos + 2, chrPos), SEQAN_CREATE_SIMD_REP_IMPL_2(data, strPos, chrPos) +#define SEQAN_CREATE_SIMD_REP_IMPL_8(data, strPos, chrPos) SEQAN_CREATE_SIMD_REP_IMPL_4(data, strPos + 4, chrPos), SEQAN_CREATE_SIMD_REP_IMPL_4(data, strPos, chrPos) +#define SEQAN_CREATE_SIMD_REP_IMPL_16(data, strPos, chrPos) SEQAN_CREATE_SIMD_REP_IMPL_8(data, strPos + 8, chrPos), SEQAN_CREATE_SIMD_REP_IMPL_8(data, strPos, chrPos) +#define SEQAN_CREATE_SIMD_REP_IMPL_32(data, strPos, chrPos) SEQAN_CREATE_SIMD_REP_IMPL_16(data, strPos + 16, chrPos), SEQAN_CREATE_SIMD_REP_IMPL_16(data, strPos, chrPos) + +#define SEQAN_CREATE_SIMD_REP_FILL_IMPL_2(MACRO, data, chrPos) MACRO(data, 0, chrPos) +#define SEQAN_CREATE_SIMD_REP_FILL_IMPL(data, chrPos, SIZE) SEQAN_CREATE_SIMD_REP_FILL_IMPL_2(SEQAN_CREATE_SIMD_REP_IMPL_##SIZE, data, chrPos) + +#define SEQAN_CREATE_SIMD_REP_IMPL(SIZE) \ +template \ +inline void _createSimdRepImpl(TSimdVecs & simdStr, \ + TStrings const & strings, \ + VectorLength_ const & /*size*/) \ +{ \ + auto itB = begin(simdStr, Standard()); \ + auto itE = end(simdStr, Standard()); \ + for (auto it = itB; it != itE; ++it) \ + fillVector(*it, SEQAN_CREATE_SIMD_REP_FILL_IMPL(strings, it - itB, SIZE)); \ +} + +SEQAN_CREATE_SIMD_REP_IMPL(2) +SEQAN_CREATE_SIMD_REP_IMPL(4) +SEQAN_CREATE_SIMD_REP_IMPL(8) +SEQAN_CREATE_SIMD_REP_IMPL(16) +SEQAN_CREATE_SIMD_REP_IMPL(32) + +template +inline void _createSimdRepImpl(TSimdVecs & simdStr, + TStrings const & strings) +{ + _createSimdRepImpl(simdStr, strings, VectorLength_::Type>::VALUE>()); +} + +// Actually precompute value if scoring scheme is score matrix and simd version. +template +inline SEQAN_FUNC_ENABLE_IF(And >, IsScoreMatrix_ >, TSeqValue) +_precomputeScoreMatrixOffset(TSeqValue const & seqVal, + Score > const & /*score*/) +{ + return createVector(TScore::VALUE_SIZE) * seqVal; +} + +// ---------------------------------------------------------------------------- +// Function _prepareAndRunSimdAlignment() +// ---------------------------------------------------------------------------- + +template +inline void +_prepareAndRunSimdAlignment(TResult & results, + TTraces & traces, + TSequencesH const & seqH, + TSequencesV const & seqV, + TScore const & scoringScheme, + AlignConfig2 const & alignConfig, + TGapModel const & /*gapModel*/, + SimdAlignEqualLength const & /*tag*/) +{ + String > stringSimdH; + String > stringSimdV; + + resize(stringSimdH, length(seqH[0])); + resize(stringSimdV, length(seqV[0])); + _createSimdRepImpl(stringSimdH, seqH); + _createSimdRepImpl(stringSimdV, seqV); + + DPScoutState_ state; + results = _setUpAndRunAlignment(traces, state, stringSimdH, stringSimdV, scoringScheme, alignConfig, TGapModel()); +} + +template +inline void +_prepareAndRunSimdAlignment(TResult & results, + TTraces & traces, + TSequencesH const & seqH, + TSequencesV const & seqV, + TScore const & scoringScheme, + AlignConfig2 const & alignConfig, + TGapModel const & /*gapModel*/, + SimdAlignVariableLength const /*tag*/) +{ + SEQAN_ASSERT_EQ(length(seqH), length(seqV)); + SEQAN_ASSERT_EQ(static_cast(LENGTH::VALUE), length(seqH)); + + using TPadStringH = ModifiedString::Type, ModPadding>; + using TPadStringV = ModifiedString::Type, ModPadding>; + + String > stringSimdH; + String > stringSimdV; + + DPScoutState_ > > state; + + String lengthsH; + String lengthsV; + + resize(lengthsH, length(seqH)); + resize(lengthsV, length(seqV)); + resize(state.endsH, length(seqH)); + resize(state.endsV, length(seqV)); + + for (unsigned i = 0; i < length(seqH); ++i) + { + lengthsH[i] = length(seqH[i]) - 1; + lengthsV[i] = length(seqV[i]) - 1; + state.endsH[i] = i; + state.endsV[i] = i; + } + + setHost(state.sortedEndsH, lengthsH); + setHost(state.sortedEndsV, lengthsV); + setCargo(state.sortedEndsH, state.endsH); + setCargo(state.sortedEndsV, state.endsV); + + auto maxLengthLambda = [](auto& lengthLhs, auto& lengthRhs) { return lengthLhs < lengthRhs; }; + sort(state.sortedEndsH, maxLengthLambda, Serial()); + sort(state.sortedEndsV, maxLengthLambda, Serial()); + + size_t maxH = back(state.sortedEndsH) + 1; + size_t maxV = back(state.sortedEndsV) + 1; + + // and we have to prepare the bit masks of the DPScoutState + resize(state.masks, maxV, createVector(0)); + resize(state.masksV, maxV, createVector(0)); + resize(state.masksH, maxH, createVector(0)); + + // Create Stringset with padded strings. + StringSet paddedH; + StringSet paddedV; + resize(paddedH, length(seqH)); + resize(paddedV, length(seqV)); + + for(unsigned i = 0; i < length(seqH); ++i) + { + setHost(paddedH[i], seqH[i]); + setHost(paddedV[i], seqV[i]); + expand(paddedH[i], maxH); + expand(paddedV[i], maxV); + + // mark the original end position of the alignment in the masks (with -1, all bits set) + assignValue(state.masksH[lengthsH[i]], i, -1); + assignValue(state.masksV[lengthsV[i]], i, -1); + } + + // now create SIMD representation + resize(stringSimdH, maxH); + resize(stringSimdV, maxV); + _createSimdRepImpl(stringSimdH, paddedH); + _createSimdRepImpl(stringSimdV, paddedV); + + state.dimV = length(stringSimdV); + state.isLocalAlignment = IsLocalAlignment_::VALUE; + state.right = IsFreeEndGap_::VALUE; + state.bottom = IsFreeEndGap_::VALUE; + + results = _setUpAndRunAlignment(traces, state, stringSimdH, stringSimdV, scoringScheme, alignConfig, TGapModel()); +} + +template +inline void +_prepareAndRunSimdAlignment(TResult & results, + TTraces & traces, + TSequencesH const & seqH, + TSequencesV const & seqV, + TScore const & scoringScheme, + AlignConfig2 const & alignConfig, + TGapModel const & /*gapModel*/) +{ + auto seqLengthH = length(seqH[0]); + auto seqLengthV = length(seqV[0]); + auto zipView = makeZipView(seqH, seqV); + bool allSameLength = std::all_of(begin(zipView, Standard()), end(zipView, Standard()), + [seqLengthH, seqLengthV](auto param) + { + return (length(std::get<0>(param)) == seqLengthH) && + (length(std::get<1>(param)) == seqLengthV); + }); + if(allSameLength) + _prepareAndRunSimdAlignment(results, traces, seqH, seqV, scoringScheme, alignConfig, TGapModel(), SimdAlignEqualLength()); + else + _prepareAndRunSimdAlignment(results, traces, seqH, seqV, scoringScheme, alignConfig, TGapModel(), + SimdAlignVariableLength()); +} + +// ---------------------------------------------------------------------------- +// Function _alignWrapperSimd(); Score; StringSet vs. StringSet +// ---------------------------------------------------------------------------- + +template +inline auto +_alignWrapperSimd(StringSet const & stringsH, + StringSet const & stringsV, + Score const & scoringScheme, + TAlignConfig const & config, + TGapModel const & /*gaps*/) +{ + typedef typename SimdVector::Type TSimdAlign; + + unsigned const numAlignments = length(stringsV); + unsigned const sizeBatch = LENGTH::VALUE; + unsigned const fullSize = sizeBatch * ((numAlignments + sizeBatch - 1) / sizeBatch); + + String results; + resize(results, numAlignments); + + StringSet > trace; // We need to declare it, but it will not be used. + + // Create a SIMD scoring scheme. + Score > > simdScoringScheme(scoringScheme); + + for (auto pos = 0u; pos < fullSize; pos += sizeBatch) + { + TSimdAlign resultsBatch; + if (SEQAN_UNLIKELY(numAlignments < pos + sizeBatch)) + { + StringSet > depSetH; + StringSet > depSetV; + for (unsigned i = pos; i < fullSize; ++i) + { + if (i >= numAlignments) + { + appendValue(depSetH, back(stringsH)); + appendValue(depSetV, back(stringsV)); + } + else + { + appendValue(depSetH, stringsH[i]); + appendValue(depSetV, stringsV[i]); + } + } + SEQAN_ASSERT_EQ(length(depSetH), sizeBatch); + SEQAN_ASSERT_EQ(length(depSetV), sizeBatch); + + _prepareAndRunSimdAlignment(resultsBatch, trace, depSetH, depSetV, simdScoringScheme, config, TGapModel()); + } + else + { + auto infSetH = infixWithLength(stringsH, pos, sizeBatch); + auto infSetV = infixWithLength(stringsV, pos, sizeBatch); + + _prepareAndRunSimdAlignment(resultsBatch, trace, infSetH, infSetV, simdScoringScheme, config, TGapModel()); + } + + // TODO(rrahn): Could be parallelized! + for(auto x = pos; x < pos + sizeBatch && x < numAlignments; ++x) + results[x] = resultsBatch[x - pos]; + } + return results; +} + +// ---------------------------------------------------------------------------- +// Function _alignWrapperSimd(); Score; String vs. StringSet +// ---------------------------------------------------------------------------- + +template +inline auto +_alignWrapperSimd(TString1 const & stringH, + StringSet const & stringsV, + Score const & scoringScheme, + TAlignConfig const & config, + TGapModel const & /*gaps*/) +{ + typedef typename SimdVector::Type TSimdAlign; + + unsigned const numAlignments = length(stringsV); + unsigned const sizeBatch = LENGTH::VALUE; + unsigned const fullSize = sizeBatch * ((numAlignments + sizeBatch - 1) / sizeBatch); + + String results; + resize(results, numAlignments); + + // Prepare strings. + StringSet > setH; + for (auto i = 0u; i < sizeBatch; ++i) + appendValue(setH, stringH); + + StringSet > trace; // We need to declare it, but it will not be used. + + // Create a SIMD scoring scheme. + Score > > simdScoringScheme(scoringScheme); + + for (auto pos = 0u; pos < fullSize; pos += sizeBatch) + { + TSimdAlign resultsBatch; + if (SEQAN_UNLIKELY(numAlignments < pos + sizeBatch)) + { + StringSet > depSetV; + for (unsigned i = pos; i < fullSize; ++i) + { + if (i >= numAlignments) + appendValue(depSetV, back(stringsV)); + else + appendValue(depSetV, stringsV[i]); + } + SEQAN_ASSERT_EQ(length(depSetV), sizeBatch); + + _prepareAndRunSimdAlignment(resultsBatch, trace, setH, depSetV, simdScoringScheme, config, TGapModel()); + } + else + { + auto infSetV = infixWithLength(stringsV, pos, sizeBatch); + _prepareAndRunSimdAlignment(resultsBatch, trace, setH, infSetV, simdScoringScheme, config, TGapModel()); + } + // TODO(rrahn): Could be parallelized! + for(auto x = pos; x < pos + sizeBatch && x < numAlignments; ++x) + results[x] = resultsBatch[x - pos]; + } + return results; +} + +// ---------------------------------------------------------------------------- +// Function _alignWrapperSimd(); Gaps +// ---------------------------------------------------------------------------- + +template +inline auto +_alignWrapperSimd(StringSet, TSetSpecH> & gapSeqSetH, + StringSet, TSetSpecV> & gapSeqSetV, + Score const & scoringScheme, + TAlignConfig const & config, + TGapModel const & /*gaps*/) +{ + typedef Gaps TGapSequenceH; + typedef Gaps TGapSequenceV; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + + typedef typename SimdVector::Type TSimdAlign; + +#if SEQAN_ALIGN_SIMD_PROFILE + timer = sysTime(); +#endif + + unsigned const numAlignments = length(gapSeqSetH); + unsigned const sizeBatch = LENGTH::VALUE; + unsigned const fullSize = sizeBatch * ((numAlignments + sizeBatch - 1) / sizeBatch); + + String results; + resize(results, numAlignments); + + // Create a SIMD scoring scheme. + Score > > simdScoringScheme(scoringScheme); + + // Prepare string sets with sequences. + StringSet::Type, Dependent<> > depSetH; + StringSet::Type, Dependent<> > depSetV; + reserve(depSetH, fullSize); + reserve(depSetV, fullSize); + for (unsigned i = 0; i < fullSize; ++i) + { + if (i >= numAlignments) + { + appendValue(depSetH, source(back(gapSeqSetH))); + appendValue(depSetV, source(back(gapSeqSetV))); + } + else + { + appendValue(depSetH, source(gapSeqSetH[i])); + appendValue(depSetV, source(gapSeqSetV[i])); + } + } + + // Run alignments in batches. + for (auto pos = 0u; pos < fullSize; pos += sizeBatch) + { + auto infSetH = infixWithLength(depSetH, pos, sizeBatch); + auto infSetV = infixWithLength(depSetV, pos, sizeBatch); + + TSimdAlign resultsBatch; + + StringSet > trace; + resize(trace, sizeBatch, Exact()); + + _prepareAndRunSimdAlignment(resultsBatch, trace, infSetH, infSetV, simdScoringScheme, config, TGapModel()); + + // copy results and finish traceback + // TODO(rrahn): Could be parallelized! + // to for_each call + for(auto x = pos; x < pos + sizeBatch && x < numAlignments; ++x) + { + results[x] = resultsBatch[x - pos]; + _adaptTraceSegmentsTo(gapSeqSetH[x], gapSeqSetV[x], trace[x - pos]); + } +#if SEQAN_ALIGN_SIMD_PROFILE + profile.traceTimer += sysTime() - timer; + timer = sysTime(); +#endif + } + return results; +} + +} // namespace seqan +#endif // #ifndef INCLUDE_SEQAN_ALIGN_DP_ALIGN_SIMD_HELPER_H_ + diff --git a/seqan/align/dp_band.h b/seqan/align/dp_band.h new file mode 100644 index 0000000..b636d50 --- /dev/null +++ b/seqan/align/dp_band.h @@ -0,0 +1,384 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// This class stores the band information as well as the meta-inforation, +// whether a band was selected or not. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_BAND_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_BAND_H_ + +namespace seqan +{ + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @defgroup DPBandSwitch + * @brief Tags used to switch between banded and unbanded alignment. + * + * @tag DPBandSwitch#BandOn + * @brief Switches banded alignment on. + * @headerfile + * @signature struct BandOn_; + * @signature typedef Tag BandOn; + * + * @tag DPBandSwitch#BandOff + * @brief Switches banded alignment off. + * @headerfile + * @signature struct BandOff_; + * @signature typedef Tag BandOff; + */ + +// ---------------------------------------------------------------------------- +// Tag BandOff +// ---------------------------------------------------------------------------- + +// Used when computing unbanded alignments. +struct BandOff_; +typedef Tag BandOff; + +// ---------------------------------------------------------------------------- +// Tag BandOn +// ---------------------------------------------------------------------------- + +// Used when computing banded alignments. +struct BandOn_; +typedef Tag BandOn; + +// ---------------------------------------------------------------------------- +// Class DPBandConfig +// ---------------------------------------------------------------------------- + +/*! + * @class DPBandConfig + * @headerfile + * @brief Simple class to configure banded alignments. + * + * @signature template + * class DPBandConfig; + * + * @tparam TSwitch Tag to switch between banded and unbanded alignments. + * One of @link DPBandSwitch @endlink. Defaults to @link DPBandSwitch#BandOff @endlink. + * + * To compute banded alignments use @link DPBand @endlink as a shortcut for the DPBandConfig with + * band switched on. + */ + +// Simple band class. +template +struct DPBandConfig {}; + +// ---------------------------------------------------------------------------- +// Class DPBandConfig [BandOff] +// ---------------------------------------------------------------------------- + +// The specialization when using no band. +// Per default the member variables _lowerDiagonal and _upperDiagonal are +// always 0. +template <> +struct DPBandConfig +{ + typedef int TPosition; +}; + +// ---------------------------------------------------------------------------- +// Class DPBandConfig [BandOn] +// ---------------------------------------------------------------------------- + +// The specialization when using a band. +// On construction the diagonals are set to 0. +template <> +struct DPBandConfig +{ + typedef int TPosition; + + int _lowerDiagonal; + int _upperDiagonal; + +/*! + * @fn DPBandConfig::DPBandConfig + * @brief Constructor. + * + * @signature DPBandConfig(); + * @signature DPBandConfig(lowerDiag, upperDiag); + * + * @tparam TSwitch Tag to switch between banded and unbanded alignments. One of @link DPBandSwitch @endlink. + * The second constructor is only supported when @link DPBandConfig @endlink is specialized with + * @link DPBandSwitch#BandOn @endlink. + * + * @param lowerDiag The value for the lower diagonal of the band. + * @param upperDiag The value for the upper diagonal of the band. + * + * A negative value for the diagonals indicates an intersection of the diagonal with the vertical sequence (y-axis) + * and a positive value indicates an intersection with the horizontal sequence (x-axis). + * The value of the lower diagonal has to compare less or equal to the value of the upper diagonal. + */ + + DPBandConfig() : + _lowerDiagonal(0), _upperDiagonal(0) {} + + DPBandConfig(int lowerDiagonal, int upperDiagonal) : + _lowerDiagonal(lowerDiagonal), _upperDiagonal(upperDiagonal) + { + SEQAN_ASSERT_LEQ(lowerDiagonal, upperDiagonal); + } +}; + +/*! + * @typedef DPBand + * @headerfile + * @brief Global typedef used for @link DPBandConfig @endlink specialized with @link DPBandSwitch#BandOn @endlink. + * + * @signature typedef DPBandConfig DPBand; + */ + +// Typedef for Band. +typedef DPBandConfig DPBand; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +/*! + * @mfn DPBandConfig#Position + * @headerfile + * @brief Metafunction returning the position type. + * + * @signature typename Position::Type; + * + * @tparam T The type @link DPBandConfig @endlink to query the position type for. + * @return TPosition The position type. + */ + +// ---------------------------------------------------------------------------- +// Metafunction Position +// ---------------------------------------------------------------------------- + +template +struct Position > +{ + typedef typename DPBandConfig::TPosition Type; +}; + +template +struct Position const>: + Position >{}; + +// ---------------------------------------------------------------------------- +// Metafunction Size +// ---------------------------------------------------------------------------- + +/*! + * @mfn DPBandConfig#Size + * @headerfile + * @brief Metafunction returning the size type. + * + * @signature typename Size::Type; + * + * @tparam T The type @link DPBandConfig @endlink to query the size type for. + * @return TSize The size type. + */ + +template +struct Size > +{ + typedef unsigned Type; +}; + + +template +struct Size const>: + Size >{}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function setLowerDiagonal +// ---------------------------------------------------------------------------- + +/*! + * @fn DPBandConfig#setLowerDiagonal + * @headerfile + * @brief Sets the value of the lower diagonal. + * + * @signature setLowerDiagonal(obj, val); + * + * @param obj The object of type @link DPBandConfig @endlink to set the lower diagonal for. + * @param val The new value for the lower diagonal. + * + * @note If the band is switched off, this function defaults to no-op. + */ + +inline void +setLowerDiagonal(DPBandConfig & /*dpBand*/, int /*newLowerDiagonal*/) +{ + //no-op +} + +inline void +setLowerDiagonal(DPBandConfig & dpBand, int newLowerDiagonal) +{ + dpBand._lowerDiagonal = newLowerDiagonal; +} + +// ---------------------------------------------------------------------------- +// Function lowerDiagonal +// ---------------------------------------------------------------------------- + +/*! + * @fn DPBandConfig#lowerDiagonal + * @headerfile + * @brief Returns the value of the lower diagonal. + * + * @signature TPosition lowerDiagonal(obj); + * + * @param obj The object of type @link DPBandConfig @endlink to query the lower diagonal for. + * + * @note If the band is switched off this function always returns 0. + * @return TPosition The value of the lower diagonal. + */ + +inline Position >::Type +lowerDiagonal(DPBandConfig const & /*dpBand*/) +{ + return 0; +} + +template +inline typename Position >::Type +lowerDiagonal(DPBandConfig const & dpBand) +{ + return dpBand._lowerDiagonal; +} + +// ---------------------------------------------------------------------------- +// Function setUpperDiagonal +// ---------------------------------------------------------------------------- + +/*! + * @fn DPBandConfig#setUpperDiagonal + * @headerfile + * @brief Sets the value of the upper diagonal. + * + * @signature setUpperDiagonal(obj, val); + * + * @param obj The object of type @link DPBandConfig @endlink to set the upper diagonal for. + * @param val The new value for the upper diagonal. + * + * @note If the band is switched off, this function defaults to no-op. + */ + +inline void +setUpperDiagonal(DPBandConfig & /*dpBand*/, int /*newUpperDiagonal*/) +{ + //no-op +} + +inline void +setUpperDiagonal(DPBandConfig & dpBand, int newUpperDiagonal) +{ + dpBand._upperDiagonal = newUpperDiagonal; +} + +// ---------------------------------------------------------------------------- +// Function upperDiagonal +// ---------------------------------------------------------------------------- + +/*! + * @fn DPBandConfig#upperDiagonal + * @headerfile + * @brief Returns the value of the upper diagonal. + * + * @signature TPosition upperDiagonal(obj); + * + * @param obj The object of type @link DPBandConfig @endlink to query the upper diagonal for. + * + * @note If the band is switched off this function always returns 0. + * @return TPosition The value of the upper diagonal. + */ + +inline Position >::Type +upperDiagonal(DPBandConfig const & /*dpBand*/) +{ + return 0; +} + +template +inline typename Position >::Type +upperDiagonal(DPBandConfig const & dpBand) +{ + return dpBand._upperDiagonal; +} + +// ---------------------------------------------------------------------------- +// Function bandSize() +// ---------------------------------------------------------------------------- + +/*! + * @fn DPBandConfig#bandSize + * @headerfile + * @brief Returns the size of the band. + * + * @signature TSize bandSize(obj); + * + * @param obj The object of type @link DPBandConfig @endlink to query the band size for. + * + * @note If the band is switched off this function always returns 0. + * @return TSize The number of diagonals covered by the band. + */ + +inline Size >::Type +bandSize(DPBandConfig const &) +{ + return 0; +} + +template +inline typename Size >::Type +bandSize(DPBandConfig const & band) +{ + return upperDiagonal(band) - lowerDiagonal(band) + 1; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_BAND_H_ diff --git a/seqan/align/dp_cell.h b/seqan/align/dp_cell.h new file mode 100644 index 0000000..49f3b85 --- /dev/null +++ b/seqan/align/dp_cell.h @@ -0,0 +1,283 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Declares the DPCell, which is used to substitute the score of each cell. +// Thus, we are able to add additional features to an alignment cell such as +// a flag to indicate if it is forbidden or not. Or to store two additional +// scores necessary for the affine gap function. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_CELL_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_CELL_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class DPCell_ +// ---------------------------------------------------------------------------- + +// Used to store the score of a particular cell of the score matrix. +// It can be specialized for linear and affine gap costs. +// For affine gap costs it stores the values of all three matrices at a particular +// position of the matrix. +template +class DPCell_; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Value +// ---------------------------------------------------------------------------- + +template +struct Value > +{ + typedef TScoreValue Type; +}; + +template +struct Value const> +{ + typedef TScoreValue const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Reference +// ---------------------------------------------------------------------------- + +template +struct Reference > +{ + typedef TScoreValue & Type; +}; + +template +struct Reference const> +{ + typedef TScoreValue const & Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction DPCellDefaultInfinity +// ---------------------------------------------------------------------------- + +// Defines the default infinity value for a DPCell. +template +struct DPCellDefaultInfinity +{ + static const int VALUE; +}; + +template +const int DPCellDefaultInfinity::VALUE = MinValue::VALUE; + +// We use the min value of the score type and shift it one bits to the left. This way we can use "infinity" without +// checking for it during the computation. +template +struct DPCellDefaultInfinity > +{ + static const TScoreValue VALUE; +}; + +template + const TScoreValue DPCellDefaultInfinity >::VALUE = + createVector(MinValue::Type>::VALUE) / createVector(2); + +template +struct DPCellDefaultInfinity const> : + public DPCellDefaultInfinity >{}; + +// ---------------------------------------------------------------------------- +// Metafunction StringSpecForValue_ +// ---------------------------------------------------------------------------- + +// Defines the default infinity value for a DPCell. +template +struct StringSpecForValue_ > +{ + typedef typename If >, Alloc, Alloc<> >::Type Type; +}; + +template +struct StringSpecForValue_ const> : + StringSpecForValue_ > +{}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _scoreOfCell +// ---------------------------------------------------------------------------- + +// Returns the score value for a given cell. +template +inline typename Reference >::Type +_scoreOfCell(DPCell_ & dpCell) +{ + return dpCell._score; +} + +template +inline typename Reference const>::Type +_scoreOfCell(DPCell_ const & dpCell) +{ + return dpCell._score; +} + +// ---------------------------------------------------------------------------- +// Function _setScoreOfCell +// ---------------------------------------------------------------------------- + +template +inline void +_setScoreOfCell(DPCell_ & dpCell, TScoreValue const & newScore) +{ + dpCell._score = newScore; +} + +template +inline void +_setScoreOfCell(DPCell_ & dpCell, TScoreValue const & newScore, TScoreValue const & mask) +{ + dpCell._score = blend(dpCell._score, newScore, mask); +} + +// ---------------------------------------------------------------------------- +// Function _verticalScoreOfCell() +// ---------------------------------------------------------------------------- + +// Returns the score of the matrix for vertical-gaps of the given cell. +template +inline typename Reference >::Type +_verticalScoreOfCell(DPCell_ & dpCell) +{ + return dpCell._score; +} + +template +inline typename Reference const>::Type +_verticalScoreOfCell(DPCell_ const & dpCell) +{ + return dpCell._score; +} + +// ---------------------------------------------------------------------------- +// Function _setVerticalScoreOfCell() +// ---------------------------------------------------------------------------- + +// Returns the score of the matrix for vertical-gaps of the given cell. +template +inline void +_setVerticalScoreOfCell(DPCell_ & /*dpCell*/, TScoreValue const & /*newVerticalScore*/) +{ + // no-op +} + +template +inline void +_setVerticalScoreOfCell(DPCell_ & /*dpCell*/, TScoreValue const & /*newVerticalScore*/, TScoreValue const & /*mask*/) +{ + // no-op +} + +// ---------------------------------------------------------------------------- +// Function _horizontalScoreOfCell() +// ---------------------------------------------------------------------------- + +// Returns the score of the matrix for horizontal-gaps of the given cell. +template +inline typename Reference >::Type +_horizontalScoreOfCell(DPCell_ & dpCell) +{ + return dpCell._score; +} + +template +inline typename Reference const>::Type +_horizontalScoreOfCell(DPCell_ const & dpCell) +{ + return dpCell._score; +} + +// ---------------------------------------------------------------------------- +// Function _setHorizontalScoreOfCell() +// ---------------------------------------------------------------------------- + +// Returns the score of the matrix for vertical-gaps of the given cell. +template +inline void +_setHorizontalScoreOfCell(DPCell_ & /*dpCell*/, TScoreValue const & /*newHorizontalScore*/) +{ + // no-op +} + +template +inline void +_setHorizontalScoreOfCell(DPCell_ & /*dpCell*/, TScoreValue const & /*newHorizontalScore*/, TScoreValue const & /*mask*/) +{ + // no-op +} + +// ---------------------------------------------------------------------------- +// Function setGapExtension() +// ---------------------------------------------------------------------------- + +template +inline void +setGapExtension(DPCell_ & /*dpCell*/, TF1 , TF2) +{ + // no-op +} + +template +inline void +setGapExtension(DPCell_ & /*dpCell*/, TF1 , TF2, TScoreValue) +{ + // no-op +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_CELL_H_ diff --git a/seqan/align/dp_cell_affine.h b/seqan/align/dp_cell_affine.h new file mode 100644 index 0000000..c12990c --- /dev/null +++ b/seqan/align/dp_cell_affine.h @@ -0,0 +1,208 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Implements the DPCell for affine gap functions. It stores the score +// values for the three matrices: diagonal, vertical and horizontal. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_CELL_AFFINE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_CELL_AFFINE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class DPCell [AffineGaps] +// ---------------------------------------------------------------------------- + +// Specialization for the affine gap cost function. +// This class stores three values belonging to the matrix storing the current +// maximum, the matrix for horizontal gaps and the matrix for vertical gaps. +template +class DPCell_ +{ +public: + TScoreValue _score = DPCellDefaultInfinity::VALUE; + TScoreValue _horizontalScore = DPCellDefaultInfinity::VALUE; + TScoreValue _verticalScore = DPCellDefaultInfinity::VALUE; + + DPCell_() = default; + // Copy c'tor. + DPCell_(DPCell_ const & other) : + _score(other._score), + _horizontalScore(other._horizontalScore), + _verticalScore(other._verticalScore) + {} + + // Move c-tor + DPCell_(DPCell_ && other) : DPCell_() + { + swap(*this, other); + } + + // The assignment operator. + DPCell_ & + operator=(DPCell_ other) + { + swap(*this, other); + return *this; + } + + // Assign score to cell. + DPCell_ & + operator=(TScoreValue const & score) + { + _score = score; + return *this; + } + + ~DPCell_() = default; +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function operator<() +// ---------------------------------------------------------------------------- + +// Needed for banded chain alignment for the set. +template +inline bool operator<(DPCell_ const & left, + DPCell_ const & right) +{ + return left._score < right._score && left._horizontalScore < right._horizontalScore && + left._verticalScore < right._verticalScore; +} + +// ---------------------------------------------------------------------------- +// Function _verticalScoreOfCell() +// ---------------------------------------------------------------------------- + +// Returns the score of the matrix for vertical-gaps of the given cell. +template +inline typename Reference >::Type +_verticalScoreOfCell(DPCell_ & dpCell) +{ + return dpCell._verticalScore; +} + +template +inline typename Reference const>::Type +_verticalScoreOfCell(DPCell_ const & dpCell) +{ + return dpCell._verticalScore; +} + +// ---------------------------------------------------------------------------- +// Function _setVerticalScoreOfCell() +// ---------------------------------------------------------------------------- + +// Returns the score of the matrix for vertical-gaps of the given cell. +template +inline SEQAN_FUNC_ENABLE_IF(Not > >,void) +_setVerticalScoreOfCell(DPCell_ & dpCell, TScoreValue const & newVerticalScore) +{ + dpCell._verticalScore = newVerticalScore; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >,void) +_setVerticalScoreOfCell(DPCell_ & dpCell, TScoreValue const & newVerticalScore, TScoreValue const & mask) +{ + dpCell._verticalScore = blend(dpCell._verticalScore, newVerticalScore, mask); +} + +// ---------------------------------------------------------------------------- +// Function _horizontalScoreOfCell() +// ---------------------------------------------------------------------------- + +// Returns the score of the matrix for horizontal-gaps of the given cell. +template +inline typename Reference >::Type +_horizontalScoreOfCell(DPCell_ & dpCell) +{ + return dpCell._horizontalScore; +} + +template +inline typename Reference const>::Type +_horizontalScoreOfCell(DPCell_ const & dpCell) +{ + return dpCell._horizontalScore; +} + +// ---------------------------------------------------------------------------- +// Function _setHorizontalScoreOfCell() +// ---------------------------------------------------------------------------- + +// Returns the score of the matrix for vertical-gaps of the given cell. +template +inline SEQAN_FUNC_ENABLE_IF(Not > >,void) +_setHorizontalScoreOfCell(DPCell_ & dpCell, TScoreValue const & newHorizontalScore) +{ + dpCell._horizontalScore = newHorizontalScore; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >,void) +_setHorizontalScoreOfCell(DPCell_ & dpCell, TScoreValue const & newHorizontalScore, TScoreValue const & mask) +{ + dpCell._horizontalScore = blend(dpCell._horizontalScore, newHorizontalScore, mask); +} + +template +inline void +swap(DPCell_ & lhs, + DPCell_ & rhs) +{ + std::swap(lhs._score, rhs._score); + std::swap(lhs._horizontalScore, rhs._horizontalScore); + std::swap(lhs._verticalScore, rhs._verticalScore); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_CELL_AFFINE_H_ diff --git a/seqan/align/dp_cell_dynamic.h b/seqan/align/dp_cell_dynamic.h new file mode 100644 index 0000000..567d5f9 --- /dev/null +++ b/seqan/align/dp_cell_dynamic.h @@ -0,0 +1,249 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Implements the dynamic gap model published in "Dynamic Gaps Selector: +// A Smith Waterman Sequence Alignment Algorithm with Affine Gap Model +// Optimization" by Gianvito Urgese et al. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_ALIGN_DP_CELL_DYNAMIC_H_ +#define INCLUDE_SEQAN_ALIGN_DP_CELL_DYNAMIC_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction GetFlagMaskType +// ---------------------------------------------------------------------------- + +namespace impl +{ +namespace dp_cell +{ +template +struct FlagMaskType +{ + using Type = typename If >, + TScoreValue, + uint8_t>::Type; +}; +} // namespace dp_cell +} // namespace impl + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +struct DynamicGapExtensionHorizontal_; +typedef Tag DynamicGapExtensionHorizontal; + +struct DynamicGapExtensionVertical_; +typedef Tag DynamicGapExtensionVertical; + +enum DynamicGapsMask +{ + MASK_VERTICAL_GAP = 1, + MASK_HORIZONTAL_GAP = 2 +}; + +// ---------------------------------------------------------------------------- +// Class DPCell [DynamicGaps] +// ---------------------------------------------------------------------------- + +// The specialization for linear gap cost function. +// It solely stores the maximal score. +template +class DPCell_ +{ +public: + using TFlagMaskType = typename impl::dp_cell::FlagMaskType::Type; + + TScoreValue _score = DPCellDefaultInfinity::VALUE; + TFlagMaskType _flagMask = TFlagMaskType(); + + DPCell_() = default; + + // Copy c'tor. + DPCell_(DPCell_ const & other) : _score(other._score), _flagMask(other._flagMask) + {} + + // Move c'tor. + DPCell_(DPCell_ && other) : DPCell_() + { + swap(*this, other); + } + + // Construct with score. + DPCell_(TScoreValue const & pScore) : _score(pScore) + {} + + // Assignment and move operator. + DPCell_& operator=(DPCell_ other) + { + swap(*this, other); + return *this; + } + + // Assignment of score. + DPCell_ & + operator=(TScoreValue const & score) + { + _score = score; + return *this; + } + + ~DPCell_() = default; +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +template +struct SetGapExtension; + +template +struct SetGapExtension, False, False> +{ + static const char VALUE = 0; +}; + +template +struct SetGapExtension, False, True> +{ + static const char VALUE = MASK_HORIZONTAL_GAP; +}; + +template +struct SetGapExtension, True, False> +{ + static const char VALUE = MASK_VERTICAL_GAP; +}; + +template +struct SetGapExtension, True, True> +{ + static const char VALUE = MASK_HORIZONTAL_GAP | MASK_VERTICAL_GAP; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +template +inline void _setBit(DPCell_ & cell, + TFlag const & /*flag*/, + DynamicGapExtensionVertical const & /*tag*/) +{ + if (IsSameType::VALUE) + cell._flagMask |= MASK_VERTICAL_GAP; + else + cell._flagMask &= ~MASK_VERTICAL_GAP; +} + +template +inline void _setBit(DPCell_ & cell, + TFlag const & /*flag*/, + DynamicGapExtensionHorizontal const & /*tag*/) +{ + if (IsSameType::VALUE) + cell._flagMask |= MASK_HORIZONTAL_GAP; + else + cell._flagMask &= ~MASK_HORIZONTAL_GAP; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >,bool) +isGapExtension(DPCell_ const & cell, + TSpec const & /*spec*/) +{ + if (IsSameType::VALUE) + return cell._flagMask & MASK_HORIZONTAL_GAP; + else + return cell._flagMask & MASK_VERTICAL_GAP; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >,TScoreValue) +isGapExtension(DPCell_ const & cell, + TSpec const & /*spec*/) +{ + return blend(cell._flagMask & createVector(MASK_VERTICAL_GAP), + cell._flagMask & createVector(MASK_HORIZONTAL_GAP), + createVector(IsSameType::VALUE)); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, void) +setGapExtension(DPCell_ & cell, + TFlagV const & /*vert*/, TFlagH const & /*hori*/) +{ + cell._flagMask = SetGapExtension, TFlagV, TFlagH>::VALUE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +setGapExtension(DPCell_ & cell, + TFlagV const & /*vert*/, TFlagH const & /*hori*/, + TScoreValue const & cmp) +{ + cell._flagMask = blend(cell._flagMask, createVector(SetGapExtension, TFlagV, TFlagH>::VALUE), cmp); +} + +// ---------------------------------------------------------------------------- +// Function operator<() +// ---------------------------------------------------------------------------- + +// Needed for banded chain alignment for the std::set. +template +inline bool operator<(DPCell_ const & left, + DPCell_ const & right) +{ + return left._score < right._score; +} + +template +inline void +swap(DPCell_ & lhs, + DPCell_ & rhs) +{ + std::swap(lhs._score, rhs._score); + std::swap(lhs._flagMask, rhs._flagMask); +} + +} // namespace seqan + +#endif // INCLUDE_SEQAN_ALIGN_DP_CELL_DYNAMIC_H_ diff --git a/seqan/align/dp_cell_linear.h b/seqan/align/dp_cell_linear.h new file mode 100644 index 0000000..1a46fbe --- /dev/null +++ b/seqan/align/dp_cell_linear.h @@ -0,0 +1,125 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Implements the DPCell for linear gap cost functions. This requires only +// one matrix, such that we only need to store one score value per matrix +// entry. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_CELL_LINEAR_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_CELL_LINEAR_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + + +// ---------------------------------------------------------------------------- +// Class DPCell [LinearGaps] +// ---------------------------------------------------------------------------- + +// The specialization for linear gap cost function. +// It solely stores the maximal score. +template +class DPCell_ +{ +public: + TScoreValue _score = DPCellDefaultInfinity::VALUE; + + DPCell_() = default; + + // Copy c'tor. + DPCell_(DPCell_ const & other) : _score(other._score) + {} + + // Move c'tor. + DPCell_(DPCell_ && other) : DPCell_() + { + swap(*this, other); + } + + // Assignment & move operator + DPCell_& operator=(DPCell_ other) + { + swap(*this, other); + return *this; + } + + // Assignment of score. + DPCell_ & + operator=(TScoreValue const & score) + { + _score = score; + return *this; + } + + ~DPCell_() = default; +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function operator<() +// ---------------------------------------------------------------------------- + +// Needed for banded chain alignment for the std::set. +template +inline bool operator<(DPCell_ const & left, + DPCell_ const & right) +{ + return left._score < right._score; +} + +template +inline void +swap(DPCell_ & lhs, + DPCell_ & rhs) +{ + std::swap(lhs._score, rhs._score); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_CELL_LINEAR_H_ diff --git a/seqan/align/dp_context.h b/seqan/align/dp_context.h new file mode 100644 index 0000000..3049369 --- /dev/null +++ b/seqan/align/dp_context.h @@ -0,0 +1,187 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Implements the context that can be passed to the dp functions in order +// to reuse memory blocks in mutliple calls of the same function. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_ALIGN_DP_CONTEXT_H_ +#define INCLUDE_SEQAN_ALIGN_DP_CONTEXT_H_ + +namespace seqan +{ + +// ============================================================================ +// Forwards +// ============================================================================ + +template +struct GetDPScoreMatrix +{}; + +template +struct GetDPTraceMatrix +{}; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +template +struct DPContext +{ + typedef typename GetDPScoreMatrix::Type TScoreMatrixHost; + typedef typename GetDPTraceMatrix::Type TTraceMatrixHost; + + TScoreMatrixHost _scoreMatrix; + TTraceMatrixHost _traceMatrix; + + DPContext() : _scoreMatrix(), _traceMatrix() + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction GetDPScoreMatrix +// ---------------------------------------------------------------------------- + +template +struct GetDPScoreMatrix > +{ + typedef DPCell_ TDPScoreValue_; + typedef DPMatrix_ TDPScoreMatrix_; + + typedef typename Host::Type Type; +}; + +template +struct GetDPScoreMatrix const > +{ + typedef DPCell_ TDPScoreValue_; + typedef DPMatrix_ TDPScoreMatrix_; + + typedef typename Host::Type const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction GetDPTraceMatrix +// ---------------------------------------------------------------------------- + +template +struct GetDPTraceMatrix > +{ + typedef typename TraceBitMap_::Type TTraceValue_; + typedef DPMatrix_ TDPScoreMatrix_; + + typedef typename Host::Type Type; +}; + +template +struct GetDPTraceMatrix const > +{ + typedef typename TraceBitMap_::Type TTraceValue_; + typedef DPMatrix_ TDPScoreMatrix_; + + typedef typename Host::Type const Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function dpScoreMatrix() +// ---------------------------------------------------------------------------- + +template +inline typename GetDPScoreMatrix >::Type & +getDpScoreMatrix(DPContext & dpContext) +{ + return dpContext._scoreMatrix; +} + +template +inline typename GetDPScoreMatrix const >::Type & +getDpScoreMatrix(DPContext const & dpContext) +{ + return dpContext._scoreMatrix; +} + +// ---------------------------------------------------------------------------- +// Function dpTraceMatrix() +// ---------------------------------------------------------------------------- + +template +inline typename GetDPTraceMatrix >::Type & +getDpTraceMatrix(DPContext & dpContext) +{ + return dpContext._traceMatrix; +} + +template +inline typename GetDPTraceMatrix const >::Type & +getDpTraceMatrix(DPContext const & dpContext) +{ + return dpContext._traceMatrix; +} + +// ---------------------------------------------------------------------------- +// Function setDpScoreMatrix() +// ---------------------------------------------------------------------------- + +template +inline void +setDpTraceMatrix(DPContext & dpContext, + typename GetDPScoreMatrix >::Type const & scoreMatrix) +{ + dpContext._scoreMatrix = scoreMatrix; +} + +// ---------------------------------------------------------------------------- +// Function setDpTraceMatrix() +// ---------------------------------------------------------------------------- + +template +inline void +setDpTraceMatrix(DPContext & dpContext, + typename GetDPTraceMatrix >::Type const & traceMatrix) +{ + dpContext._tarceMatrix = traceMatrix; +} + +} + +#endif // INCLUDE_SEQAN_ALIGN_DP_CONTEXT_H_ diff --git a/seqan/align/dp_formula.h b/seqan/align/dp_formula.h new file mode 100644 index 0000000..9ecd0ab --- /dev/null +++ b/seqan/align/dp_formula.h @@ -0,0 +1,220 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Defines the recursion formula for the dp-alignment algorithms. +// ========================================================================== + +// TODO(holtgrew): Documentation in this header necessary or internal only? + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_FORMULA_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_FORMULA_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Tag RecursionDirectionDiagonal +// ---------------------------------------------------------------------------- + +struct RecursionDirectionDiagonal_; +typedef Tag RecursionDirectionDiagonal; + +// ---------------------------------------------------------------------------- +// Tag RecursionDirectionHorizontal +// ---------------------------------------------------------------------------- + +struct RecursionDirectionHorizontal_; +typedef Tag RecursionDirectionHorizontal; + +// ---------------------------------------------------------------------------- +// Tag RecursionDirectionVertical +// ---------------------------------------------------------------------------- + +struct RecursionDirectionVertical_; +typedef Tag RecursionDirectionVertical; + +// ---------------------------------------------------------------------------- +// Tag RecursionDirectionAll +// ---------------------------------------------------------------------------- + +struct RecursionDirectionAll_; +typedef Tag RecursionDirectionAll; + +// ---------------------------------------------------------------------------- +// Tag RecursionDirectionUpperDiagonal +// ---------------------------------------------------------------------------- + +struct RecursionDirectionUpperDiagonal_; +typedef Tag RecursionDirectionUpperDiagonal; + +// ---------------------------------------------------------------------------- +// Tag RecursionDirectionLowerDiagonal +// ---------------------------------------------------------------------------- + +struct RecursionDirectionLowerDiagonal_; +typedef Tag RecursionDirectionLowerDiagonal; + +// ---------------------------------------------------------------------------- +// Tag RecursionDirectionZero +// ---------------------------------------------------------------------------- + +struct RecursionDirectionZero_; +typedef Tag RecursionDirectionZero; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _computeScore +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_computeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + TRecursionDirection const & recDir, + TDPProfile const & dpProfile) +{ + typedef typename TraceBitMap_::Type TTraceValue; + + TTraceValue traceDir = _doComputeScore(activeCell, previousDiagonal, previousHorizontal, previousVertical, seqHVal, + seqVVal, scoringScheme, recDir, dpProfile); + if (IsLocalAlignment_::VALUE) + if (activeCell._score <= 0) + { + _setScoreOfCell(activeCell, static_cast(0)); + _setHorizontalScoreOfCell(activeCell, static_cast(0)); + _setVerticalScoreOfCell(activeCell, static_cast(0)); + return TraceBitMap_::NONE; + } + + return traceDir; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_computeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + TRecursionDirection const & recDir, + TDPProfile const & dpProfile) +{ + typedef typename TraceBitMap_::Type TTraceValue; + + TTraceValue traceDir = _doComputeScore(activeCell, previousDiagonal, previousHorizontal, previousVertical, seqHVal, + seqVVal, scoringScheme, recDir, dpProfile); + if (IsLocalAlignment_::VALUE) + { + TScoreValue cmp = cmpGt(createVector(1), activeCell._score); + _setScoreOfCell(activeCell, TraceBitMap_::NONE, cmp); + _setHorizontalScoreOfCell(activeCell, TraceBitMap_::NONE, cmp); + _setVerticalScoreOfCell(activeCell, TraceBitMap_::NONE, cmp); + return blend(traceDir, TraceBitMap_::NONE, cmp); + } + + return traceDir; +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionDirectionDiagonal] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & /*previousHorizontal*/, + DPCell_ const & /*previousVertical*/, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionDiagonal const &, + TDPProfile const &) +{ + activeCell._score = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + setGapExtension(activeCell, False(), False(), createVector(-1)); + + if (!IsTracebackEnabled_::VALUE) + return TraceBitMap_::NONE; + + return TraceBitMap_::DIAGONAL; +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionDirectionZero] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & /*previousDiagonal*/, + DPCell_ const & /*previousHorizontal*/, + DPCell_ const & /*previousVertical*/, + TSequenceHValue const & /*seqHVal*/, + TSequenceVValue const & /*seqVVal*/, + TScoringScheme const & /*scoringScheme*/, + RecursionDirectionZero const &, + DPProfile_ const &) +{ + _scoreOfCell(activeCell) = createVector(0); + return TraceBitMap_::NONE; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_FORMULA_H_ diff --git a/seqan/align/dp_formula_affine.h b/seqan/align/dp_formula_affine.h new file mode 100644 index 0000000..2e22c0c --- /dev/null +++ b/seqan/align/dp_formula_affine.h @@ -0,0 +1,636 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Implements the affine gap cost functions. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_FORMULA_AFFINE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_FORMULA_AFFINE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _internalComputeScore [RecursionDirectionDiagonal, AffineGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL, + TTraceValueGap, + TracebackOff const &, + RecursionDirectionDiagonal const &) +{ + if(activeCell._score < rightCompare) + activeCell._score = rightCompare; + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL, + TTraceValueGap, + TracebackOff const &, + RecursionDirectionDiagonal const &) +{ + activeCell._score = blend(activeCell._score, rightCompare, cmpGt(rightCompare, activeCell._score)); + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL leftTrace, + TTraceValueGap gapTrace, + TracebackOn > const &, + RecursionDirectionDiagonal const &) +{ + if(activeCell._score <= rightCompare) + { + activeCell._score = rightCompare; + return TraceBitMap_::DIAGONAL | leftTrace; + } + return leftTrace | gapTrace; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL const & leftTrace, + TTraceValueGap const & gapTrace, + TracebackOn > const &, + RecursionDirectionDiagonal const &) +{ + TScoreValue cmp = cmpGt(activeCell._score, rightCompare); + activeCell._score = blend(rightCompare, activeCell._score, cmp); + return blend(TraceBitMap_::DIAGONAL | leftTrace, + leftTrace | gapTrace, + cmp); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL leftTrace, + TTraceValueGap gapTrace, + TracebackOn > const &, + RecursionDirectionDiagonal const &) +{ + if(activeCell._score < rightCompare) + { + activeCell._score = rightCompare; // Maximal score comes from diagonal. + return TraceBitMap_::DIAGONAL | leftTrace; // Return trace for Diagonal. + } + if (activeCell._score == rightCompare) // Maximal score comes from previous computed directions and diagonal. + return leftTrace | TraceBitMap_::DIAGONAL | gapTrace; // Return all directions inclusively the flag indicating max from gap. + return leftTrace | gapTrace; // Maximum comes from gap. Return gap value inclusively the flag indicating max from gap. +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL const & leftTrace, + TTraceValueGap const & gapTrace, + TracebackOn > const &, + RecursionDirectionDiagonal const &) +{ + TScoreValue cmpG = cmpGt(rightCompare, activeCell._score); + TScoreValue cmpE = cmpEq(rightCompare, activeCell._score); + TScoreValue result = leftTrace | gapTrace; + activeCell._score = blend(activeCell._score, rightCompare, cmpG); + result = blend(result, TraceBitMap_::DIAGONAL | leftTrace, cmpG); + return blend(result, leftTrace | TraceBitMap_::DIAGONAL | gapTrace, cmpE); +} + +// ---------------------------------------------------------------------------- +// Function _internalComputeScore [RecursionDirectionHorizontal, AffineGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL, + TTraceValueR, + TracebackOff const &, + RecursionDirectionHorizontal const &) +{ + if(activeCell._horizontalScore < rightCompare) + activeCell._score = activeCell._horizontalScore = rightCompare; + else + activeCell._score = activeCell._horizontalScore; + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL, + TTraceValueR, + TracebackOff const &, + RecursionDirectionHorizontal const &) +{ + TScoreValue cmp = cmpGt(rightCompare, activeCell._horizontalScore); + activeCell._horizontalScore = blend(activeCell._horizontalScore, rightCompare, cmp); + activeCell._score = activeCell._horizontalScore; + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL leftTrace, + TTraceValueR rightTrace, + TracebackOn > const &, + RecursionDirectionHorizontal const &) +{ + if(activeCell._horizontalScore < rightCompare) + { + activeCell._score = activeCell._horizontalScore = rightCompare; + return rightTrace; + } + activeCell._score = activeCell._horizontalScore; + return leftTrace; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL leftTrace, + TTraceValueR rightTrace, + TracebackOn > const &, + RecursionDirectionHorizontal const &) +{ + TScoreValue cmp = cmpGt(rightCompare, activeCell._horizontalScore); + activeCell._horizontalScore = blend(activeCell._horizontalScore, rightCompare, cmp); + activeCell._score = activeCell._horizontalScore; + return blend(leftTrace, rightTrace, cmp); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL leftTrace, + TTraceValueR rightTrace, + TracebackOn > const &, + RecursionDirectionHorizontal const &) +{ + if(activeCell._horizontalScore < rightCompare) + { + activeCell._score = activeCell._horizontalScore = rightCompare; + return rightTrace; + } + activeCell._score = activeCell._horizontalScore; + if (activeCell._horizontalScore == rightCompare) + return leftTrace | rightTrace; + return leftTrace; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL const & leftTrace, + TTraceValueR const & rightTrace, + TracebackOn > const &, + RecursionDirectionHorizontal const &) +{ + TScoreValue cmpG = cmpGt(rightCompare, activeCell._horizontalScore); + TScoreValue cmpE = cmpEq(rightCompare, activeCell._horizontalScore); + activeCell._horizontalScore = blend(activeCell._horizontalScore, rightCompare, cmpG); + activeCell._score = activeCell._horizontalScore; + + TScoreValue result = leftTrace; + result = blend(result, rightTrace, cmpG); + return blend(result, leftTrace | rightTrace, cmpE); +} + +// ---------------------------------------------------------------------------- +// Function _internalComputeScore [RecursionDirectionVertical, AffineGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL, + TTraceValueR, + TracebackOff const &, + RecursionDirectionVertical const &) +{ + if(activeCell._verticalScore < rightCompare) + activeCell._score = activeCell._verticalScore = rightCompare; + else + activeCell._score = activeCell._verticalScore; + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL, + TTraceValueR, + TracebackOff const &, + RecursionDirectionVertical const &) +{ + TScoreValue cmp = cmpGt(rightCompare, activeCell._verticalScore); + activeCell._verticalScore = blend(activeCell._verticalScore, rightCompare, cmp); + activeCell._score = activeCell._verticalScore; + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL leftTrace, + TTraceValueR rightTrace, + TracebackOn > const &, + RecursionDirectionVertical const &) +{ + if(activeCell._verticalScore < rightCompare) + { + activeCell._score = activeCell._verticalScore = rightCompare; + return rightTrace; + } + activeCell._score = activeCell._verticalScore; + return leftTrace; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL const & leftTrace, + TTraceValueR const & rightTrace, + TracebackOn > const &, + RecursionDirectionVertical const &) +{ + TScoreValue cmp = cmpGt(rightCompare, activeCell._verticalScore); + activeCell._verticalScore = blend(activeCell._verticalScore, rightCompare, cmp); + activeCell._score = activeCell._verticalScore; + return blend(leftTrace, rightTrace, cmp); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL leftTrace, + TTraceValueR rightTrace, + TracebackOn > const &, + RecursionDirectionVertical const &) +{ + if(activeCell._verticalScore < rightCompare) + { + activeCell._score = activeCell._verticalScore = rightCompare; + return rightTrace; + } + activeCell._score = activeCell._verticalScore; + if (activeCell._verticalScore == rightCompare) + return leftTrace | rightTrace; + return leftTrace; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL leftTrace, + TTraceValueR rightTrace, + TracebackOn > const &, + RecursionDirectionVertical const &) +{ + TScoreValue cmpG = cmpGt(rightCompare, activeCell._verticalScore); + TScoreValue cmpE = cmpEq(rightCompare, activeCell._verticalScore); + activeCell._verticalScore = blend(activeCell._verticalScore, rightCompare, cmpG); + activeCell._score = activeCell._verticalScore; + + TScoreValue result = leftTrace; + result = blend(result, rightTrace, cmpG); + return blend(result, leftTrace | rightTrace, cmpE); +} + +// ---------------------------------------------------------------------------- +// Function _internalComputeScore [Vertical vs Horizontal, AffineGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TracebackOff const &) +{ + if(activeCell._score < activeCell._horizontalScore) + activeCell._score = activeCell._horizontalScore; + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TracebackOff const &) +{ + activeCell._score = blend(activeCell._score, activeCell._horizontalScore, + cmpGt(activeCell._horizontalScore, activeCell._score)); + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TracebackOn > const &) +{ + if(activeCell._score < activeCell._horizontalScore) + { + activeCell._score = activeCell._horizontalScore; + return TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; + } + return TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TracebackOn > const &) +{ + TScoreValue cmp = cmpGt(activeCell._horizontalScore, activeCell._score); + activeCell._score = blend(activeCell._score, activeCell._horizontalScore, cmp); + return blend(TraceBitMap_::MAX_FROM_VERTICAL_MATRIX, + TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + cmp); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TracebackOn > const &) +{ + if(activeCell._score < activeCell._horizontalScore) + { + activeCell._score = activeCell._horizontalScore; + return TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; + } + if (activeCell._score == activeCell._horizontalScore) + return TraceBitMap_::MAX_FROM_VERTICAL_MATRIX | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; + return TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TracebackOn > const &) +{ + TScoreValue cmpG = cmpGt(activeCell._horizontalScore, activeCell._score); + TScoreValue cmpE = cmpEq(activeCell._horizontalScore, activeCell._score); + activeCell._score = blend(activeCell._score, activeCell._horizontalScore, cmpG); + + return blend(blend(TraceBitMap_::MAX_FROM_VERTICAL_MATRIX, + TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + cmpG), + TraceBitMap_::MAX_FROM_VERTICAL_MATRIX | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + cmpE); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionAllDirection, AffineGaps] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionAll const &, + DPProfile_ const &) +{ + typedef typename TraceBitMap_::Type TTraceValue; + + // Now we have to find a smart version to solve this problem. Which is not as easy I would think. + activeCell._horizontalScore = _horizontalScoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal); + TScoreValue tmpScore = _scoreOfCell(previousHorizontal) + scoreGapOpenHorizontal(scoringScheme, seqHVal, seqVVal); + TTraceValue tvGap = _internalComputeScore(activeCell, + tmpScore, + TraceBitMap_::HORIZONTAL, + TraceBitMap_::HORIZONTAL_OPEN, + TTracebackConfig(), + RecursionDirectionHorizontal()); + + // Now we can decide for the optimal score in horizontal score or not? + activeCell._verticalScore = _verticalScoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + tmpScore = _scoreOfCell(previousVertical) + scoreGapOpenVertical(scoringScheme, seqHVal, seqVVal); + tvGap |= _internalComputeScore(activeCell, + tmpScore, + TraceBitMap_::VERTICAL, + TraceBitMap_::VERTICAL_OPEN, + TTracebackConfig(), + RecursionDirectionVertical()); + + // Finds the maximum between the vertical and the horizontal matrix. Stores the flag for coming from a potential direction. + TTraceValue tvMax = _internalComputeScore(activeCell, TTracebackConfig()); // Stores from where the maximal score comes. + tmpScore = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, tmpScore, tvGap, tvMax, TTracebackConfig(), RecursionDirectionDiagonal()); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionUpperDiagonalDirection, AffineGaps] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & /*previousVertical*/, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionUpperDiagonal const &, + DPProfile_ const &) +{ + typedef typename TraceBitMap_::Type TTraceValue; + + activeCell._horizontalScore = _horizontalScoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal); + activeCell._verticalScore = DPCellDefaultInfinity >::VALUE; + TScoreValue tmpScore = _scoreOfCell(previousHorizontal) + scoreGapOpenHorizontal(scoringScheme, seqHVal, seqVVal); + TTraceValue tv = _internalComputeScore(activeCell, + tmpScore, + TraceBitMap_::HORIZONTAL, + TraceBitMap_::HORIZONTAL_OPEN, + TTracebackConfig(), + RecursionDirectionHorizontal()); + tmpScore = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, + tmpScore, + tv, + TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + TTracebackConfig(), + RecursionDirectionDiagonal()); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionDirectionLowerDiagonal, AffineGaps] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & /*previousHorizontal*/, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionLowerDiagonal const &, + DPProfile_ const &) +{ + typedef typename TraceBitMap_::Type TTraceValue; + + activeCell._verticalScore = _verticalScoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + TScoreValue tmpScore = _scoreOfCell(previousVertical) + scoreGapOpenVertical(scoringScheme, seqHVal, seqVVal); + + activeCell._horizontalScore = DPCellDefaultInfinity >::VALUE; + // This computes the difference between the vertical extend and vertical open. + TTraceValue tv = _internalComputeScore(activeCell, + tmpScore, + TraceBitMap_::VERTICAL, + TraceBitMap_::VERTICAL_OPEN, + TTracebackConfig(), + RecursionDirectionVertical()); + + // Up to here, activeCell stores the highest value of vertical or vertical open. + tmpScore = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, + tmpScore, + tv, + TraceBitMap_::MAX_FROM_VERTICAL_MATRIX, + TTracebackConfig(), + RecursionDirectionDiagonal()); // Now we have this problem. How do we determine if the max comes from the vertical distance. +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionHorizontalDirection] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & /*previousDiagonal*/, + DPCell_ const & previousHorizontal, + DPCell_ const & /*previousVertical*/, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionHorizontal const &, + DPProfile_ const &) +{ + TScoreValue tmpGapOpenHorizontal = _scoreOfCell(previousHorizontal) + scoreGapOpenHorizontal(scoringScheme, seqHVal, seqVVal); + activeCell._horizontalScore = _horizontalScoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal); + + activeCell._verticalScore = DPCellDefaultInfinity >::VALUE; + return _internalComputeScore(activeCell, + tmpGapOpenHorizontal, + TraceBitMap_::HORIZONTAL, + TraceBitMap_::HORIZONTAL_OPEN, + TTracebackConfig(), + RecursionDirectionHorizontal()) | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionVerticalDirection] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & /*previousDiagonal*/, + DPCell_ const & /*previousHorizontal*/, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionVertical const &, + DPProfile_ const &) +{ + TScoreValue tmpGapOpenVertical = _scoreOfCell(previousVertical) + scoreGapOpenVertical(scoringScheme, seqHVal, seqVVal); + activeCell._verticalScore = _verticalScoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + + // Here we distinguish between vertical and vertical open. + activeCell._horizontalScore = DPCellDefaultInfinity >::VALUE; + return _internalComputeScore(activeCell, + tmpGapOpenVertical, + TraceBitMap_::VERTICAL, + TraceBitMap_::VERTICAL_OPEN, + TTracebackConfig(), + RecursionDirectionVertical()) | TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_FORMULA_AFFINE_H_ diff --git a/seqan/align/dp_formula_dynamic.h b/seqan/align/dp_formula_dynamic.h new file mode 100644 index 0000000..1c8fe8b --- /dev/null +++ b/seqan/align/dp_formula_dynamic.h @@ -0,0 +1,689 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Implements the score function for dynamic gap costs published in +// "Dynamic Gaps Selector: A Smith Waterman Sequence Alignment Algorithm with +// Affine Gap Model Optimization" by Gianvito Urgese et al. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_ALIGN_DP_FORMULA_DYNAMIC_H_ +#define INCLUDE_SEQAN_ALIGN_DP_FORMULA_DYNAMIC_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _internalComputeScore [RecursionDirectionDiagonal, DynamicGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & diagCompare, + TTraceValueL, + TTraceValueGap, + TracebackOff const &, + RecursionDirectionDiagonal const &) +{ + if(_scoreOfCell(activeCell) < diagCompare) + { + activeCell._score = diagCompare; + setGapExtension(activeCell, False(), False()); + return TraceBitMap_::NONE; + } + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & diagCompare, + TTraceValueL, + TTraceValueGap, + TracebackOff const &, + RecursionDirectionDiagonal const &) +{ + TScoreValue cmp = cmpGt(diagCompare, _scoreOfCell(activeCell)); + activeCell._score = blend(activeCell._score, diagCompare, cmp); + setGapExtension(activeCell, False(), False(), cmp); + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & diagCompare, + TTraceValueL leftTrace, + TTraceValueGap gapTrace, + TracebackOn > const &, + RecursionDirectionDiagonal const &) +{ + if(_scoreOfCell(activeCell) <= diagCompare) + { + activeCell._score = diagCompare; + setGapExtension(activeCell, False(), False()); + return TraceBitMap_::DIAGONAL | leftTrace; + } + return leftTrace | gapTrace; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & diagCompare, + TTraceValueL const & leftTrace, + TTraceValueGap const & gapTrace, + TracebackOn > const &, + RecursionDirectionDiagonal const &) +{ + TScoreValue cmp = cmpGt(_scoreOfCell(activeCell), diagCompare); + activeCell._score = blend(diagCompare, activeCell._score, cmp); + setGapExtension(activeCell, False(), False(), cmp); + return blend(TraceBitMap_::DIAGONAL | leftTrace, + leftTrace | gapTrace, + cmp); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & diagCompare, + TTraceValueL leftTrace, + TTraceValueGap gapTrace, + TracebackOn > const &, + RecursionDirectionDiagonal const &) +{ + if(_scoreOfCell(activeCell) < diagCompare) + { + activeCell._score = diagCompare; // Maximal score comes from diagonal. + setGapExtension(activeCell, False(), False()); + return TraceBitMap_::DIAGONAL | leftTrace; // Return trace for Diagonal. + } + if (_scoreOfCell(activeCell) == diagCompare) // Maximal score comes from previous computed directions and diagonal. + return leftTrace | TraceBitMap_::DIAGONAL | gapTrace; // Return all directions inclusively the flag indicating max from gap. + + return leftTrace | gapTrace; // Maximum comes from gap. Return gap value inclusively the flag indicating max from gap. +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & diagCompare, + TTraceValueL const & leftTrace, + TTraceValueGap const & gapTrace, + TracebackOn > const &, + RecursionDirectionDiagonal const &) +{ + TScoreValue cmp = cmpGt(diagCompare, _scoreOfCell(activeCell)); + activeCell._score = blend(activeCell._score, diagCompare, cmp); + setGapExtension(activeCell, False(), False(), cmp); + return blend(blend(leftTrace | gapTrace, + TraceBitMap_::DIAGONAL | leftTrace, + cmp), + leftTrace | TraceBitMap_::DIAGONAL | gapTrace, + cmpEq(_scoreOfCell(activeCell), diagCompare)); +} + +// ---------------------------------------------------------------------------- +// Function _internalComputeScore [RecursionDirectionHorizontal, DynamicGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + DPCell_ const & prevCell, + TValueH const & valH, + TValueV const & valV, + TScore const & score, + TracebackOff const &, + RecursionDirectionHorizontal const &) +{ + if(!isGapExtension(prevCell, DynamicGapExtensionHorizontal())) + activeCell._score = _scoreOfCell(prevCell) + scoreGapOpenHorizontal(score, valH, valV); + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + DPCell_ const & prevCell, + TValueH const & valH, + TValueV const & valV, + TScore const & score, + TracebackOff const &, + RecursionDirectionHorizontal const &) +{ + activeCell._score = blend(_scoreOfCell(prevCell) + scoreGapOpenHorizontal(score, valH, valV), activeCell._score, + isGapExtension(prevCell, DynamicGapExtensionHorizontal())); + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + DPCell_ const & prevCell, + TValueH const & valH, + TValueV const & valV, + TScore const & score, + TracebackOn const &, + RecursionDirectionHorizontal const &) +{ + if (!isGapExtension(prevCell, DynamicGapExtensionHorizontal())) + { + activeCell._score = _scoreOfCell(prevCell) + scoreGapOpenHorizontal(score, valH, valV); + return TraceBitMap_::HORIZONTAL_OPEN; + } + return TraceBitMap_::HORIZONTAL; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + DPCell_ const & prevCell, + TValueH const & valH, + TValueV const & valV, + TScore const & score, + TracebackOn const &, + RecursionDirectionHorizontal const &) +{ + activeCell._score = blend(_scoreOfCell(prevCell) + scoreGapOpenHorizontal(score, valH, valV), activeCell._score, + isGapExtension(prevCell, DynamicGapExtensionHorizontal())); + return TraceBitMap_::HORIZONTAL; +} + +// ---------------------------------------------------------------------------- +// Function _internalComputeScore [RecursionDirectionVertical, DynamicGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + DPCell_ const & prevCell, + TValueH const & valH, + TValueV const & valV, + TScore const & score, + TracebackOff const &, + RecursionDirectionVertical const &) +{ + if(!isGapExtension(prevCell, DynamicGapExtensionVertical())) + activeCell._score = _scoreOfCell(prevCell) + scoreGapOpenVertical(score, valH, valV); + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + DPCell_ const & prevCell, + TValueH const & valH, + TValueV const & valV, + TScore const & score, + TracebackOff const &, + RecursionDirectionVertical const &) +{ + activeCell._score = blend(_scoreOfCell(prevCell) + scoreGapOpenVertical(score, valH, valV), activeCell._score, + isGapExtension(prevCell, DynamicGapExtensionVertical())); + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + DPCell_ const & prevCell, + TValueH const & valH, + TValueV const & valV, + TScore const & score, + TracebackOn const &, + RecursionDirectionVertical const &) +{ + if (!isGapExtension(prevCell, DynamicGapExtensionVertical())) + { + activeCell._score = _scoreOfCell(prevCell) + scoreGapOpenVertical(score, valH, valV); + return TraceBitMap_::VERTICAL_OPEN; + } + return TraceBitMap_::VERTICAL; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + DPCell_ const & prevCell, + TValueH const & valH, + TValueV const & valV, + TScore const & score, + TracebackOn const &, + RecursionDirectionVertical const &) +{ + TScoreValue cmp = isGapExtension(prevCell, DynamicGapExtensionVertical()); + activeCell._score = blend(_scoreOfCell(prevCell) + scoreGapOpenVertical(score, valH, valV), activeCell._score, cmp); + return blend(TraceBitMap_::VERTICAL_OPEN, + TraceBitMap_::VERTICAL, + cmp); +} + +// ---------------------------------------------------------------------------- +// Function _internalComputeScore [Vertical vs Horizontal, DynamicGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & horizontalComp, + TracebackOff const &) +{ + if(_scoreOfCell(activeCell) < horizontalComp) + { + activeCell._score = horizontalComp; + setGapExtension(activeCell, False(), True()); + return TraceBitMap_::NONE; + } + setGapExtension(activeCell, True(), False()); + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & horizontalComp, + TracebackOff const &) +{ + TScoreValue cmp = cmpGt(horizontalComp, _scoreOfCell(activeCell)); + activeCell._score = blend(activeCell._score, horizontalComp, cmp); + setGapExtension(activeCell, False(), True(), cmp); + setGapExtension(activeCell, True(), False(), cmpEq(cmp, TraceBitMap_::NONE)); + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & horizontalComp, + TracebackOn > const &) +{ + if(_scoreOfCell(activeCell) < horizontalComp) + { + activeCell._score = horizontalComp; + setGapExtension(activeCell, False(), True()); + return TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; + } + setGapExtension(activeCell, True(), False()); + return TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & horizontalComp, + TracebackOn > const &) +{ + TScoreValue cmp = cmpGt(horizontalComp, _scoreOfCell(activeCell)); + activeCell._score = blend(activeCell._score, horizontalComp, cmp); + setGapExtension(activeCell, False(), True(), cmp); + setGapExtension(activeCell, True(), False(), cmpEq(cmp, TraceBitMap_::NONE)); + return blend(TraceBitMap_::MAX_FROM_VERTICAL_MATRIX, + TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + cmp); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & horizontalComp, + TracebackOn > const &) +{ + if(_scoreOfCell(activeCell) < horizontalComp) + { + setGapExtension(activeCell, False(), True()); + activeCell._score = horizontalComp; + return TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; + } + if (_scoreOfCell(activeCell) == horizontalComp) + { + setGapExtension(activeCell, True(), True()); + return TraceBitMap_::MAX_FROM_VERTICAL_MATRIX | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; + } + setGapExtension(activeCell, True(), False()); + return TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & horizontalComp, + TracebackOn > const &) +{ + TScoreValue cmpG = cmpGt(horizontalComp, _scoreOfCell(activeCell)); + TScoreValue cmpE = cmpEq(horizontalComp, _scoreOfCell(activeCell)); + setGapExtension(activeCell, True(), False(), createVector(-1)); + setGapExtension(activeCell, False(), True(), cmpG); + setGapExtension(activeCell, True(), True(), cmpE); + + TScoreValue result = TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; + result = blend(result, + TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + cmpG); + return blend(result, + TraceBitMap_::MAX_FROM_VERTICAL_MATRIX + | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + cmpE); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionAllDirection, DynamicGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionAll const &, + DPProfile_ const &) +{ + typedef typename TraceBitMap_::Type TTraceValue; + typedef typename std::decay::type TCell; + + // Compute best alignment from either horizontal open or extension. + TCell tmpScore(_scoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal)); + TTraceValue tvGap = _internalComputeScore(tmpScore, previousHorizontal, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), RecursionDirectionHorizontal()); + + // Compute best alignment between vertical and vertical open gap. + activeCell._score = _scoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + tvGap |= _internalComputeScore(activeCell, previousVertical, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), RecursionDirectionVertical()); + + // Finds the maximum between the vertical and the horizontal matrix. Stores the flag for coming from a potential direction. + TTraceValue tvMax = _internalComputeScore(activeCell, tmpScore._score, TTracebackConfig()); // Stores from where the maximal score comes. + tmpScore._score = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, tmpScore._score, tvGap, tvMax, TTracebackConfig(), RecursionDirectionDiagonal()); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionAll const &, + DPProfile_ const &) +{ + typedef typename TraceBitMap_::Type TTraceValue; + typedef typename std::decay::type TCell; + + // Compute best alignment from either horizontal open or extension. + TCell tmpScore = {_scoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal), + typename TCell::TFlagMaskType()}; + TTraceValue tvGap = _internalComputeScore(tmpScore, previousHorizontal, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), RecursionDirectionHorizontal()); + + // Compute best alignment between vertical and vertical open gap. + activeCell._score = _scoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + tvGap |= _internalComputeScore(activeCell, previousVertical, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), RecursionDirectionVertical()); + + // Finds the maximum between the vertical and the horizontal matrix. Stores the flag for coming from a potential direction. + TTraceValue tvMax = _internalComputeScore(activeCell, tmpScore._score, TTracebackConfig()); // Stores from where the maximal score comes. + tmpScore._score = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, tmpScore._score, tvGap, tvMax, TTracebackConfig(), RecursionDirectionDiagonal()); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionUpperDiagonalDirection, DynamicGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & /*previousVertical*/, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionUpperDiagonal const &, + DPProfile_ const &) +{ + typedef typename TraceBitMap_::Type TTraceValue; + + // This computes the difference between the horizontal extend and horizontal open. + activeCell._score = _scoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal); + TTraceValue tv = _internalComputeScore(activeCell, previousHorizontal, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), RecursionDirectionHorizontal()); + + setGapExtension(activeCell, False(), True()); + TScoreValue tmpScore = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, tmpScore, tv, TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + TTracebackConfig(),RecursionDirectionDiagonal()); +} + + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & /*previousVertical*/, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionUpperDiagonal const &, + DPProfile_ const &) +{ + typedef typename TraceBitMap_::Type TTraceValue; + + // This computes the difference between the horizontal extend and horizontal open. + activeCell._score = _scoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal); + TTraceValue tv = _internalComputeScore(activeCell, previousHorizontal, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), RecursionDirectionHorizontal()); + + setGapExtension(activeCell, False(), True(), createVector(-1)); + TScoreValue tmpScore = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, + tmpScore, + tv, + TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + TTracebackConfig(), + RecursionDirectionDiagonal()); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionDirectionLowerDiagonal, DynamicGaps] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & /*previousHorizontal*/, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionLowerDiagonal const &, + DPProfile_ const &) +{ + typedef typename TraceBitMap_::Type TTraceValue; + + // This computes the difference between the vertical extend and vertical open. + activeCell._score = _scoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + TTraceValue tv = _internalComputeScore(activeCell, previousVertical, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), RecursionDirectionVertical()); + setGapExtension(activeCell, True(), False()); + TScoreValue tmpScore = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, tmpScore, tv, TraceBitMap_::MAX_FROM_VERTICAL_MATRIX, + TTracebackConfig(), RecursionDirectionDiagonal()); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & /*previousHorizontal*/, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionLowerDiagonal const &, + DPProfile_ const &) +{ + typedef typename TraceBitMap_::Type TTraceValue; + + // This computes the difference between the vertical extend and vertical open. + activeCell._score = _scoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + TTraceValue tv = _internalComputeScore(activeCell, previousVertical, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), RecursionDirectionVertical()); + setGapExtension(activeCell, True(), False(), createVector(-1)); + TScoreValue tmpScore = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, + tmpScore, + tv, + TraceBitMap_::MAX_FROM_VERTICAL_MATRIX, + TTracebackConfig(), + RecursionDirectionDiagonal()); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionHorizontalDirection] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & /*previousDiagonal*/, + DPCell_ const & previousHorizontal, + DPCell_ const & /*previousVertical*/, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionHorizontal const & tag, + DPProfile_ const &) +{ + activeCell._score = _scoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal); + setGapExtension(activeCell, False(), True()); + return _internalComputeScore(activeCell, previousHorizontal, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), tag) | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & /*previousDiagonal*/, + DPCell_ const & previousHorizontal, + DPCell_ const & /*previousVertical*/, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionHorizontal const & tag, + DPProfile_ const &) +{ + activeCell._score = _scoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal); + setGapExtension(activeCell, False(), True(), createVector(-1)); + return _internalComputeScore(activeCell, previousHorizontal, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), tag) | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionVerticalDirection] +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & /*previousDiagonal*/, + DPCell_ const & /*previousHorizontal*/, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionVertical const & tag, + DPProfile_ const &) +{ + activeCell._score = _scoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + setGapExtension(activeCell, True(), False()); + return _internalComputeScore(activeCell, previousVertical, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), tag) | TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & /*previousDiagonal*/, + DPCell_ const & /*previousHorizontal*/, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionVertical const & tag, + DPProfile_ const &) +{ + activeCell._score = _scoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + setGapExtension(activeCell, True(), False(), createVector(-1)); + return _internalComputeScore(activeCell, previousVertical, seqHVal, seqVVal, scoringScheme, + TTracebackConfig(), tag) | TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; +} + +} // namespace seqan + +#endif // INCLUDE_SEQAN_ALIGN_DP_FORMULA_DYNAMIC_H_ diff --git a/seqan/align/dp_formula_linear.h b/seqan/align/dp_formula_linear.h new file mode 100644 index 0000000..45ed936 --- /dev/null +++ b/seqan/align/dp_formula_linear.h @@ -0,0 +1,291 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Defines the methods to compute the score when using linear gap costs. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_FORMULA_LINEAR_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_FORMULA_LINEAR_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _internalComputeScore() +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL, + TTraceValueR, + TracebackOff const &) +{ + if (activeCell._score < rightCompare) + activeCell._score = rightCompare; + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL, + TTraceValueR, + TracebackOff const &) +{ + TScoreValue cmp = cmpGt(rightCompare, activeCell._score); + activeCell._score = blend(activeCell._score, rightCompare, cmp); + return TraceBitMap_::NONE; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL leftTrace, + TTraceValueR rightTrace, + TracebackOn > const &) +{ + if (activeCell._score < rightCompare) + { + activeCell._score = rightCompare; + return rightTrace; + } + return leftTrace; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL const & leftTrace, + TTraceValueR const & rightTrace, + TracebackOn > const &) +{ + TScoreValue cmp = cmpGt(rightCompare, activeCell._score); + activeCell._score = blend(activeCell._score, rightCompare, cmp); + return blend(leftTrace, rightTrace, cmp); +} + +template + inline SEQAN_FUNC_ENABLE_IF(Not > >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL leftTrace, + TTraceValueR rightTrace, + TracebackOn > const &) +{ + if (activeCell._score < rightCompare) + { + activeCell._score = rightCompare; + return rightTrace; + } + return (activeCell._score == rightCompare) ? (rightTrace | leftTrace) : (leftTrace); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename TraceBitMap_::Type) +_internalComputeScore(DPCell_ & activeCell, + TScoreValue const & rightCompare, + TTraceValueL const & leftTrace, + TTraceValueR const & rightTrace, + TracebackOn > const &) +{ + // Check for greater values. + TScoreValue cmp = cmpGt(activeCell._score, rightCompare); // cmp greater + activeCell._score = blend(rightCompare, activeCell._score, cmp); // activeCell._score + + // Check for equality. + return blend(blend(rightTrace, leftTrace, cmp), leftTrace | rightTrace, cmpEq(rightCompare, activeCell._score)); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionDirectionAll, LinearGaps] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionAll const &, + DPProfile_ const &) +{ + typedef typename TraceBitMap_::Type TTraceValue; + activeCell._score = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + + TScoreValue tmpScore = _scoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + + TTraceValue tv = _internalComputeScore(activeCell, + tmpScore, + TraceBitMap_::DIAGONAL, + TraceBitMap_::VERTICAL | TraceBitMap_::MAX_FROM_VERTICAL_MATRIX, + TTracebackConfig()); + tmpScore = _scoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, + tmpScore, + tv, + TraceBitMap_::HORIZONTAL | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + TTracebackConfig()); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionDirectionUpperDiagonal, LinearGaps] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & /*previousVertical*/, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionUpperDiagonal const &, + DPProfile_ const &) +{ + activeCell._score = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + TScoreValue tmpScore = _scoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal); + return _internalComputeScore(activeCell, + tmpScore, + TraceBitMap_::DIAGONAL, + TraceBitMap_::HORIZONTAL | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX, + TTracebackConfig()); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionDirectionLowerDiagonal, LinearGaps] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & /*previousHorizontal*/, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionLowerDiagonal const &, + DPProfile_ const &) +{ + activeCell._score = _scoreOfCell(previousDiagonal) + score(scoringScheme, seqHVal, seqVVal); + TScoreValue tmpScore = _scoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + + return _internalComputeScore(activeCell, + tmpScore, + TraceBitMap_::DIAGONAL, + TraceBitMap_::VERTICAL | TraceBitMap_::MAX_FROM_VERTICAL_MATRIX, + TTracebackConfig()); +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionDirectionHorizontal] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & /*previousDiagonal*/, + DPCell_ const & previousHorizontal, + DPCell_ const & /*previousVertical*/, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionHorizontal const &, + DPProfile_ const &) +{ + activeCell._score = _scoreOfCell(previousHorizontal) + scoreGapExtendHorizontal(scoringScheme, seqHVal, seqVVal); + + if (!IsTracebackEnabled_::VALUE) + return TraceBitMap_::NONE; + + return TraceBitMap_::HORIZONTAL + | TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX; +} + +// ---------------------------------------------------------------------------- +// Function _doComputeScore [RecursionDirectionVertical] +// ---------------------------------------------------------------------------- + +template +inline typename TraceBitMap_::Type +_doComputeScore(DPCell_ & activeCell, + DPCell_ const & /*previousDiagonal*/, + DPCell_ const & /*previousHorizontal*/, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + RecursionDirectionVertical const &, + DPProfile_ const &) +{ + activeCell._score = _scoreOfCell(previousVertical) + scoreGapExtendVertical(scoringScheme, seqHVal, seqVVal); + + if (!IsTracebackEnabled_::VALUE) + return TraceBitMap_::NONE; + + return TraceBitMap_::VERTICAL + | TraceBitMap_::MAX_FROM_VERTICAL_MATRIX; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_FORMULA_LINEAR_H_ diff --git a/seqan/align/dp_matrix.h b/seqan/align/dp_matrix.h new file mode 100644 index 0000000..1e853c5 --- /dev/null +++ b/seqan/align/dp_matrix.h @@ -0,0 +1,644 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Ren� Rahn +// ========================================================================== +// This file implements the class DPMatrix and its specialization +// FullDPMatrix. The DPMatrix is a wrapper class around the Matrix +// class. Thus we can implement different specializations for the dp-matrix +// that are used through the different dp-algorithms. For example, we need +// a full dp matrix to store the traceback or the score for the Waterman- +// Eggert algorithm, while for the other dp-algorithms we only need one +// column vector to compute the scores. The default dp-matrix specialization +// can be selected using a special meta-function. +// ========================================================================== + +// TODO(holtgrew): Documentation in this header necessary or internal only? + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +template +struct DefaultScoreMatrixSpec_; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Tag MatrixMember +// ---------------------------------------------------------------------------- + +struct DPMatrixMember_; +typedef Tag DPMatrixMember; + +// ---------------------------------------------------------------------------- +// Tag SparseDPMatrix +// ---------------------------------------------------------------------------- + +struct SparseDPMatrix_; +typedef Tag SparseDPMatrix; + +// ---------------------------------------------------------------------------- +// Tag FullDPMatrix +// ---------------------------------------------------------------------------- + +struct FullDPMatrix_; +typedef Tag FullDPMatrix; + +// ---------------------------------------------------------------------------- +// Enum DPMatrixDimension +// ---------------------------------------------------------------------------- + +// Used to globally specify the correct dimension and the correct size of +// dimension for the dp matrix. +struct DPMatrixDimension_ +{ + typedef unsigned int TValue; + + static const TValue VERTICAL = 0u; + static const TValue HORIZONTAL = 1u; + static const TValue DIMENSION = 2u; +}; + +// ---------------------------------------------------------------------------- +// Class DPMatrix_ +// ---------------------------------------------------------------------------- + +// The dp matrix used as a score matrix and as a trace-back matrix. +template +class DPMatrix_ +{}; + + +// Default dp matrix implementation stores all cells of the dp matrix in the +// underlying two-dimensional matrix. +template +class DPMatrix_ +{ +public: + + typedef typename Member::Type THost; + + Holder data_host; // The host containing the actual matrix. + + DPMatrix_() : + data_host() + { + create(data_host); + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction DefaultScoreMatrixSpec_ +// ---------------------------------------------------------------------------- + +// This meta-function determines the default specialization of dp matrix +// based on the given algorithm tag. +template +struct DefaultScoreMatrixSpec_ +{ + typedef SparseDPMatrix Type; +}; + +// TODO(rmaerker): Move to WatermanEggert implementation? +template <> +struct DefaultScoreMatrixSpec_ > +{ + typedef FullDPMatrix Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction DataHost_ +// ---------------------------------------------------------------------------- + +// Returns the type of the underlying matrix. +template +struct Member, DPMatrixMember> +{ + typedef Matrix Type; +}; + +template +struct Member const, DPMatrixMember> +{ + typedef Matrix const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction SizeArr_ +// ---------------------------------------------------------------------------- + +// Returns the type of the containers to store the dimensions and the factors +// in order to move properly in the matrix. +template +struct SizeArr_ {}; + +template +struct SizeArr_ > +{ + typedef DPMatrix_ TDPMatrix_; + typedef typename Member::Type TDataHost_; + typedef typename SizeArr_::Type Type; +}; + +template +struct SizeArr_ const> +{ + typedef DPMatrix_ TDPMatrix_; + typedef typename Member::Type TDataHost_; + typedef typename SizeArr_::Type const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Spec +// ---------------------------------------------------------------------------- + +template +struct Spec > +{ + typedef TMatrixSpec Type; +}; + +template +struct Spec const>: + Spec >{}; + + +// ---------------------------------------------------------------------------- +// Metafunction Value +// ---------------------------------------------------------------------------- + +template +struct Value > +{ + typedef TValue Type; +}; + +template +struct Value const> +{ + typedef TValue const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Reference +// ---------------------------------------------------------------------------- + +template +struct Reference > +{ + typedef TValue & Type; +}; + +template +struct Reference const> +{ + typedef TValue const & Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction GetValue +// ---------------------------------------------------------------------------- + +template +struct GetValue >: + Reference >{}; + +template +struct GetValue const>: + Reference const>{}; + +// ---------------------------------------------------------------------------- +// Metafunction Position +// ---------------------------------------------------------------------------- + +template +struct Position > +{ + typedef typename DPMatrix_::THost TDataMatrix_; + typedef typename Position::Type Type; +}; + +template +struct Position const>: + Position >{}; + +// ---------------------------------------------------------------------------- +// Metafunction Size +// ---------------------------------------------------------------------------- + +template +struct Size > +{ + typedef typename DPMatrix_::THost TDataMatrix_; + typedef typename Size::Type Type; +}; + +template +struct Size const>: + Size >{}; + +// ---------------------------------------------------------------------------- +// Metafunction Host +// ---------------------------------------------------------------------------- + +template +struct Host > +{ + typedef DPMatrix_ TDPMatrix_; + typedef typename Member::Type TDataMatrix_; + typedef typename Host::Type Type; +}; + +template +struct Host const> +{ + typedef DPMatrix_ TDPMatrix_; + typedef typename Member::Type TDataMatrix_; + typedef typename Host::Type const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Iterator +// ---------------------------------------------------------------------------- + +// There are two iterator types. The standard iterator returns a +// non-rooted iterator to the underlying vector of the hosted two-dimensional +// matrix. The rooted iterator returns the iterator defined by the +// hosted matrix object which is a position iterator. +template +struct Iterator, Standard const> +{ + typedef DPMatrix_ TDPMatrix_; + typedef typename Host::Type THost_; + typedef typename Iterator::Type Type; +}; + +template +struct Iterator const, Standard const> +{ + typedef DPMatrix_ const TDPMatrix_; + typedef typename Host::Type THost_; + typedef typename Iterator::Type Type; +}; + +template +struct Iterator, Rooted const> +{ + typedef DPMatrix_ TDPMatrix_; + typedef typename Member::Type TDataMatrix_; + typedef typename Iterator::Type Type; +}; + +template +struct Iterator const, Rooted const> +{ + typedef DPMatrix_ TDPMatrix_; + typedef typename Member::Type TDataMatrix_; + typedef typename Iterator::Type Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _checkCorrectDimension() +// ---------------------------------------------------------------------------- + +// Checks whether a given value applies to the correct dimension. +inline bool _checkCorrectDimension(DPMatrixDimension_::TValue dim) +{ + return dim < DPMatrixDimension_::DIMENSION; +} + +// ---------------------------------------------------------------------------- +// Function _dataHost() +// ---------------------------------------------------------------------------- + +// Returns a reference to the hosted matrix. +template +inline Holder >::Type> & +_dataHost(DPMatrix_& dpMatrix) +{ + return _dataHost(value(dpMatrix.data_host)); +} + +template +inline Holder >::Type> const & +_dataHost(DPMatrix_ const & dpMatrix) +{ + return _dataHost(value(dpMatrix.data_host)); +} + +// ---------------------------------------------------------------------------- +// Function _dataLengths() +// ---------------------------------------------------------------------------- + +// Returns a reference to the _dataLengths container of the hosted matrix. +template +inline typename SizeArr_ >::Type & +_dataLengths(DPMatrix_&dpMatrix) +{ + return _dataLengths(value(dpMatrix.data_host)); +} + +template +inline typename SizeArr_ const>::Type & +_dataLengths(DPMatrix_ const & dpMatrix) +{ + return _dataLengths(value(dpMatrix.data_host)); +} + +// ---------------------------------------------------------------------------- +// Function _dataFactors() +// ---------------------------------------------------------------------------- + +// Returns a reference to the _dataFactors container of the hosted matrix. +template +inline typename SizeArr_ >::Type & +_dataFactors(DPMatrix_&dpMatrix) +{ + return _dataFactors(value(dpMatrix.data_host)); +} + +template +inline typename SizeArr_ const>::Type & +_dataFactors(DPMatrix_ const & dpMatrix) +{ + return _dataFactors(value(dpMatrix.data_host)); +} + +// ---------------------------------------------------------------------------- +// Function value() +// ---------------------------------------------------------------------------- + +// Returns the value of the matrix at the given host position. +template +inline typename Reference >::Type +value(DPMatrix_ & dpMatrix, + TPosition const & pos) +{ + return value(value(dpMatrix.data_host), pos); +} + +template +inline typename Reference const>::Type +value(DPMatrix_ const & dpMatrix, + TPosition const & pos) +{ + return value(value(dpMatrix.data_host), pos); +} + +// Returns the value of the matrix at the two given coordinates. +template +inline typename Reference >::Type +value(DPMatrix_ & dpMatrix, + TPositionV const & posDimV, + TPositionH const & posDimH) +{ + return value(value(dpMatrix.data_host), posDimV, posDimH); +} + +template +inline typename Reference const>::Type +value(DPMatrix_ const & dpMatrix, + TPositionV const & posDimV, + TPositionH const & posDimH) +{ + return value(value(dpMatrix.data_host), posDimV, posDimH); +} + +// ---------------------------------------------------------------------------- +// Function length() +// ---------------------------------------------------------------------------- + +// Returns the length of a given dimension. +template +inline typename Size const>::Type +length(DPMatrix_ const & dpMatrix, + unsigned int dimension) +{ + SEQAN_ASSERT(_checkCorrectDimension(dimension)); + + return length(value(dpMatrix.data_host), dimension); +} + +// Returns the overall length of the underlying vector of the hosted matrix. +template +inline typename Size const>::Type +length(DPMatrix_ const & dpMatrix) +{ + return length(value(dpMatrix.data_host)); // Note that even if the dimensional lengths are set but the matrix was not resized + // this function returns 0 or the previous length of the host before the resize. +} + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +template +inline void +clear(DPMatrix_ & dpMatrix) +{ + clear(_dataLengths(dpMatrix)); + resize(_dataLengths(dpMatrix), 2, 0); + clear(_dataFactors(dpMatrix)); + resize(_dataFactors(dpMatrix), 2, 0); + _dataFactors(dpMatrix)[DPMatrixDimension_::VERTICAL] = 1u; + clear(host(dpMatrix)); +} + +// ---------------------------------------------------------------------------- +// Function empty() +// ---------------------------------------------------------------------------- + +template +inline bool +empty(DPMatrix_ const & dpMatrix) +{ + return empty(host(dpMatrix)); +} + +// ---------------------------------------------------------------------------- +// Function setLength() +// ---------------------------------------------------------------------------- + +// Sets the new length of a given dimension. +template +inline void +setLength(DPMatrix_ & dpMatrix, + unsigned int dimension, + TSize const & newLength) +{ + SEQAN_ASSERT(_checkCorrectDimension(dimension)); + setLength(value(dpMatrix.data_host), dimension, newLength); +} + +// ---------------------------------------------------------------------------- +// Function updateFactors() +// ---------------------------------------------------------------------------- + +template +inline typename Size >::Type +updateFactors(DPMatrix_ & dpMatrix) +{ + typedef typename Size >::Type TSize; + + TSize factor_ = _dataFactors(dpMatrix)[0] * length(dpMatrix, 0); + for (unsigned int i = 1; (factor_ > 0) && (i < dimension(value(dpMatrix.data_host))); ++i) + { + _dataFactors(dpMatrix)[i] = factor_; + factor_ *= length(dpMatrix, i); + } + return factor_; +} + +// ---------------------------------------------------------------------------- +// Function resize() +// ---------------------------------------------------------------------------- + +// Resizes the matrix. Note, the lengths of the dimensions have to be set before. +template +inline void +resize(DPMatrix_ & dpMatrix) +{ + typedef typename Size >::Type TSize; + + TSize reqSize = updateFactors(dpMatrix); + if (reqSize >= length(dpMatrix)) + resize(host(dpMatrix), reqSize, Exact()); +} + +template +inline void +resize(DPMatrix_ & dpMatrix, + TValue const & fillValue) +{ + typedef typename Size >::Type TSize; + + TSize reqSize = updateFactors(dpMatrix); + if (reqSize >= length(dpMatrix)) + resize(host(dpMatrix), reqSize, fillValue, Exact()); +} + +// ---------------------------------------------------------------------------- +// Function begin() +// ---------------------------------------------------------------------------- + +template +inline typename Iterator, Standard const>::Type +begin(DPMatrix_ & dpMatrix, Standard const) +{ + return begin(host(dpMatrix)); +} + +template +inline typename Iterator const, Standard const>::Type +begin(DPMatrix_ const & dpMatrix, Standard const) +{ + return begin(host(dpMatrix)); +} + +template +inline typename Iterator, Rooted const>::Type +begin(DPMatrix_ & dpMatrix, Rooted const) +{ + return begin(value(dpMatrix.data_host)); +} + +template +inline typename Iterator const, Rooted const>::Type +begin(DPMatrix_ const & dpMatrix, Rooted const) +{ + return begin(value(dpMatrix.data_host)); +} + +// ---------------------------------------------------------------------------- +// Function end() +// ---------------------------------------------------------------------------- + +template +inline typename Iterator, Standard const>::Type +end(DPMatrix_ & dpMatrix, Standard const) +{ + return end(host(dpMatrix)); +} + +template +inline typename Iterator const, Standard const>::Type +end(DPMatrix_ const & dpMatrix, Standard const) +{ + return end(host(dpMatrix)); +} + +template +inline typename Iterator, Rooted const>::Type +end(DPMatrix_ & dpMatrix, Rooted const) +{ + return end(value(dpMatrix.data_host)); +} + +template +inline typename Iterator const, Rooted const>::Type +end(DPMatrix_ const & dpMatrix, Rooted const) +{ + return end(value(dpMatrix.data_host)); +} + +// ---------------------------------------------------------------------------- +// Function coordinate() +// ---------------------------------------------------------------------------- + +// Returns the coordinate of a host positio in a given dimension. +template +inline typename Position >::Type +coordinate(DPMatrix_ const & dpMatrix, + TPosition hostPos, + typename DPMatrixDimension_::TValue dimension) +{ + return coordinate(value(dpMatrix.data_host), hostPos, dimension); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_H_ diff --git a/seqan/align/dp_matrix_navigator.h b/seqan/align/dp_matrix_navigator.h new file mode 100644 index 0000000..a39100b --- /dev/null +++ b/seqan/align/dp_matrix_navigator.h @@ -0,0 +1,230 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Implements the DPMatrixNavigator. +// This is the parent class for all navigators that parse over a dp-matrix. +// This class facilitates the correct navigation through the dp-matrix for +// all kind of standard dp-algorithms. At the moment there only exists the +// NavigateColumnWise but this can be complemented by other navigation +// structures like anti-diagonals or in tiles. +// The Navigator can be specialized with three parameters. The first one is +// the used specialization of the dp-matrix (FullDPMatrix or SparseDPMatrix). +// the second parameter decides if it is a navigator for a score matrix or +// a trace matrix. And the last parameter determines the sort of navigation. +// ========================================================================== + +// TODO(holtgrew): Documentation in this header necessary or internal only? + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Tag DPScoreMatrix +// ---------------------------------------------------------------------------- + +// Used to select a navigator for the score matrix. +struct DPScoreMatrix_; +typedef Tag DPScoreMatrix; + +// ---------------------------------------------------------------------------- +// Tag DPTraceMatrix +// ---------------------------------------------------------------------------- + +// Used to select a navigator for the trace matrix. +template +struct DPTraceMatrix {}; + +// ---------------------------------------------------------------------------- +// Tag NavigateColumnWise +// ---------------------------------------------------------------------------- + +// Facilitates column wise navigation through the dp-matrix. +struct NavigateColumnWise_; +typedef Tag NavigateColumnWise; + +// ---------------------------------------------------------------------------- +// Class DPMatrixNavigator_ +// ---------------------------------------------------------------------------- + +template +class DPMatrixNavigator_; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Value +// ---------------------------------------------------------------------------- + +template +struct Value > +{ + typedef typename Value::Type Type; +}; + +template +struct Value const> +{ + typedef typename Value::Type Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Reference +// ---------------------------------------------------------------------------- + +template +struct Reference > +{ + typedef typename Reference::Type Type; +}; + +template +struct Reference const> +{ + typedef typename Reference::Type Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Container +// ---------------------------------------------------------------------------- + +template +struct Container > +{ + typedef TDPMatrix Type; +}; + +template +struct Container const> +{ + typedef TDPMatrix const Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function assignValue() +// ---------------------------------------------------------------------------- + +template +inline void +assignValue(DPMatrixNavigator_ & dpNavigator, + TValue const & element) +{ + assignValue(dpNavigator._activeColIterator, element); +} + +// ---------------------------------------------------------------------------- +// Function value() +// ---------------------------------------------------------------------------- + +template +inline typename Reference >::Type +value(DPMatrixNavigator_ & dpNavigator) +{ + return value(dpNavigator._activeColIterator); +} + +template +inline typename Reference const>::Type +value(DPMatrixNavigator_ const & dpNavigator) +{ + return value(dpNavigator._activeColIterator); +} + +template +inline typename Reference >::Type +value(DPMatrixNavigator_ & dpNavigator, + TCoordinateH const & coordinateV, + TCoordinateV const & coordinateH) +{ + return value(container(dpNavigator), coordinateV, coordinateH); +} + +template +inline typename Reference const>::Type +value(DPMatrixNavigator_ const & dpNavigator, + TCoordinateV const & coordinateV, + TCoordinateH const & coordinateH) +{ + return value(container(dpNavigator), coordinateV, coordinateH); +} + +// ---------------------------------------------------------------------------- +// Function coordinate() +// ---------------------------------------------------------------------------- + +template +inline typename DPMatrixDimension_::TValue +coordinate(DPMatrixNavigator_ const & dpNavigator, + typename DPMatrixDimension_::TValue const & dimension) +{ + // Simply delegate to coordinate of underlying matrix. + return coordinate(value(dpNavigator._ptrDataContainer), + dpNavigator._activeColIterator - begin(*dpNavigator._ptrDataContainer, Standard()), dimension); +} + +// ---------------------------------------------------------------------------- +// Function container() +// ---------------------------------------------------------------------------- + +template +inline typename Container >::Type & +container(DPMatrixNavigator_ & dpNavigator) +{ + return *dpNavigator._ptrDataContainer; +} + +template +inline typename Container const>::Type & +container(DPMatrixNavigator_ const & dpNavigator) +{ + return *dpNavigator._ptrDataContainer; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_H_ diff --git a/seqan/align/dp_matrix_navigator_score_matrix.h b/seqan/align/dp_matrix_navigator_score_matrix.h new file mode 100644 index 0000000..9110b49 --- /dev/null +++ b/seqan/align/dp_matrix_navigator_score_matrix.h @@ -0,0 +1,407 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// The navigator for the full score dp-matrix. We need two iterators over the +// current column and the previous column. We also store the three neighboring +// cells needed for the recursion formula. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_SCORE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_SCORE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class DPMatrixNavigator [FullDPMatrix, ScoreMatrix] +// ---------------------------------------------------------------------------- + +// The navigator for the score matrix. +// +// This navigator runs on a FullDPMatrix while it navigates column wise. +template +class DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> +{ +public: + typedef DPMatrix_ TDPMatrix_; + typedef typename Pointer_::Type TDPMatrixPointer_; + typedef typename Iterator::Type TDPMatrixIterator; + + TDPMatrixPointer_ _ptrDataContainer = nullptr; // Pointer to the matrix this navigator is working on. + int _laneLeap = 0; // Stores the jump to the next column + TDPMatrixIterator _activeColIterator = TDPMatrixIterator(); // The active column iterator. + TDPMatrixIterator _prevColIterator = TDPMatrixIterator(); // The previous column iterator. + TValue _prevCellDiagonal = TValue(); // The previous diagonal cell + TValue _prevCellHorizontal = TValue(); // The previous Horizontal cell + TValue _prevCellVertical = TValue(); // The previous Vertical cell +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _init() +// ---------------------------------------------------------------------------- + +// Initializes the navigator for an unbanded alignment. +template +inline void +_init(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & navigator, + DPMatrix_ & dpMatrix, + DPBandConfig const &) +{ + navigator._ptrDataContainer = &dpMatrix; + navigator._activeColIterator = begin(dpMatrix, Standard()); + navigator._prevColIterator = navigator._activeColIterator - _dataFactors(dpMatrix)[DPMatrixDimension_::HORIZONTAL]; + navigator._laneLeap = 1; + assignValue(navigator._activeColIterator, TValue()); +} + +// Initializes the navigator for a banded alignment. +template +inline void +_init(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & navigator, + DPMatrix_ & dpMatrix, + DPBandConfig const & band) +{ + typedef typename Size >::Type TMatrixSize; + typedef typename MakeSigned::Type TSignedSize; + navigator._ptrDataContainer = &dpMatrix; + + + // Band begins within the first row. + if (lowerDiagonal(band) >= 0) + { + navigator._laneLeap = _min(length(dpMatrix, DPMatrixDimension_::VERTICAL), bandSize(band)); + navigator._activeColIterator = begin(dpMatrix, Standard()) + _dataLengths(dpMatrix)[DPMatrixDimension_::VERTICAL] - 1; + } + else if (upperDiagonal(band) <= 0) // Band begins within the first column. + { + navigator._laneLeap = 1; + navigator._activeColIterator = begin(dpMatrix, Standard()); + } + else // Band intersects with the point of origin. + { + TMatrixSize lengthVertical = length(dpMatrix, DPMatrixDimension_::VERTICAL); + int lastPos = _max(-static_cast(lengthVertical - 1), lowerDiagonal(band)); + navigator._laneLeap = lengthVertical + lastPos; + navigator._activeColIterator = begin(dpMatrix, Standard()) + navigator._laneLeap - 1; + } + // Set previous iterator to same position, one column left. + navigator._prevColIterator = navigator._activeColIterator - _dataFactors(dpMatrix)[DPMatrixDimension_::HORIZONTAL]; + assignValue(navigator._activeColIterator, TValue()); +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [DPInitialColumn, FirstCell] +// ---------------------------------------------------------------------------- + +// In the initial column we don't need to do anything because, the navigagtor is already initialized. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & /*dpNavigator*/, + MetaColumnDescriptor const &, + FirstCell const &) +{ + // no-op +} + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & /*dpNavigator*/, + MetaColumnDescriptor const &, + FirstCell const &) +{ + // no-op +} + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & /*dpNavigator*/, + MetaColumnDescriptor const &, + FirstCell const &) +{ + // no-op +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [PartialColumnTop, FirstCell] +// ---------------------------------------------------------------------------- + +// We are in the banded case, where the band crosses the first row. +// The left cell of the active cell is not valid, beacause we only can come from horizontal direction. +// The lower left cell of the active cell is the horizontal direction. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + FirstCell const &) +{ + --dpNavigator._laneLeap; + dpNavigator._activeColIterator += dpNavigator._laneLeap; + dpNavigator._prevColIterator += dpNavigator._laneLeap; + dpNavigator._prevCellHorizontal = value(++dpNavigator._prevColIterator); +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [FullColumn, FirstCell] +// ---------------------------------------------------------------------------- + +// We are in the unbanded case or in the middle phase of the wide band. +// The left cell of the active cell represents horizontal direction. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + FirstCell const &) +{ + dpNavigator._activeColIterator += dpNavigator._laneLeap; + dpNavigator._prevColIterator += dpNavigator._laneLeap; + dpNavigator._prevCellHorizontal = value(dpNavigator._prevColIterator); +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [PartialColumnMiddle, PartialColumnBottom, FirstCell] +// ---------------------------------------------------------------------------- + +// We are in the banded case. +// The left cell of the active cell represents diagonal direction. The lower left diagonal represents the horizontal direction. + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + FirstCell const &) +{ + dpNavigator._activeColIterator += dpNavigator._laneLeap; + dpNavigator._prevColIterator += dpNavigator._laneLeap; + dpNavigator._prevCellDiagonal = value(dpNavigator._prevColIterator); + dpNavigator._prevCellHorizontal = value(++dpNavigator._prevColIterator); +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [DPInitialColumn, InnerCell] +// ---------------------------------------------------------------------------- + +// If we are in the initial column, we only need to represent the vertical direction. +// But we still have to update the previous column iterator. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + InnerCell const &) +{ + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; + ++dpNavigator._prevColIterator; // Do we have to increase the prevColIterator.... +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [AnyColumn, InnerCell] +// ---------------------------------------------------------------------------- + +// For any other column type and location we can use the same navigation procedure. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + InnerCell const &) +{ + dpNavigator._prevCellDiagonal = dpNavigator._prevCellHorizontal; + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + dpNavigator._prevCellHorizontal = value(++dpNavigator._prevColIterator); + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [DPInitialColumn, LastCell] +// ---------------------------------------------------------------------------- + +// If we are in the initial column we only need to represent the vertical direction. +// But we still have to update the previous column iterator. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; + ++dpNavigator._prevColIterator; +} + +// We need this function to avoid ambiguous function calls. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; + ++dpNavigator._prevColIterator; +} + +// We need this function to avoid ambiguous function calls. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; + ++dpNavigator._prevColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [FullColumn, LastCell] +// ---------------------------------------------------------------------------- + +// If we are in a full column the values correspond to standard dp directions. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellDiagonal = dpNavigator._prevCellHorizontal; + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + dpNavigator._prevCellHorizontal = value(++dpNavigator._prevColIterator); + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [PartialColumnBottom, LastCell] +// ---------------------------------------------------------------------------- + +// If we are in banded case and are the band crosses the last row, we have to update +// the additional leap for the current track. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellDiagonal = dpNavigator._prevCellHorizontal; + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + dpNavigator._prevCellHorizontal = value(++dpNavigator._prevColIterator); + ++dpNavigator._activeColIterator; + ++dpNavigator._laneLeap; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [PartialColumnTop & PartialColumnBottom, LastCell] +// ---------------------------------------------------------------------------- + +// If we are in the banded case the left cell of the active represents the diagonal direction. +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellDiagonal = dpNavigator._prevCellHorizontal; + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function previousCellDiagonal() +// ---------------------------------------------------------------------------- + +template +inline typename Reference >::Type +previousCellDiagonal(DPMatrixNavigator_ & dpNavigator) +{ + return dpNavigator._prevCellDiagonal; +} + +template +inline typename Reference const>::Type +previousCellDiagonal(DPMatrixNavigator_ const & dpNavigator) +{ + return dpNavigator._prevCellDiagonal; +} + +// ---------------------------------------------------------------------------- +// Function previousCellHorizontal() +// ---------------------------------------------------------------------------- + +template +inline typename Reference >::Type +previousCellHorizontal(DPMatrixNavigator_ & dpNavigator) +{ + return dpNavigator._prevCellHorizontal; +} + +template +inline typename Reference const>::Type +previousCellHorizontal(DPMatrixNavigator_ const & dpNavigator) +{ + return dpNavigator._prevCellHorizontal; +} + +// ---------------------------------------------------------------------------- +// Function previousCellVertical() +// ---------------------------------------------------------------------------- + +template +inline typename Reference >::Type +previousCellVertical(DPMatrixNavigator_ & dpNavigator) +{ + return dpNavigator._prevCellVertical; +} + +template +inline typename Reference const>::Type +previousCellVertical(DPMatrixNavigator_ const & dpNavigator) +{ + return dpNavigator._prevCellVertical; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_SCORE_H_ diff --git a/seqan/align/dp_matrix_navigator_score_matrix_sparse.h b/seqan/align/dp_matrix_navigator_score_matrix_sparse.h new file mode 100644 index 0000000..acc3267 --- /dev/null +++ b/seqan/align/dp_matrix_navigator_score_matrix_sparse.h @@ -0,0 +1,369 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// The navigator for the sparse score dp-matrix. This class also provides an +// iterator for the active and the previous column. It stores the neighbouring +// cells needed for the recursion formula. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_SCORE_SPARSE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_SCORE_SPARSE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class DPMatrixNavigator [SparseDPMatrix, ScoreMatrix] +// ---------------------------------------------------------------------------- + +// Specialization of the score matrix navigator for a sparse dp matrix. +template +class DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> +{ +public: + typedef DPMatrix_ TDPMatrix_; + typedef typename Pointer_::Type TDPMatrixPointer_; + typedef typename Iterator::Type TDPMatrixIterator; + + TDPMatrixPointer_ _ptrDataContainer = nullptr; // Pointer to the underlying matrix to navigate on. + int _laneLeap = 0; // The distance to leap when going to the next column. + TDPMatrixIterator _activeColIterator = TDPMatrixIterator(); // The iterator over the active column. + TDPMatrixIterator _prevColIterator = TDPMatrixIterator(); // The iterator over the previous column. + TValue _prevCellDiagonal = TValue(); // The previous value in diagonal direction. + TValue _prevCellHorizontal = TValue(); // The previous value in horizontal direction. + TValue _prevCellVertical = TValue(); // The previous value in vertical direction. +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _init() +// ---------------------------------------------------------------------------- + + +// Initializes the navigator for unbanded alignments +template +inline void +_init(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & navigator, + DPMatrix_ & dpMatrix, + DPBandConfig const &) +{ + navigator._ptrDataContainer = &dpMatrix; + navigator._activeColIterator = begin(dpMatrix, Standard()); + navigator._prevColIterator = navigator._activeColIterator; + navigator._laneLeap = 1 - _dataLengths(dpMatrix)[DPMatrixDimension_::VERTICAL]; + assignValue(navigator._activeColIterator, TValue()); +} + +// Initializes the navigator for banded alignments +template +inline void +_init(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & navigator, + DPMatrix_ & dpMatrix, + DPBandConfig const & band) +{ + typedef DPMatrix_ TSparseDPMatrix; + typedef typename Size::Type TSize; + typedef typename MakeSigned::Type TSignedSize; + navigator._ptrDataContainer = &dpMatrix; + + // Band begins within the first row. + if (lowerDiagonal(band) >= 0) + { + navigator._laneLeap = 0; + navigator._activeColIterator = begin(dpMatrix, Standard()) + length(dpMatrix, DPMatrixDimension_::VERTICAL) - 1; + } + else if (upperDiagonal(band) <= 0) // Band begins within the first column + { + navigator._laneLeap = 1 - _dataLengths(dpMatrix)[DPMatrixDimension_::VERTICAL]; + navigator._activeColIterator = begin(dpMatrix, Standard()); + } + else // Band intersects with the point of origin. + { + navigator._laneLeap = _max(lowerDiagonal(band), 1 - static_cast(length(dpMatrix, DPMatrixDimension_::VERTICAL))); + navigator._activeColIterator = begin(dpMatrix, Standard()) + length(dpMatrix, DPMatrixDimension_::VERTICAL) + navigator._laneLeap - 1; + } + navigator._prevColIterator = navigator._activeColIterator; + assignValue(navigator._activeColIterator, TValue()); +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [DPInitialColumn, PartialColumnTop, FirstCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & /*dpNavigator*/, + MetaColumnDescriptor const &, + FirstCell const &) +{ + // no-op +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [DPInitialColumn, FullColumn, FirstCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & /*dpNavigator*/, + MetaColumnDescriptor const &, + FirstCell const &) +{ + // no-op +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [DPInitialColumn, FirstCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & /*dpNavigator*/, + MetaColumnDescriptor const &, + FirstCell const &) +{ + // no-op +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [PartialColumnTop, FirstCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + FirstCell const &) +{ + --dpNavigator._laneLeap; + dpNavigator._activeColIterator += dpNavigator._laneLeap; + dpNavigator._prevColIterator = dpNavigator._activeColIterator; + dpNavigator._prevCellHorizontal = value(++dpNavigator._prevColIterator); +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [FullColumn, FirstCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + FirstCell const &) +{ + dpNavigator._activeColIterator += dpNavigator._laneLeap; + dpNavigator._prevCellHorizontal = value(dpNavigator._activeColIterator); +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [FirstCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + FirstCell const &) +{ + dpNavigator._activeColIterator += dpNavigator._laneLeap; + dpNavigator._prevColIterator = dpNavigator._activeColIterator; + dpNavigator._prevCellDiagonal = value(dpNavigator._prevColIterator); + dpNavigator._prevCellHorizontal = value(++dpNavigator._prevColIterator); +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [DPInitialColumn, InnerCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + InnerCell const &) +{ + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [DPInitialColumn, FullColumn, InnerCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + InnerCell const &) +{ + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [InnerCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + InnerCell const &) +{ + dpNavigator._prevCellDiagonal = dpNavigator._prevCellHorizontal; + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + dpNavigator._prevCellHorizontal = value(++dpNavigator._prevColIterator); + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [FullColumn, InnerCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + InnerCell const &) +{ + dpNavigator._prevCellDiagonal = dpNavigator._prevCellHorizontal; + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + dpNavigator._prevCellHorizontal = value(++dpNavigator._activeColIterator); +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [DPInitialColumn, LastCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [DPInitialColumn, PartialColumnBottom, LastCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [DPInitialColumn, FullColumn, LastCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [LastCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellDiagonal = dpNavigator._prevCellHorizontal; + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [PartialColumnBottom, LastCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellDiagonal = dpNavigator._prevCellHorizontal; + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + dpNavigator._prevCellHorizontal = value(++dpNavigator._prevColIterator); + ++dpNavigator._activeColIterator; + ++dpNavigator._laneLeap; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [FullColumn, LastCell] +// ---------------------------------------------------------------------------- + + +template +inline void +_goNextCell(DPMatrixNavigator_, DPScoreMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + dpNavigator._prevCellDiagonal = dpNavigator._prevCellHorizontal; + dpNavigator._prevCellVertical = value(dpNavigator._activeColIterator); + dpNavigator._prevCellHorizontal = value(++dpNavigator._activeColIterator); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_SCORE_SPARSE_H_ diff --git a/seqan/align/dp_matrix_navigator_trace_matrix.h b/seqan/align/dp_matrix_navigator_trace_matrix.h new file mode 100644 index 0000000..0fc7233 --- /dev/null +++ b/seqan/align/dp_matrix_navigator_trace_matrix.h @@ -0,0 +1,517 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// This specialization is used to navigate through the traceback matrix +// of any standard dp-alignment algorithm. The DPTraceMatrix gets the +// traceback flag TracebackOn or TracebackOff. A traceback is only computed +// if the traceback is switched on. If this is not the case, the void +// functions will be compiled as no-op functions, while in functions that try +// to access a value of the underlying matrix via the navigator an assertion +// is thrown. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_TRACE_MATRIX_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_TRACE_MATRIX_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class DPMatrixNavigator [FullDPMatrix, DPTraceMatrix] +// ---------------------------------------------------------------------------- + +// The matrix navigator for the trace-back matrix. +// +// It takes three types to be specialized. The first type defines the underlying +// dp-matrix it is working on. This has to be a FullDPMatrix. The second type, +// specifies that this is a trace-matrix navigator while the TTraceFlag can either +// be TracebackOn to enable the navigator or TracebackOff to disable it. +// The last parameter specifies the kind of navigation. +template +class DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> +{ +public: + + typedef DPMatrix_ TDPMatrix_; + typedef typename Pointer_::Type TDPMatrixPointer_; + typedef typename Iterator::Type TDPMatrixIterator; + + TDPMatrixPointer_ _ptrDataContainer = nullptr; // The pointer to the underlying Matrix. + int _laneLeap = 0; // Keeps track of the jump size from one column to another. + unsigned _simdLane = 0; // Used for tracing the correct cell in case of simd vectors. + TDPMatrixIterator _activeColIterator = TDPMatrixIterator(); // The current column iterator. +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _init() +// ---------------------------------------------------------------------------- + +// Initializes the navigator for unbanded alignments. +template +inline void +_init(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & navigator, + DPMatrix_ & dpMatrix, + DPBandConfig const &) +{ + if (IsSameType::VALUE) + return; // Leave navigator uninitialized because it is never used. + + navigator._ptrDataContainer = &dpMatrix; + navigator._activeColIterator = begin(dpMatrix, Standard()); + navigator._laneLeap = 1; + assignValue(navigator._activeColIterator, TValue()); +} + +// Initializes the navigator for banded alignments. +// Note, the band size has a maximal width of length of the vertical sequence. +template +inline void +_init(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & navigator, + DPMatrix_ & dpMatrix, + DPBandConfig const & band) +{ + typedef typename Size >::Type TMatrixSize; + typedef typename MakeSigned::Type TSignedSize; + + if (IsSameType::VALUE) + return; // Leave navigator as is because it should never be used. + + navigator._ptrDataContainer = &dpMatrix; + + // Band begins within the first row. + if (lowerDiagonal(band) >= 0) + { + // The first cell of the first column starts at the last cell in the matrix of the current column. + navigator._laneLeap = _min(length(dpMatrix, DPMatrixDimension_::VERTICAL), bandSize(band)); + navigator._activeColIterator = begin(dpMatrix, Standard()) + _dataLengths(dpMatrix)[DPMatrixDimension_::VERTICAL] - 1; + } + else if (upperDiagonal(band) <= 0) // Band begins within the first column. + { + // The first cell starts at the beginning of the current column. + navigator._laneLeap = 1; + navigator._activeColIterator = begin(dpMatrix, Standard()); + } + else // Band intersects with the point of origin. + { + // First cell starts at position i, such that i + abs(lowerDiagonal) = length(seqV). + TMatrixSize lengthVertical = length(dpMatrix, DPMatrixDimension_::VERTICAL); + int lastPos = _max(-static_cast(lengthVertical - 1), lowerDiagonal(band)); + navigator._laneLeap = lengthVertical + lastPos; + navigator._activeColIterator = begin(dpMatrix, Standard()) + navigator._laneLeap - 1; + } + assignValue(navigator._activeColIterator, TValue()); +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [DPInitialColumn, FirstCell] +// ---------------------------------------------------------------------------- + +// In the initial column we don't need to do anything because, the navigagtor is already initialized. +template +inline void +_goNextCell(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & /*dpNavigator*/, + MetaColumnDescriptor const &, + FirstCell const &) +{ + // no-op +} + +template +inline void +_goNextCell(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & /*dpNavigator*/, + MetaColumnDescriptor const &, + FirstCell const &) +{ + // no-op +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [PartialColumnTop, FirstCell] +// ---------------------------------------------------------------------------- + +// We are in the banded case, where the band crosses the first row. +// The left cell of the active cell is not valid, beacause we only can come from horizontal direction. +// The lower left cell of the active cell is the horizontal direction. + +template +inline void +_goNextCell(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + FirstCell const &) +{ + if (IsSameType::VALUE) + return; // Do nothing since no trace back is computed. + + --dpNavigator._laneLeap; + dpNavigator._activeColIterator += dpNavigator._laneLeap; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell() [other column types, FirstCell] +// ---------------------------------------------------------------------------- + +// We are in the banded case. +// The left cell of the active cell represents diagonal direction. The lower left diagonal represents the horizontal direction. + +template +inline void +_goNextCell(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + FirstCell const &) +{ + if (IsSameType::VALUE) + return; // Do nothing since no trace back is computed. + + dpNavigator._activeColIterator += dpNavigator._laneLeap; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [any column, InnerCell] +// ---------------------------------------------------------------------------- + +// For any other column type and location we can use the same navigation procedure. +template +inline void +_goNextCell(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + InnerCell const &) +{ + if (IsSameType::VALUE) + return; // Do nothing since no trace back is computed. + + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [PartialColumnBottom, LastCell] +// ---------------------------------------------------------------------------- + +template +inline void +_goNextCell(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + if (IsSameType::VALUE) + return; // Do nothing since no trace back is computed. + + ++dpNavigator._activeColIterator; +} + +// If we are in banded case and the band crosses the last row, we have to update +// the additional leap for the current track. +template +inline void +_goNextCell(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + if (IsSameType::VALUE) + return; // Do nothing since no trace back is computed. + + ++dpNavigator._activeColIterator; + ++dpNavigator._laneLeap; +} + +// ---------------------------------------------------------------------------- +// Function _goNextCell [any other column, LastCell] +// ---------------------------------------------------------------------------- + +// If we are in the banded case the left cell of the active represents the diagonal direction. +template +inline void +_goNextCell(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + MetaColumnDescriptor const &, + LastCell const &) +{ + if (IsSameType::VALUE) + return; // Do nothing since no trace back is computed. + + ++dpNavigator._activeColIterator; +} + +// ---------------------------------------------------------------------------- +// Function _traceHorizontal() +// ---------------------------------------------------------------------------- + +template +inline void +_traceHorizontal(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + bool isBandShift) +{ + if (IsSameType::VALUE) + return; // Do nothing since no trace back is computed. + + if (isBandShift) + dpNavigator._activeColIterator -= _dataFactors(*dpNavigator._ptrDataContainer)[DPMatrixDimension_::HORIZONTAL] - 1; + else + dpNavigator._activeColIterator -= _dataFactors(*dpNavigator._ptrDataContainer)[DPMatrixDimension_::HORIZONTAL]; + +} + +// ---------------------------------------------------------------------------- +// Function _traceDiagonal() +// ---------------------------------------------------------------------------- + +template +inline void +_traceDiagonal(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + bool isBandShift) +{ + if (IsSameType::VALUE) + return; // Do nothing since no trace back is computed. + + if (isBandShift) + dpNavigator._activeColIterator -= _dataFactors(*dpNavigator._ptrDataContainer)[DPMatrixDimension_::HORIZONTAL]; + else + dpNavigator._activeColIterator -= _dataFactors(*dpNavigator._ptrDataContainer)[DPMatrixDimension_::HORIZONTAL] + 1; + +} + +// ---------------------------------------------------------------------------- +// Function _traceVertical() +// ---------------------------------------------------------------------------- + +template +inline void +_traceVertical(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + bool /*isBandShift*/) +{ + if (IsSameType::VALUE) + return; // Do nothing since no trace back is computed. + + dpNavigator._activeColIterator -= _dataFactors(*dpNavigator._ptrDataContainer)[DPMatrixDimension_::VERTICAL]; +} + +// ---------------------------------------------------------------------------- +// Function setToPosition() +// ---------------------------------------------------------------------------- + +template +inline void +_setToPosition(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + TPosition const & hostPosition) +{ + if (IsSameType::VALUE) + return; + + SEQAN_ASSERT_LT(hostPosition, static_cast(length(container(dpNavigator)))); + + dpNavigator._activeColIterator = begin(*dpNavigator._ptrDataContainer, Standard()) + hostPosition; +} + + +// Sets the host position based on the given horizontal and vertical position. Note that the horizontal and +// vertical positions must correspond to the correct size of the underlying matrix. +// For banded matrices the vertical dimension might not equal the length of the vertical sequence. +template +inline void +_setToPosition(DPMatrixNavigator_, DPTraceMatrix, NavigateColumnWise> & dpNavigator, + TPositionH const & horizontalPosition, + TPositionV const & verticalPosition) +{ + if (IsSameType::VALUE) + return; + SEQAN_ASSERT_LT(horizontalPosition, static_cast(length(container(dpNavigator), +DPMatrixDimension_::HORIZONTAL))); + SEQAN_ASSERT_LT(verticalPosition, static_cast(length(container(dpNavigator), +DPMatrixDimension_::VERTICAL))); + + TPositionH hostPosition = horizontalPosition * _dataFactors(container(dpNavigator))[+DPMatrixDimension_::HORIZONTAL] + verticalPosition; + dpNavigator._activeColIterator = begin(*dpNavigator._ptrDataContainer, Standard()) + hostPosition; +} + +// ---------------------------------------------------------------------------- +// Function assignValue() +// ---------------------------------------------------------------------------- + +template +inline void +assignValue(DPMatrixNavigator_, TNavigationSpec> & dpNavigator, + TValue const & element) +{ + if (IsSameType::VALUE) + return; // Do nothing since no trace back is computed. + + assignValue(dpNavigator._activeColIterator, element); +} + +// ---------------------------------------------------------------------------- +// Function scalarValue(); Helper to switch between simd and scalar. +// ---------------------------------------------------------------------------- + +// SIMD Version. Returns always a copy and never a reference. +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename Value::Type) +_scalarValue(TValue const & vec, + TPos const pos) +{ + return value(vec, pos); +} + +// Non-simd variant. Identity version. +template +inline SEQAN_FUNC_ENABLE_IF(Not > >, TValue &) +_scalarValue(TValue & val, + TPos const /*pos*/) +{ + return val; +} + +// Wrapper to get the scalar value. +template +inline auto +scalarValue(DPMatrixNavigator_, TNavigationSpec> const & dpNavigator) +{ + if (IsSameType::VALUE) + SEQAN_ASSERT_FAIL("Try to access uninitialized object!"); + + return _scalarValue(*dpNavigator._activeColIterator, dpNavigator._simdLane); +} + +// ---------------------------------------------------------------------------- +// Function value() +// ---------------------------------------------------------------------------- + +// Current position. +template +inline typename Reference, TNavigationSpec> >::Type +value(DPMatrixNavigator_, TNavigationSpec> & dpNavigator) +{ + if (IsSameType::VALUE) + SEQAN_ASSERT_FAIL("Try to access uninitialized object!"); + + return *dpNavigator._activeColIterator; +} + +template +inline typename Reference, TNavigationSpec> const >::Type +value(DPMatrixNavigator_, TNavigationSpec> const & dpNavigator) +{ + if (IsSameType::VALUE) + SEQAN_ASSERT_FAIL("Try to access uninitialized object!"); + + return *dpNavigator._activeColIterator; +} + +// At specified position. +template +inline typename Reference, TNavigationSpec> >::Type +value(DPMatrixNavigator_, TNavigationSpec> & dpNavigator, + TPosition const & position) +{ + if (IsSameType::VALUE) + SEQAN_ASSERT_FAIL("Try to access uninitialized object!"); + + return *(begin(*dpNavigator._ptrDataContainer) + position); +} + +template +inline typename Reference, TNavigationSpec> const >::Type +value(DPMatrixNavigator_, TNavigationSpec> const & dpNavigator, + TPosition const & position) +{ + if (IsSameType::VALUE) + SEQAN_ASSERT_FAIL("Try to access uninitialized object!"); + + return *(begin(*dpNavigator._ptrDataContainer) + position); +} + +// ---------------------------------------------------------------------------- +// Function coordinate() +// ---------------------------------------------------------------------------- + +// Returns the coordinate of the given dimension for the current position of the +// navigator within the matrix. +template +inline typename DPMatrixDimension_::TValue +coordinate(DPMatrixNavigator_, TNavigationSpec> const & dpNavigator, + typename DPMatrixDimension_::TValue const & dimension) +{ + if (IsSameType::VALUE) + SEQAN_ASSERT_FAIL("Try to access uninitialized object!"); + SEQAN_ASSERT_EQ(_checkCorrectDimension(dimension), true); + + if (IsSameType::VALUE) + return _dataLengths(*dpNavigator._ptrDataContainer)[dimension]; // Return lengths of given dimension. + + return coordinate(value(dpNavigator._ptrDataContainer), position(dpNavigator), dimension); // Simply delegate to coordinate of underlying matrix. +} + +// ---------------------------------------------------------------------------- +// Function position() +// ---------------------------------------------------------------------------- + +// Returns the current position of the navigator within the matrix. +template +inline typename Position, TNavigationSpec> >::Type +position(DPMatrixNavigator_, TNavigationSpec> const & dpNavigator) +{ + // Return 0 when traceback is not enabled. This is necessary to still track the score even + // the traceback is not enabled. + if (IsSameType::VALUE) + return 0; + + return position(dpNavigator._activeColIterator, *dpNavigator._ptrDataContainer); +} + +// ---------------------------------------------------------------------------- +// Function _setSimdLane() +// ---------------------------------------------------------------------------- + +template +inline void +_setSimdLane(DPMatrixNavigator_, TNavigationSpec> & dpNavigator, + TPos const pos) +{ + SEQAN_ASSERT_LT(pos, static_cast(LENGTH::Type>::VALUE)); + + dpNavigator._simdLane = pos; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_NAVIGATOR_TRACE_MATRIX_H_ diff --git a/seqan/align/dp_matrix_sparse.h b/seqan/align/dp_matrix_sparse.h new file mode 100644 index 0000000..4666a46 --- /dev/null +++ b/seqan/align/dp_matrix_sparse.h @@ -0,0 +1,150 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_SPARSE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_SPARSE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class DPMatrix [SparseDPMatrix] +// ---------------------------------------------------------------------------- + +template +class DPMatrix_ +{ +public: + + typedef typename Member::Type THost; + + Holder data_host; // The host containing the actual matrix. + + DPMatrix_() : + data_host() + { + create(data_host); + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function resize() +// ---------------------------------------------------------------------------- + +template +inline void +resize(DPMatrix_ & dpMatrix) +{ + typedef DPMatrix_ TDPMatrix; + typedef typename Size::Type TSize; + + TSize _dimVertical = length(dpMatrix, DPMatrixDimension_::VERTICAL); + + if (_dimVertical >= length(dpMatrix)) + resize(host(dpMatrix), _dimVertical, Exact()); +} + +template +inline void +resize(DPMatrix_ & dpMatrix, + TValue const & fillValue) +{ + typedef DPMatrix_ TDPMatrix; + typedef typename Size::Type TSize; + + TSize _dimVertical = length(dpMatrix, DPMatrixDimension_::VERTICAL); + + if (_dimVertical > length(dpMatrix)) + resize(host(dpMatrix), _dimVertical, fillValue, Exact()); +} + +// ---------------------------------------------------------------------------- +// Function value() +// ---------------------------------------------------------------------------- + +template +inline typename Reference >::Type +value(DPMatrix_ & dpMatrix, + TPositionV const & posV, + TPositionH const &) +{ + return value(dpMatrix, posV); +} + +template +inline typename Reference const>::Type +value(DPMatrix_ const & dpMatrix, + TPositionV const & posV, + TPositionH const &) +{ + return value(dpMatrix, posV); +} + +// ---------------------------------------------------------------------------- +// Function coordinate() +// ---------------------------------------------------------------------------- + + +template +inline typename Position >::Type +coordinate(DPMatrix_ const & /*dpMatrix*/, + TPosition hostPos, + typename DPMatrixDimension_::TValue dimension) +{ + SEQAN_ASSERT(_checkCorrectDimension(dimension)); + + if (dimension == DPMatrixDimension_::VERTICAL) + return hostPos; + + return 0u; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_MATRIX_SPARSE_H_ diff --git a/seqan/align/dp_meta_info.h b/seqan/align/dp_meta_info.h new file mode 100644 index 0000000..dab1bdc --- /dev/null +++ b/seqan/align/dp_meta_info.h @@ -0,0 +1,485 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Ren� Rahn +// ========================================================================== +// Here are defined the strategies for the different alignment algorithms. +// All classes are only used to determine the correct computational state +// of a particular alignment algorithm depending on its profile at a +// particular time. +// All classes are only used on a meta-level. +// ========================================================================== + +// TODO(holtgrew): Documentation in this header necessary or internal only? + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_META_INFO_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_META_INFO_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Tag DPInitialColumn +// ---------------------------------------------------------------------------- + +// Specifies the first column of the dp matrix. +struct DPInitialColumn_; +typedef Tag DPInitialColumn; + +// ---------------------------------------------------------------------------- +// Tag DPInnerColumn +// ---------------------------------------------------------------------------- + +// Specifies any inner column of the dp matrix between the first and the last +// column. +struct DPInnerColumn_; +typedef Tag DPInnerColumn; + +// ---------------------------------------------------------------------------- +// Tag DPFinalColumn +// ---------------------------------------------------------------------------- + +// Specifies the last column of a dp matrix. +struct DPFinalColumn_; +typedef Tag DPFinalColumn; + + +// The TColumnProperty determines the property of the column (if it is initial, inner, or last column) +// The TLocation determines how the column is organized in the matrix. +// It can have the values: FullColumn, PartialColumnTop, PartialColumnMiddle, PartialColumnBottom. +template +struct MetaColumnDescriptor +{ + typedef TColumnProperty_ TColumnProperty; + typedef TLocation_ TLocation; +}; + +// ---------------------------------------------------------------------------- +// Tag FullColumn +// ---------------------------------------------------------------------------- + +// Columns that span over the complete dp-matrix. (Unbanded alignemnts) +struct FullColumn_; +typedef Tag FullColumn; + +// ---------------------------------------------------------------------------- +// Tag PartialColumnTop +// ---------------------------------------------------------------------------- + +// Columns that begin in the first row, but does not at the last row of the dp-matrix +struct PartialColumnTop_; +typedef Tag PartialColumnTop; + +// ---------------------------------------------------------------------------- +// Tag PartialColumnMiddle +// ---------------------------------------------------------------------------- + +// Columns that are not attached to the begin or end of the dp-matrix. +struct PartialColumnMiddle_; +typedef Tag PartialColumnMiddle; + +// ---------------------------------------------------------------------------- +// Tag PartialColumnBottom +// ---------------------------------------------------------------------------- + +// Columns that end in the last row of the dp-matrix but do not start in the first row. +struct PartialColumnBottom_; +typedef Tag PartialColumnBottom; + + +// The cell specifiers are used to determine the cell of a column. +// There are three different cell specifiers used for the first cell, the +// inner cell and the last cell of a column. + +// ---------------------------------------------------------------------------- +// Tag FirstCell +// ---------------------------------------------------------------------------- + +struct FirstCell_; +typedef Tag FirstCell; + +// ---------------------------------------------------------------------------- +// Tag InnerCell +// ---------------------------------------------------------------------------- + +struct InnerCell_; +typedef Tag InnerCell; + +// ---------------------------------------------------------------------------- +// Tag LastCell +// ---------------------------------------------------------------------------- + +struct LastCell_; +typedef Tag LastCell; + + +// ---------------------------------------------------------------------------- +// Class DPMetaCell_ +// ---------------------------------------------------------------------------- + +// Keeps meta-information of a cell in the dp-matrix. It stores the recursion direction +// for a particular cell type and whether it can be tracked or not. + +template +struct DPMetaCell_ {}; + +// ---------------------------------------------------------------------------- +// Class DPMetaColumn_ +// ---------------------------------------------------------------------------- + +// Keeps meta-information of an entire column in the dp-matrix. Depending on the chosen +// DPProfile and the current column descriptor it selects for the different column locations and +// cell specifiers the correct meta-information about how is which cell computed and which cell is +// tracked. + +template +struct DPMetaColumn_ {}; + + +// ---------------------------------------------------------------------------- +// Class DPMetaColumn_ [FullColumn] +// ---------------------------------------------------------------------------- + +template +struct DPMetaColumn_ > +{ + typedef typename IsLocalAlignment_::Type TIsLocal; + + // If InitialColumn -> Zero, Vertical | Zero, Vertical | Zero // Within the algorithm we need to define the first row as only one cell if it is no initial column + // If InnerColumn -> Horizontal | Zero, All, All + // If FinalColumn -> Horizontal | Zero, All, All + + typedef typename If, + IsFreeEndGap_ >, RecursionDirectionZero, RecursionDirectionHorizontal>::Type TRecursionTypeFirstCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeInnerCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeLastCell_; + + // If Local + // If InitialColumn -> True, True, True + // If InnerColumn -> True, True, True + // If FinalColumn -> True, True, True + + // If Global + // If InitialColumn -> False, False, False | True (if DPLastRow) + // If InnerColumn -> False, False, False | True (if DPLastRow) + // If FinalColumn -> False | True, False | True (if DPLastColumn), True + + typedef typename If, + And, + IsFreeEndGap_ > // check this if he is really entitled to find the maximum here. + >, True, False>::Type TrackFlagFirstCell_; + typedef typename If, + And, + IsFreeEndGap_ > + >, True, False>::Type TrackFlagInnerCell_; + typedef typename If, + Or, + IsFreeEndGap_ > >, True, False>::Type TrackFlagLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + +// ---------------------------------------------------------------------------- +// Class DPMetaColumn_ [PartialColumnTop] +// ---------------------------------------------------------------------------- + +template +struct DPMetaColumn_ > +{ + typedef typename IsLocalAlignment_::Type TIsLocal; + + // How does the recursion directions look like? + + // If InitialColumn -> Zero, Vertical | Zero, Vertical | Zero // Within the algorithm we need to define the first row as only one cell if it is no initial column + // If InnerColumn -> Horizontal | Zero, All, LowerBand + // If FinalColumn -> Horizontal | Zero, All, LowerBand + + typedef typename If, + IsFreeEndGap_ >, RecursionDirectionZero, RecursionDirectionHorizontal>::Type TRecursionTypeFirstCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeInnerCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionLowerDiagonal>::Type TRecursionTypeLastCell_; + + // If Local + // If InitialColumn -> True, True, True + // If InnerColumn -> True, True, True + // If FinalColumn -> True, True, True + + // If Global + // If InitialColumn -> False, False, False + // If InnerColumn -> False, False, False + // If FinalColumn -> False | True, False | True, False | True (if DPLastColumn True) + + typedef typename If, + And, + IsFreeEndGap_ > + >, True, False>::Type TrackFlagFirstCell_; + typedef typename If, + And, + IsFreeEndGap_ > + >, True, False>::Type TrackFlagInnerCell_; + typedef typename If, + And, + IsFreeEndGap_ > + >, True, False>::Type TrackFlagLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + +// ---------------------------------------------------------------------------- +// Class DPMetaColumn_ [PartialColumnMiddle] +// ---------------------------------------------------------------------------- + +template +struct DPMetaColumn_ > +{ + typedef typename IsLocalAlignment_::Type TIsLocal; + + // If InitialColumn -> Zero, Vertical | Zero, Vertical | Zero // Within the algorithm we need to define the first row as only one cell if it is no initial column + // If InnerColumn -> UpperDiagonal, All, LowerDiagonal + // If FinalColumn -> UpperDiagonal, All, LowerDiagonal + + typedef typename If, RecursionDirectionZero, RecursionDirectionUpperDiagonal>::Type TRecursionTypeFirstCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeInnerCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionLowerDiagonal>::Type TRecursionTypeLastCell_; + + // If Local + // If InitialColumn -> True, True, True + // If InnerColumn -> True, True, True + // If FinalColumn -> True, True, True + + // If Global + // If InitialColumn -> False, False, False + // If InnerColumn -> False, False, False + // If FinalColumn -> False | True, False | True, False | True (if DPLastColumn True) + + typedef typename If, + And, + IsFreeEndGap_ > + >, True, False>::Type TrackFlagFirstCell_; + typedef typename If, + And, + IsFreeEndGap_ > + >, True, False>::Type TrackFlagInnerCell_; + typedef typename If, + And, + IsFreeEndGap_ > + >, True, False>::Type TrackFlagLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + +// ---------------------------------------------------------------------------- +// Class DPMetaColumn_ [PartialColumnBottom] +// ---------------------------------------------------------------------------- + +template +struct DPMetaColumn_ > +{ + typedef typename IsLocalAlignment_::Type TIsLocal; + + // If InitialColumn -> Zero, Vertical | Zero, Vertical | Zero // Within the algorithm we need to define the first row as only one cell if it is no initial column + // If InnerColumn -> UpperDiagonal, All, All + // If FinalColumn -> UpperDiagonal, All, All + + typedef typename If, RecursionDirectionZero, RecursionDirectionUpperDiagonal>::Type TRecursionTypeFirstCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeInnerCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeLastCell_; + + // If Local + // If InitialColumn -> True, True, True + // If InnerColumn -> True, True, True + // If FinalColumn -> True, True, True + + // If Global + // If InitialColumn -> False, False, False | True (if DPLastRow) + // If InnerColumn -> False, False, False | True (if DPLastRow) + // If FinalColumn -> False | True, False | True (if DPLastColumn), True (last is always true) + + typedef typename If, + And, + IsFreeEndGap_ > + >, True, False>::Type TrackFlagFirstCell_; + typedef typename If, + And, + IsFreeEndGap_ > + >, True, False>::Type TrackFlagInnerCell_; + typedef typename If, + Or, + IsFreeEndGap_ > >, True, False>::Type TrackFlagLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + + +// ---------------------------------------------------------------------------- +// Metafunction GetRecursionDirection_ +// ---------------------------------------------------------------------------- + +// Returns the type of recursion for a given DPMetaCell object. +template +struct GetRecursionDirection_ +{ + typedef Nothing Type; +}; + +template +struct GetRecursionDirection_ > +{ + typedef TRecursionDirection Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction RecursionDirection_ +// ---------------------------------------------------------------------------- + +// Returns the type of recursion for a given DPMetaColumn object and a given cell specifier. +template +struct RecursionDirection_ {}; + +template +struct RecursionDirection_ +{ + typedef typename GetRecursionDirection_::Type Type; +}; + +template +struct RecursionDirection_ +{ + typedef typename GetRecursionDirection_::Type Type; +}; + +template +struct RecursionDirection_ +{ + typedef typename GetRecursionDirection_::Type Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction IsTrackingEnabled_ +// ---------------------------------------------------------------------------- + +// Returns an object that evaluates to true if for a given cell description the +// tracking was enabled. Otherwise the object evaluates to false. +template +struct IsTrackingEnabled_ : + False {}; + +template +struct IsTrackingEnabled_ >: + True {}; + + +template +struct TrackingEnabled_ : + False {}; + +template +struct TrackingEnabled_: + IsTrackingEnabled_{}; + +template +struct TrackingEnabled_: + IsTrackingEnabled_{}; + +template +struct TrackingEnabled_: + IsTrackingEnabled_{}; + +// ---------------------------------------------------------------------------- +// Metafunction LastColumnEnabled_ +// ---------------------------------------------------------------------------- + +template +struct LastColumnEnabled_ +{ + typedef typename IsSameType::Type Type; +}; + +template +struct LastColumnEnabled_, TColumnDescriptor> : + LastColumnEnabled_ +{}; + +// ---------------------------------------------------------------------------- +// Metafunction LastRowEnabled_ +// ---------------------------------------------------------------------------- + +template +struct LastRowEnabled_ +{ + typedef typename And, + Or, + IsSameType > >::Type Type; +}; + +template +struct LastRowEnabled_, TCellDescriptor, TColumnDescriptor> : + LastRowEnabled_ +{}; + +// ============================================================================ +// Functions +// ============================================================================ + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_META_INFO_H_ diff --git a/seqan/align/dp_profile.h b/seqan/align/dp_profile.h new file mode 100644 index 0000000..f57e161 --- /dev/null +++ b/seqan/align/dp_profile.h @@ -0,0 +1,571 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// This header contains all tags, structures and meta-functions that are +// used to define the meta-profile of an alignment algorithm. +// With the meta-profile the sort of alignment can be selected such as +// a global or a local alignment. It further structures the different +// specializations of global and local alignments or selects the gap cost +// function, or enables or disables the trace-back function. +// ========================================================================== + +// TODO(holtgrew): Documentation in this header necessary or internal only? + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_PROFILE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_PROFILE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class FreeEndGaps_ +// ---------------------------------------------------------------------------- + +// Used to determine which end-gaps are free. +template +struct FreeEndGaps_ {}; + +// ---------------------------------------------------------------------------- +// Class SplitBreakpointAlignment +// ---------------------------------------------------------------------------- +// TODO(rmaerker): maybe in a different header +// Used to specify the global alignment for split breakpoint computation. +struct AlignmentSplitBreakpoint_; +typedef Tag SplitBreakpointAlignment; + +// ---------------------------------------------------------------------------- +// Class GlobalAlignment_ +// ---------------------------------------------------------------------------- + +// This is used to select global alignments. The default is the standard global +// dp-algorithm. +// +// Note, all global alignments have to be specialized versions of GlobalAlignment_<> +template > +struct GlobalAlignment_; + +typedef GlobalAlignment_<> DPGlobal; + +// ---------------------------------------------------------------------------- +// Class SuboptimalAlignment +// ---------------------------------------------------------------------------- + +// TODO(rmaerker): maybe in a different header +// Used to specify the WatermanEggert algorithm. +struct AlignmentSuboptimal_; +typedef Tag SuboptimalAlignment; + +// ---------------------------------------------------------------------------- +// Class LocalAlignment_ +// ---------------------------------------------------------------------------- + +// This is used to select local alignments. The default is the standard local +// dp-algorithm. +// +// Note, all local alignments have to be specialized versions of LocalAlignment_<> + +template +struct LocalAlignment_; + +typedef LocalAlignment_<> DPLocal; +typedef LocalAlignment_ DPLocalEnumerate; + +// Use macro expansion to define all possible SIMD initialization types. + +template +struct InitSimdTrace_; + +#define SEQAN_SIMD_INIT_FILL_VALUE_2_ FILL_VALUE, FILL_VALUE +#define SEQAN_SIMD_INIT_FILL_VALUE_4_ SEQAN_SIMD_INIT_FILL_VALUE_2_, SEQAN_SIMD_INIT_FILL_VALUE_2_ +#define SEQAN_SIMD_INIT_FILL_VALUE_8_ SEQAN_SIMD_INIT_FILL_VALUE_4_, SEQAN_SIMD_INIT_FILL_VALUE_4_ +#define SEQAN_SIMD_INIT_FILL_VALUE_16_ SEQAN_SIMD_INIT_FILL_VALUE_8_, SEQAN_SIMD_INIT_FILL_VALUE_8_ +#define SEQAN_SIMD_INIT_FILL_VALUE_32_ SEQAN_SIMD_INIT_FILL_VALUE_16_, SEQAN_SIMD_INIT_FILL_VALUE_16_ + +#define SEQAN_SIMD_TRACE_SETUP_2_(SIZE, ...) \ +template \ +struct InitSimdTrace_ \ +{ \ + static const TVector VALUE; \ +}; \ + \ +template \ +const TVector InitSimdTrace_::VALUE = TVector{__VA_ARGS__}; + +#define SEQAN_SIMD_TRACE_SETUP_1_(SIZE, MACRO) SEQAN_SIMD_TRACE_SETUP_2_(SIZE, MACRO) +#define SEQAN_SIMD_TRACE_SETUP_(SIZE) SEQAN_SIMD_TRACE_SETUP_1_(SIZE, SEQAN_SIMD_INIT_FILL_VALUE_ ## SIZE ## _) + +SEQAN_SIMD_TRACE_SETUP_(2) +SEQAN_SIMD_TRACE_SETUP_(4) +SEQAN_SIMD_TRACE_SETUP_(8) +SEQAN_SIMD_TRACE_SETUP_(16) +SEQAN_SIMD_TRACE_SETUP_(32) + +// Scalar version. +template +struct TraceValue_ +{ + typedef uint8_t Type; + static const Type NONE = 0u; //0000000 + static const Type DIAGONAL = 1u; //0000001 + static const Type HORIZONTAL = 2u; //0000010 + static const Type VERTICAL = 4u; //0000100 + static const Type HORIZONTAL_OPEN = 8u; //0001000 + static const Type VERTICAL_OPEN = 16u; //0010000 + static const Type MAX_FROM_HORIZONTAL_MATRIX = 32u; //0100000 + static const Type MAX_FROM_VERTICAL_MATRIX = 64u; //1000000 + static const Type NO_VERTICAL_TRACEBACK = ~(VERTICAL | VERTICAL_OPEN); + static const Type NO_HORIZONTAL_TRACEBACK = ~(HORIZONTAL | HORIZONTAL_OPEN); +}; + +// SIMD Vector version. +template +struct TraceValue_ +{ + typedef TVector Type; + static const Type NONE; + static const Type DIAGONAL; + static const Type HORIZONTAL; + static const Type VERTICAL; + static const Type HORIZONTAL_OPEN; + static const Type VERTICAL_OPEN; + static const Type MAX_FROM_HORIZONTAL_MATRIX; + static const Type MAX_FROM_VERTICAL_MATRIX; + static const Type NO_HORIZONTAL_TRACEBACK; + static const Type NO_VERTICAL_TRACEBACK; +}; + +// Macro expansion to define out-of-class initialization of static members. + +#define SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(TRACE_VALUE) \ + template \ + const TVector TraceValue_::TRACE_VALUE = InitSimdTrace_::TRACE_VALUE, LENGTH::VALUE>::VALUE; + +SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(NONE) +SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(DIAGONAL) +SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(HORIZONTAL) +SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(VERTICAL) +SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(HORIZONTAL_OPEN) +SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(VERTICAL_OPEN) +SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(MAX_FROM_HORIZONTAL_MATRIX) +SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(MAX_FROM_VERTICAL_MATRIX) +SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(NO_HORIZONTAL_TRACEBACK) +SEQAN_SIMD_TRACE_OUT_OF_CLASS_INIT_(NO_VERTICAL_TRACEBACK) + +// Type alias to choose between scalar and simd version of trace value. +template +using TraceBitMap_ = TraceValue_ >::Type >; + +// ---------------------------------------------------------------------------- +// Tag GapsLeft +// ---------------------------------------------------------------------------- + +struct GapsLeft_; +typedef Tag GapsLeft; + +// ---------------------------------------------------------------------------- +// Tag GapsRight +// ---------------------------------------------------------------------------- + +struct GapsRight_; +typedef Tag GapsRight; + + +// ---------------------------------------------------------------------------- +// Tag SingleTrace +// ---------------------------------------------------------------------------- + +struct SingleTrace_; +typedef Tag SingleTrace; + +// ---------------------------------------------------------------------------- +// Tag CompleteTrace +// ---------------------------------------------------------------------------- + +struct CompleteTrace_; +typedef Tag CompleteTrace; + +// ---------------------------------------------------------------------------- +// Tag TracebackConfig_ +// ---------------------------------------------------------------------------- + +template +struct TracebackConfig_ {}; + +// ---------------------------------------------------------------------------- +// Tag TracebackOn +// ---------------------------------------------------------------------------- + +template > +struct TracebackOn {}; + +// ---------------------------------------------------------------------------- +// Tag TracebackOff +// ---------------------------------------------------------------------------- + +struct TracebackOff_ {}; +typedef Tag TracebackOff; + +// ---------------------------------------------------------------------------- +// Tag LinearGaps +// ---------------------------------------------------------------------------- + +/*! + * @tag AlignmentAlgorithmTags#LinearGaps + * @headerfile + * @brief Tag for selecting linear gap cost model. This tag can be used for all standard DP algorithms. + * + * @signature struct LinearGaps_; + * @signature typedef Tag LinearGaps; + */ +struct LinearGaps_; +typedef Tag LinearGaps; + +// ---------------------------------------------------------------------------- +// Tag AffineGaps +// ---------------------------------------------------------------------------- + +/*! + * @tag AlignmentAlgorithmTags#AffineGaps + * @headerfile + * @brief Tag for selecting affine gap cost model. This tag can be used for all standard DP algorithms. + * + * @signature struct AffineGaps_; + * @signature typedef Tag AffineGaps; + */ +struct AffineGaps_; +typedef Tag AffineGaps; + +// ---------------------------------------------------------------------------- +// Tag DynamicGaps +// ---------------------------------------------------------------------------- + +/*! + * @tag AlignmentAlgorithmTags#DynamicGaps + * @headerfile + * @brief Tag for selecting dynamic gap cost model. This tag can be used for all standard DP algorithms. + * + * @signature struct DynamicGaps_; + * @signature typedef Tag DynamicGaps; + */ + +struct DynamicGaps_; +typedef Tag DynamicGaps; + +// ---------------------------------------------------------------------------- +// Class DPProfile +// ---------------------------------------------------------------------------- + +// This meta-object takes three types to be specialized. +// +// TAlignment: The type to select the pairwise alignment algorithm. +// TGapCosts: The gap cost function (LinearGaps or AffineGaps). +// TTraceback: The traceback switch (TracebackOn or TracebackOff). +template +struct DPProfile_ {}; + + +// ---------------------------------------------------------------------------- +// Tag DPFirstRow +// ---------------------------------------------------------------------------- + +// These tags are used to specify the four locations of a dp-matrix where +// free gaps can occur. +struct DPFirstRow_; +typedef Tag DPFirstRow; + +// ---------------------------------------------------------------------------- +// Tag DPFirstColumn +// ---------------------------------------------------------------------------- + +struct DPFirstColumn_; +typedef Tag DPFirstColumn; + +// ---------------------------------------------------------------------------- +// Tag DPLastRow +// ---------------------------------------------------------------------------- + +struct DPLastRow_; +typedef Tag DPLastRow; + +// ---------------------------------------------------------------------------- +// Tag DPLastColumn +// ---------------------------------------------------------------------------- + +struct DPLastColumn_; +typedef Tag DPLastColumn; + +template , + typename TTraceConfig = TracebackOn > > +class AlignConfig2 +{ +public: + TBand _band; + + AlignConfig2() : _band() + {} + + template + AlignConfig2(TPosition const & lDiag, TPosition const & uDiag) : _band(lDiag, uDiag) + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction IsGlobalAlignment +// ---------------------------------------------------------------------------- + +// Checks if the dp profile is a global alignment. +template +struct IsGlobalAlignment_ : + False {}; + +template +struct IsGlobalAlignment_ >: + True {}; + +template +struct IsGlobalAlignment_ const>: + True {}; + +template +struct IsGlobalAlignment_ >: + IsGlobalAlignment_{}; + +template +struct IsGlobalAlignment_ const>: + IsGlobalAlignment_{}; + +// ---------------------------------------------------------------------------- +// Metafunction TraceTail_ +// ---------------------------------------------------------------------------- + +// define whether to include the 'tail' of an alignment in the trace +template +struct TraceTail_ : + IsGlobalAlignment_{}; + +// ---------------------------------------------------------------------------- +// Metafunction TraceHead_ +// ---------------------------------------------------------------------------- + +// define whether to include the 'head' of an alignment in the trace +template +struct TraceHead_ : + IsGlobalAlignment_{}; + +// ---------------------------------------------------------------------------- +// Metafunction HasTerminationCriterium_ +// ---------------------------------------------------------------------------- + +// check whether an algorithm has an early termination criterium +// if an algorithm has this, it will get a DPscout that can be terminated +// see dp_scout.h for more info +template +struct HasTerminationCriterium_ : + False {}; + +// ---------------------------------------------------------------------------- +// Metafunction IsLocalAlignment_ +// ---------------------------------------------------------------------------- + +// Checks if the dp profile is a local alignment. +template +struct IsLocalAlignment_ : + False {}; + +template +struct IsLocalAlignment_ >: + True {}; + +template +struct IsLocalAlignment_ const>: + True {}; + +template +struct IsLocalAlignment_ >: + IsLocalAlignment_{}; + +template +struct IsLocalAlignment_ const>: + IsLocalAlignment_{}; + +// ---------------------------------------------------------------------------- +// Metafunction IsTracebackEnabled_ +// ---------------------------------------------------------------------------- + +// Checks if the trace-back for the current dp profile is enabled. +template +struct IsTracebackEnabled_ : + False {}; + +template +struct IsTracebackEnabled_ >: + True {}; + +template +struct IsTracebackEnabled_ const>: + True {}; + +template +struct IsTracebackEnabled_ >: + IsTracebackEnabled_{}; + +template +struct IsTracebackEnabled_ const>: + IsTracebackEnabled_{}; + +// ---------------------------------------------------------------------------- +// Metafunction IsGapsLeft_ +// ---------------------------------------------------------------------------- + +template +struct IsGapsLeft_ : False{}; + +template +struct IsGapsLeft_ > > + : True{}; + +template +struct IsGapsLeft_ > + : IsGapsLeft_{}; + +// ---------------------------------------------------------------------------- +// Metafunction IsSingleTrace_ +// ---------------------------------------------------------------------------- + +template +struct IsSingleTrace_ : False{}; + +template +struct IsSingleTrace_ > > +: True{}; + +template +struct IsSingleTrace_ > +: IsSingleTrace_{}; + +// ---------------------------------------------------------------------------- +// Metafunction IsFreeEndGap_ +// ---------------------------------------------------------------------------- + +// Checks if for the current dp profile and a given gap location the algorithm uses free gaps. +template +struct IsFreeEndGap_ : + False {}; + +template +struct IsFreeEndGap_ const, TDPSide>: + IsFreeEndGap_{}; + +template +struct IsFreeEndGap_, TDPSide>: + IsFreeEndGap_{}; + +template +struct IsFreeEndGap_ const, TDPSide>: + True +{}; + +template +struct IsFreeEndGap_, TDPSide>: + True +{}; + +template +struct IsFreeEndGap_ const, TDPSide>: + IsFreeEndGap_ +{}; + +template +struct IsFreeEndGap_, TDPSide>: + IsFreeEndGap_ +{}; + +template +struct IsFreeEndGap_, DPFirstRow>: + True +{}; + +template +struct IsFreeEndGap_ const, DPFirstRow>: + True +{}; + +template +struct IsFreeEndGap_, DPFirstColumn>: + True +{}; + +template +struct IsFreeEndGap_ const, DPFirstColumn>: + True +{}; + +template +struct IsFreeEndGap_, DPLastRow>: + True +{}; + +template +struct IsFreeEndGap_ const, DPLastRow>: + True +{}; + +template +struct IsFreeEndGap_, DPLastColumn>: + True +{}; + +template +struct IsFreeEndGap_ const, DPLastColumn>: + True +{}; + +// ============================================================================ +// Functions +// ============================================================================ + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_PROFILE_H_ diff --git a/seqan/align/dp_scout.h b/seqan/align/dp_scout.h new file mode 100644 index 0000000..4642f9d --- /dev/null +++ b/seqan/align/dp_scout.h @@ -0,0 +1,340 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// The dp scout is a structure that stores the current maximal score and its +// host position in the underlying dp-matrix. +// This class can be overloaded to implement different behaviors of tracking +// the maximal score, e.g., for the split breakpoint computation. +// ========================================================================== +// Author: Hannes Hauswedell +// ========================================================================== +// The terminator specialization of dp scout offers the possibility to have +// dp generation stop, if specified criteria are met. +// To do this, define HasTerminationCriterium_<> for your algorithm and +// implement a DPScoutState for your terminator specialization. In your +// overloaded _scoutBestScore() or _computeCell() you can call +// terminateScout() on your Scout to have DP-generation stop. +// see dp_scout_xdrop.h for an example. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_TEST_ALIGNMENT_DP_SCOUT_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_TEST_ALIGNMENT_DP_SCOUT_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class Terminator_ +// ---------------------------------------------------------------------------- + +template +struct Terminator_; + +// ---------------------------------------------------------------------------- +// Class DPScoutState_ +// ---------------------------------------------------------------------------- + +template +class DPScoutState_; + +template <> +class DPScoutState_ : public Nothing // empty member optimization +{}; + +// ---------------------------------------------------------------------------- +// Class DPScout_ +// ---------------------------------------------------------------------------- + +template +class DPScout_; + +// The default implementation of the dp scout simply stores one maximum +// and its corresponding position. +// +// The state must be a Nothing and is left untouched and unused. +template +class DPScout_ +{ +public: + using TScoreValue = typename Value::Type; + + TDPCell _maxScore = TDPCell(); + uint32_t _maxHostPosition = DPCellDefaultInfinity::VALUE; // The corresponding host position within the underlying dp-matrix. + + DPScout_() = default; + + DPScout_(DPScoutState_ const & /*state*/) {} +}; + +// Terminator_ Specialization +template +class DPScout_ > + : public DPScout_ +{ +public: + typedef DPScout_ TParent; + + DPScoutState_ > * state = nullptr; + bool terminationCriteriumMet = false; + + DPScout_() = default; + + DPScout_(DPScoutState_ > & pState) : + DPScout_(), + state(&pState) + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction ScoutSpecForAlignmentAlgorithm_ +// ---------------------------------------------------------------------------- + +// Given an alignment algorithm tag such as GlobalAlignment_ or LocalAlignment_, returns the specialization tag for the +// corresponding DPScout_ specialization. + +template +struct ScoutSpecForAlignmentAlgorithm_ +{ + typedef If, + Terminator_<>, + Default> Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction ScoutStateSpecForScout_ +// ---------------------------------------------------------------------------- + +// Given an dp scout this meta-function returns the appropriate specialization for the scout state. + +template +struct ScoutStateSpecForScout_ +{ + typedef Default Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _scoutBestScore() +// ---------------------------------------------------------------------------- + +// Tracks the new score, if it is the new maximum. +template +inline void +_scoutBestScore(DPScout_ & dpScout, + TDPCell const & activeCell, + TTraceMatrixNavigator const & navigator, + TIsLastColumn const & /**/, + TIsLastRow const & /**/) +{ + if (_scoreOfCell(activeCell) > _scoreOfCell(dpScout._maxScore)) + { + dpScout._maxScore = activeCell; + dpScout._maxHostPosition = position(navigator); + } +} + +// TODO(rmaerker): Why is this needed? +template +inline void +_scoutBestScore(DPScout_ & dpScout, + TDPCell const & activeCell, + TTraceMatrixNavigator const & navigator, + TIsLastColumn const & /**/) +{ + _scoutBestScore(dpScout, activeCell, navigator, TIsLastColumn(), False()); +} + +// TODO(rmaerker): Why is this needed? +template +inline void +_scoutBestScore(DPScout_ & dpScout, + TDPCell const & activeCell, + TTraceMatrixNavigator const & navigator) +{ + _scoutBestScore(dpScout, activeCell, navigator, False(), False()); +} + +// ---------------------------------------------------------------------------- +// Function maxScore() +// ---------------------------------------------------------------------------- + +// Returns the current maximal score. +template +inline typename Value::Type const +maxScore(DPScout_ const & dpScout) +{ + return _scoreOfCell(dpScout._maxScore); +} + +// ---------------------------------------------------------------------------- +// Function maxHostPosition() +// ---------------------------------------------------------------------------- + +// Returns the host position that holds the current maximum score. +template +inline unsigned int +maxHostPosition(DPScout_ const & dpScout) +{ + return dpScout._maxHostPosition; +} + +// ---------------------------------------------------------------------------- +// Function _terminationCriteriumIsMet() +// ---------------------------------------------------------------------------- + +template +inline bool +_terminationCriteriumIsMet(DPScout_ > const & scout) +{ + return scout.terminationCriteriumMet; +} + +// ---------------------------------------------------------------------------- +// Function terminateScout() +// ---------------------------------------------------------------------------- + +template +inline void +terminateScout(DPScout_ > & scout) +{ + scout.terminationCriteriumMet = true; +} + +// ---------------------------------------------------------------------------- +// Function _preInitScoutHorizontal() +// ---------------------------------------------------------------------------- + +template +inline void +_preInitScoutHorizontal(DPScout_ const & /*scout*/) +{ + // no-op. +} + +// ---------------------------------------------------------------------------- +// Function _reachedHorizontalEndPoint() +// ---------------------------------------------------------------------------- + +template +constexpr inline bool +_reachedHorizontalEndPoint(DPScout_ const & /*scout*/, + TIter const & /*hIt*/) +{ + return false; +} + +// ---------------------------------------------------------------------------- +// Function _preInitScoutVertical() +// ---------------------------------------------------------------------------- + +template +inline void +_preInitScoutVertical(DPScout_ const & /*scout*/) +{ + // no-op. +} + +// ---------------------------------------------------------------------------- +// Function _reachedVerticalEndPoint() +// ---------------------------------------------------------------------------- + +template +constexpr inline bool +_reachedVerticalEndPoint(DPScout_ const & /*scout*/, + TIter const & /*iter*/) +{ + return false; +} + +// ---------------------------------------------------------------------------- +// Function _nextHorizontalEndPos() +// ---------------------------------------------------------------------------- + +template +inline void +_nextHorizontalEndPos(DPScout_ const & /*scout*/) +{ + // no-op. +} + +// ---------------------------------------------------------------------------- +// Function _nextVerticalEndPos() +// ---------------------------------------------------------------------------- + +template +inline void +_nextVerticalEndPos(DPScout_ const & /*scout*/) +{ + // no-op. +} + +// ---------------------------------------------------------------------------- +// Function _incHorizontalPos() +// ---------------------------------------------------------------------------- + +template +inline void +_incHorizontalPos(DPScout_ const & /*scout*/) +{ + // no-op. +} + +// ---------------------------------------------------------------------------- +// Function _incVerticalPos() +// ---------------------------------------------------------------------------- + +template +inline void +_incVerticalPos(DPScout_ const & /*scout*/) +{ + // no-op. +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_TEST_ALIGNMENT_DP_SCOUT_H_ diff --git a/seqan/align/dp_scout_simd.h b/seqan/align/dp_scout_simd.h new file mode 100644 index 0000000..92095d2 --- /dev/null +++ b/seqan/align/dp_scout_simd.h @@ -0,0 +1,454 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2015, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stefan Budach +// ========================================================================== +// DPScout_ specialization for the SIMD alignment implementation. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_SIMD_DP_SCOUT_SIMD_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_SIMD_DP_SCOUT_SIMD_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +struct SimdAlignEqualLength_; +typedef Tag SimdAlignEqualLength; + +template +struct SimdAlignVariableLength +{}; + +template +struct SimdAlignmentScout {}; + +// ---------------------------------------------------------------------------- +// Class DPScoutState_ +// ---------------------------------------------------------------------------- + +template <> +class DPScoutState_ +{}; + +template +class DPScoutState_ > +{ +public: + using TSizeH = typename Size::Type; + using TSizeV = typename Size::Type; + + String > masksH; + String > masksV; + String > masks; + + String endsH; + String endsV; + ModifiedString, ModPos > > sortedEndsH; + ModifiedString, ModPos > > sortedEndsV; + + decltype(begin(sortedEndsH, Standard())) nextEndsH; + decltype(begin(sortedEndsV, Standard())) nextEndsV; + + size_t dimV; + size_t posH; + size_t posV; + bool right; + bool bottom; + bool isLocalAlignment; + + // ---------------------------------------------------------------------------- + // Function DPScout_#updateMasksRight() + // ---------------------------------------------------------------------------- + + inline void updateMasksRight() + { + for(size_t pos = dimV - 2; pos != MaxValue::VALUE; --pos) + masks[pos] |= masks[pos + 1]; + } + + // ---------------------------------------------------------------------------- + // Function DPScout_#updateMasksBottom() + // ---------------------------------------------------------------------------- + + inline void updateMasksBottom() + { + for (auto posIt = begin(sortedEndsV, Standard()); posIt != end(sortedEndsV, Standard()); ++posIt) + for (auto it = nextEndsH; it != end(sortedEndsH, Standard()); ++it) + { + masks[*posIt] |= (masksH[*it] & masksV[*posIt]); + } + } + + // ---------------------------------------------------------------------------- + // Function DPScout_#updateMasks() + // ---------------------------------------------------------------------------- + + inline void updateMasks() + { + for(size_t pos = 0; pos < dimV; ++pos) + masks[pos] = masksH[posH] & masksV[pos]; + //for local alignments the BOTTOM parameter must be checked first + if(isLocalAlignment) + { + updateMasksBottom(); + updateMasksRight(); + } + else + { + if(right && posH == *nextEndsH) + updateMasksRight(); + if(bottom) + updateMasksBottom(); + } + } +}; + +// ---------------------------------------------------------------------------- +// Class DPScout_ +// ---------------------------------------------------------------------------- + +template +class DPScout_ > : + public DPScout_ +{ +public: + using TBase = DPScout_; + using TScoutState = DPScoutState_; + + //used in the SIMD version to keep track of all host positions + //SIMD register size divided by 16bit is the amount of alignments + //so we need two vectors of type 32bit to save the host for all alignments + + // TODO(rrahn): Abstract into a struct, so we can model different configurations. + SimdVector::Type _maxHostLow; //first half of alignments + SimdVector::Type _maxHostHigh; //other half + TScoutState * state = nullptr; + unsigned _simdLane = 0; + + DPScout_(TScoutState & pState) : TBase(), state(&pState) + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction ScoutSpecForSimdAlignment_ +// ---------------------------------------------------------------------------- + +template +struct ScoutSpecForAlignmentAlgorithm_ > +{ + typedef SimdAlignmentScout Type; +}; + +template +struct ScoutSpecForAlignmentAlgorithm_ > > +{ + typedef SimdAlignmentScout > Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _copySimdCell() +// ---------------------------------------------------------------------------- + +template +inline void +_copySimdCell(DPScout_, SimdAlignmentScout > & dpScout, + DPCell_ const & activeCell, + TScoreValue const & cmp) +{ + dpScout._maxScore._score = blend(dpScout._maxScore._score, activeCell._score, cmp); +} + +template +inline void +_copySimdCell(DPScout_, SimdAlignmentScout > & dpScout, + DPCell_ const & activeCell, + TScoreValue const & cmp) +{ + dpScout._maxScore._score = blend(dpScout._maxScore._score, activeCell._score, cmp); + dpScout._maxScore._horizontalScore = blend(dpScout._maxScore._horizontalScore, activeCell._horizontalScore, cmp); + dpScout._maxScore._verticalScore = blend(dpScout._maxScore._verticalScore, activeCell._verticalScore, cmp); +} + +template +inline void +_copySimdCell(DPScout_, SimdAlignmentScout > & dpScout, + DPCell_ const & activeCell, + TScoreValue const & cmp) +{ + dpScout._maxScore._score = blend(dpScout._maxScore._score, activeCell._score, cmp); + dpScout._maxScore._flagMask = blend(dpScout._maxScore._flagMask, activeCell._flagMask, cmp); +} + +// ---------------------------------------------------------------------------- +// Function _updateHostPositions() +// ---------------------------------------------------------------------------- + +template +inline void +_updateHostPositions(DPScout_ & dpScout, + TSimdVec & cmp, + SimdVector::Type positionNavigator) +{ +// TODO(rrahn): Refactor! +#if defined(__AVX2__) + dpScout._maxHostLow = blend(dpScout._maxHostLow, positionNavigator, + _mm256_cvtepi16_epi32(_mm256_castsi256_si128(reinterpret_cast<__m256i&>(cmp)))); + dpScout._maxHostHigh = blend(dpScout._maxHostHigh, positionNavigator, + _mm256_cvtepi16_epi32(_mm256_extractf128_si256(reinterpret_cast<__m256i&>(cmp),1))); +#elif defined(__SSE3__) + dpScout._maxHostLow = blend(dpScout._maxHostLow, positionNavigator, + _mm_unpacklo_epi16(reinterpret_cast<__m128i&>(cmp), reinterpret_cast<__m128i&>(cmp))); + dpScout._maxHostHigh = blend(dpScout._maxHostHigh, positionNavigator, + _mm_unpackhi_epi16(reinterpret_cast<__m128i&>(cmp), reinterpret_cast<__m128i&>(cmp))); +#endif +} + +// ---------------------------------------------------------------------------- +// Function _scoutBestScore() +// ---------------------------------------------------------------------------- + +template +inline void +_scoutBestScore(DPScout_ > & dpScout, + TDPCell const & activeCell, + TTraceMatrixNavigator const & navigator, + TIsLastColumn const & /**/, + TIsLastRow const & /**/) +{ + auto cmp = cmpGt(_scoreOfCell(activeCell), _scoreOfCell(dpScout._maxScore)); + _copySimdCell(dpScout, activeCell, cmp); + _updateHostPositions(dpScout, cmp, createVector::Type>(position(navigator))); +} + +template +inline void +_scoutBestScore(DPScout_ > > & dpScout, + TDPCell const & activeCell, + TTraceMatrixNavigator const & navigator, + TIsLastColumn const & /**/, + TIsLastRow const & /**/) +{ + auto cmp = cmpGt(_scoreOfCell(activeCell), _scoreOfCell(dpScout._maxScore)); + cmp &= dpScout.state->masks[dpScout.state->posV]; + _copySimdCell(dpScout, activeCell, cmp); + _updateHostPositions(dpScout, cmp, createVector::Type>(position(navigator))); +} + +// ---------------------------------------------------------------------------- +// Function maxHostPosition() +// ---------------------------------------------------------------------------- + +template +inline unsigned int +maxHostPosition(DPScout_ > const & dpScout) +{ + if(dpScout._simdLane < LENGTH::Type>::VALUE) + return value(dpScout._maxHostLow, dpScout._simdLane); + else + return value(dpScout._maxHostHigh, dpScout._simdLane - LENGTH::Type>::VALUE); +} + +// ---------------------------------------------------------------------------- +// Function _setSimdLane() +// ---------------------------------------------------------------------------- + +template +inline void +_setSimdLane(DPScout_ & dpScout, TPosition const pos) +{ + dpScout._simdLane = pos; +} + +// ---------------------------------------------------------------------------- +// Function _preInitScoutHorizontal() +// ---------------------------------------------------------------------------- + +template +inline void +_preInitScoutHorizontal(DPScout_ > > & scout) +{ + scout.state->nextEndsH = begin(scout.state->sortedEndsH, Standard()); + scout.state->posH = 0; +} + +// ---------------------------------------------------------------------------- +// Function _preInitScoutVertical() +// ---------------------------------------------------------------------------- + +template +inline void +_preInitScoutVertical(DPScout_ > > & scout) +{ + scout.state->updateMasks(); + scout.state->nextEndsV = begin(scout.state->sortedEndsV, Standard()); + scout.state->posV = 0; +} + +// ---------------------------------------------------------------------------- +// Function _reachedHorizontalEndPoint() +// ---------------------------------------------------------------------------- + +template +inline bool +_reachedHorizontalEndPoint(DPScout_ > > & scout, + TIter const & hIt) +{ + return *(scout.state->nextEndsH) == position(hIt); +} + +// ---------------------------------------------------------------------------- +// Function _reachedVerticalEndPoint() +// ---------------------------------------------------------------------------- + +template +inline bool +_reachedVerticalEndPoint(DPScout_ > > & scout, + TIter const & vIt) +{ + return *(scout.state->nextEndsV) == position(vIt); +} + +// ---------------------------------------------------------------------------- +// Function _nextHorizontalEndPos() +// ---------------------------------------------------------------------------- + +template +inline void +_nextHorizontalEndPos(DPScout_ > > & scout) +{ + auto oldLength = *scout.state->nextEndsH; + while (scout.state->nextEndsH != end(scout.state->sortedEndsH, Standard()) && + *scout.state->nextEndsH == oldLength) + { + ++scout.state->nextEndsH; + } +} + +// ---------------------------------------------------------------------------- +// Function _nextVerticalEndPos() +// ---------------------------------------------------------------------------- + +template +inline void +_nextVerticalEndPos(DPScout_ > > & scout) +{ + auto oldLength = *scout.state->nextEndsV; + while (scout.state->nextEndsV != end(scout.state->sortedEndsV, Standard()) && + *scout.state->nextEndsV == oldLength) + { + ++scout.state->nextEndsV; + } +} + +// ---------------------------------------------------------------------------- +// Function _incHorizontalPos() +// ---------------------------------------------------------------------------- + +template +inline void +_incHorizontalPos(DPScout_ > > & scout) +{ + ++scout.state->posH; +} + +// ---------------------------------------------------------------------------- +// Function _incVerticalPos() +// ---------------------------------------------------------------------------- + +template +inline void +_incVerticalPos(DPScout_ > > & scout) +{ + ++scout.state->posV; +} + +// ---------------------------------------------------------------------------- +// Function _hostLengthH() +// ---------------------------------------------------------------------------- + +template +inline auto +_hostLengthH(DPScout_ > const & /*scout*/, + TSeqH const & seqH) +{ + return length(seqH); +} + +template +inline auto +_hostLengthH(DPScout_ > > const & scout, + TSeqH const & /*seqH*/) +{ + return host(scout.state->sortedEndsH)[scout._simdLane] + 1; +} + +// ---------------------------------------------------------------------------- +// Function _hostLengthV() +// ---------------------------------------------------------------------------- + +template +inline auto +_hostLengthV(DPScout_ > const & /*scout*/, + TSeqV const & seqV) +{ + return length(seqV); +} + +template +inline auto +_hostLengthV(DPScout_ > > const & scout, + TSeqV const & /*seqV*/) +{ + return host(scout.state->sortedEndsV)[scout._simdLane] + 1; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_SIMD_DP_SCOUT_SIMD_H_ + diff --git a/seqan/align/dp_setup.h b/seqan/align/dp_setup.h new file mode 100644 index 0000000..29bf429 --- /dev/null +++ b/seqan/align/dp_setup.h @@ -0,0 +1,332 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_SETUP_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_SETUP_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// SubstituteAlignConfig_ +// ---------------------------------------------------------------------------- + +template +struct SubstituteAlignConfig_; + +// 0000 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + +// 0001 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + +// 0010 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 0011 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 0100 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 0101 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 0110 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 0111 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 1000 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 1001 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 1010 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 1011 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 1100 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 1101 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + + +// 1110 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + +// 1111 +template +struct SubstituteAlignConfig_ > +{ + typedef FreeEndGaps_ Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction SubstituteAlgoTag_ +// ---------------------------------------------------------------------------- + +// NOTE(rmaerker): Needed to substitute the global alingment algo tags to the correct gap model. +template +struct SubstituteAlgoTag_ +{ + typedef TTag Type; +}; + +template <> +struct SubstituteAlgoTag_ +{ + typedef LinearGaps Type; +}; + +template <> +struct SubstituteAlgoTag_ +{ + typedef AffineGaps Type; +}; + +// ---------------------------------------------------------------------------- +// SetUpAlignmentProfile +// ---------------------------------------------------------------------------- + +template +struct SetupAlignmentProfile_; + +// Profile for Needleman-Wunsch algorithm. +template +struct SetupAlignmentProfile_ +{ + typedef DPProfile_, TGapCosts, TTraceSwitch> Type; +}; + +// Profile for Smith-Waterman algorithm. +template +struct SetupAlignmentProfile_ +{ + typedef DPProfile_, TGapCosts, TTraceSwitch> Type; +}; + +// Profile for Waterman-Eggert algorithm +template +struct SetupAlignmentProfile_ +{ + typedef DPProfile_, TGapCosts, TracebackOn > > Type; +}; + + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _usesAffineGaps() +// ---------------------------------------------------------------------------- + +template +inline bool +_usesAffineGaps(TScoringScheme const & scoringScheme, + TSeqH const & seqH, + TSeqV const & seqV) +{ + typedef typename SequenceEntryForScore::Type TSequenceHEntry; + typedef typename SequenceEntryForScore::Type TSequenceVEntry; + + TSequenceHEntry seqHEntry = sequenceEntryForScore(scoringScheme, seqH, 0); + TSequenceVEntry seqVEntry = sequenceEntryForScore(scoringScheme, seqV, 0); + + return (scoreGapExtendHorizontal(scoringScheme, seqHEntry, seqVEntry) != + scoreGapOpenHorizontal(scoringScheme, seqHEntry, seqVEntry)) || + (scoreGapExtendVertical(scoringScheme, seqHEntry, seqVEntry) != + scoreGapOpenVertical(scoringScheme, seqHEntry, seqVEntry)); +} + +// ---------------------------------------------------------------------------- +// Function _setUpAndRunAlignment() +// ---------------------------------------------------------------------------- + +template +typename Value >::Type +_setUpAndRunAlignment(DPContext & dpContext, + TTrace & traceSegments, + DPScoutState_ & dpScoutState, + TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme, + AlignConfig2 const & alignConfig) +{ + SEQAN_ASSERT_GEQ(length(seqH), 1u); + SEQAN_ASSERT_GEQ(length(seqV), 1u); + + typedef typename SetupAlignmentProfile_::Type TDPProfile; + return _computeAlignment(dpContext, traceSegments, dpScoutState, seqH, seqV, scoringScheme, alignConfig._band, + TDPProfile()); +} + +template +typename Value >::Type +_setUpAndRunAlignment(TTrace & traceSegments, + DPScoutState_ & dpScoutState, + TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme, + AlignConfig2 const & alignConfig, + TGapModel const & /**/) +{ + DPContext dpContext; + return _setUpAndRunAlignment(dpContext, traceSegments, dpScoutState, seqH, seqV, scoringScheme, alignConfig); +} + +template +typename Value >::Type +_setUpAndRunAlignment(TTrace & traceSegments, + DPScoutState_ & dpScoutState, + TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme, + AlignConfig2 const & alignConfig) +{ + if (_usesAffineGaps(scoringScheme, seqH, seqV)) + return _setUpAndRunAlignment(traceSegments, dpScoutState, seqH, seqV, scoringScheme, alignConfig, AffineGaps()); + else + return _setUpAndRunAlignment(traceSegments, dpScoutState, seqH, seqV, scoringScheme, alignConfig, LinearGaps()); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_SETUP_H_ diff --git a/seqan/align/dp_trace_segment.h b/seqan/align/dp_trace_segment.h new file mode 100644 index 0000000..2b591be --- /dev/null +++ b/seqan/align/dp_trace_segment.h @@ -0,0 +1,341 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// +// The TraceSegment structure is used to store the traceback in a common +// structure such that we can easiely adapt them afterwards in the +// user-defined structure, such as Align or AlignmentGraph objects. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_TRACE_SEGMENT_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_TRACE_SEGMENT_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class TraceSegment +// ---------------------------------------------------------------------------- + +// TraceSegments are used as a common interface to all structures that can represent an alignment. +// +// See alignment_dp_traceback_adaptor.h to find methods for adaption. +template +class TraceSegment_ +{ +public: + typedef typename TraceBitMap_<>::Type TTraceValue; + + TPosition _horizontalBeginPos; // the begin position in horizontal dimension + TPosition _verticalBeginPos; // the begin position in vertical dimension + TSize _length; // the length of the segment + TTraceValue _traceValue; // the trace direction + + TraceSegment_() : + _horizontalBeginPos(0), _verticalBeginPos(0), _length(0), _traceValue(+TraceBitMap_::NONE){} + + TraceSegment_(TraceSegment_ const & other) : + _horizontalBeginPos(other._horizontalBeginPos), + _verticalBeginPos(other._verticalBeginPos), + _length(other._length), + _traceValue(other._traceValue) {} + + TraceSegment_(TPosition const & horizontalBeginPos, TPosition const & verticalBeginPos, TSize const & length, + TTraceValue const & traceValue) : + _horizontalBeginPos(horizontalBeginPos), + _verticalBeginPos(verticalBeginPos), + _length(length), + _traceValue(traceValue) {} + + TraceSegment_ & + operator=(TraceSegment_ const & other) + { + if (this != &other) + { + _horizontalBeginPos = other._horizontalBeginPos; + _verticalBeginPos = other._verticalBeginPos; + _length = other._length; + _traceValue = other._traceValue; + } + return *this; + } + +}; + + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Position +// ---------------------------------------------------------------------------- + +template +struct Position > +{ + typedef TPosition Type; +}; + +template +struct Position const>: + Position >{}; + +// ---------------------------------------------------------------------------- +// Metafunction Size +// ---------------------------------------------------------------------------- + +template +struct Size > +{ + typedef TSize Type; +}; + +template +struct Size const>: + Size >{}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _getBeginHorizontal() +// ---------------------------------------------------------------------------- + +// The begin position of the segment in horizontal dimension. +template +inline TPosition +_getBeginHorizontal(TraceSegment_ const & traceSegment) +{ + return traceSegment._horizontalBeginPos; +} + +// ---------------------------------------------------------------------------- +// Function _getBeginVertical() +// ---------------------------------------------------------------------------- + +// The begin position of the segment in vertical dimension. +template +inline TPosition +_getBeginVertical(TraceSegment_ const & traceSegment) +{ + return traceSegment._verticalBeginPos; +} + +// ---------------------------------------------------------------------------- +// Function _getEndHorizontal() +// ---------------------------------------------------------------------------- + +// The end position of the segment in horizontal dimension. +template +inline TPosition +_getEndHorizontal(TraceSegment_ const & traceSegment) +{ + typedef typename std::remove_const::type TTraceValue; + if (traceSegment._traceValue & (TraceBitMap_::HORIZONTAL | TraceBitMap_::DIAGONAL)) + { + return traceSegment._horizontalBeginPos + traceSegment._length; + } + return traceSegment._horizontalBeginPos; +} + +// ---------------------------------------------------------------------------- +// Function _getEndVertical() +// ---------------------------------------------------------------------------- + +// The end position of the segment in vertical dimension. +template +inline TPosition +_getEndVertical(TraceSegment_ const & traceSegment) +{ + typedef typename std::remove_const::type TTraceValue; + if (traceSegment._traceValue & (TraceBitMap_::VERTICAL | TraceBitMap_::DIAGONAL)) + { + return traceSegment._verticalBeginPos + traceSegment._length; + } + return traceSegment._verticalBeginPos; +} + +// ---------------------------------------------------------------------------- +// Function _getTraceValue() +// ---------------------------------------------------------------------------- + +// The end position of the segment in vertical dimension. +template +inline typename TraceSegment_::TTraceValue +_getTraceValue(TraceSegment_ const & traceSegment) +{ + return traceSegment._traceValue; +} + +// ---------------------------------------------------------------------------- +// Function length() +// ---------------------------------------------------------------------------- + +// The length of the segment. +template +inline TSize +length(TraceSegment_ const & traceSegment) +{ + return traceSegment._length; +} + +// ---------------------------------------------------------------------------- +// Function _setLength() +// ---------------------------------------------------------------------------- + +// The length of the segment. +template +inline void +_setLength(TraceSegment_ & traceSegment, TSize newLength) +{ + traceSegment._length = newLength; +} + +// ---------------------------------------------------------------------------- +// Function _translateTraceValue() +// ---------------------------------------------------------------------------- + +// Translates the trace value into a human-readable format. +// +// Note, used for debugging reasons only. +template +String _translateTraceValue(TTraceValue const & traceValue) +{ + String transcript; + + if ((traceValue & TraceBitMap_::DIAGONAL) == TraceBitMap_::DIAGONAL) + append(transcript, 'D'); + if ((traceValue & TraceBitMap_::VERTICAL) == TraceBitMap_::VERTICAL) + append(transcript, 'V'); + if ((traceValue & TraceBitMap_::HORIZONTAL) == TraceBitMap_::HORIZONTAL) + append(transcript, 'H'); + if ((traceValue & TraceBitMap_::VERTICAL_OPEN) == TraceBitMap_::VERTICAL_OPEN) + append(transcript, 'v'); + if ((traceValue & TraceBitMap_::HORIZONTAL_OPEN) == TraceBitMap_::HORIZONTAL_OPEN) + append(transcript, 'h'); + if ((traceValue & TraceBitMap_::MAX_FROM_VERTICAL_MATRIX) == TraceBitMap_::MAX_FROM_VERTICAL_MATRIX) + append(transcript, '|'); + if ((traceValue & TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX) == TraceBitMap_::MAX_FROM_HORIZONTAL_MATRIX) + append(transcript, '-'); + + if ((traceValue) == TraceBitMap_::NONE) + append(transcript, '0'); + return transcript; +} + +// ---------------------------------------------------------------------------- +// Function oerpator<<() +// ---------------------------------------------------------------------------- + +template +TStream & operator<<(TStream & stream, TraceSegment_ const & traceSegment) +{ + stream << _translateTraceValue(traceSegment._traceValue) << "-"; + stream << "(" << traceSegment._horizontalBeginPos << ", " << traceSegment._verticalBeginPos << ", " << + traceSegment._length << ")"; + return stream; +} + +// ---------------------------------------------------------------------------- +// Function oerpator==() +// ---------------------------------------------------------------------------- + +template +inline bool operator==(TraceSegment_ const & left, TraceSegment_ const & right) +{ + if (left._horizontalBeginPos != right._horizontalBeginPos) + return false; + + if (left._verticalBeginPos != right._verticalBeginPos) + return false; + + if (left._length != right._length) + return false; + + if (left._traceValue != right._traceValue) + return false; + + return true; +} + +// ---------------------------------------------------------------------------- +// Function oerpator!=() +// ---------------------------------------------------------------------------- + +template +inline bool operator!=(TraceSegment_ const & left, TraceSegment_ const & right) +{ + return !(left == right); +} + +// ---------------------------------------------------------------------------- +// Function recordSegment() +// ---------------------------------------------------------------------------- + +// Records a segment given the horizontal and vertical begin position, the length, +// and the corrsponding trace value. +// +// The first parameter is the container the segment is recorded to. +template +inline void _recordSegment(TTraceSegments & traceSegments, + TPositionH const & horizontalBeginPos, + TPositionV const & verticalBeginPos, + TSize const & segmentLength, + TTraceValue const & traceValue) +{ + typedef typename Value::Type TTraceSegment; + + if (segmentLength == 0) + return; // we don't store empty segments + + if (traceValue & TraceBitMap_::DIAGONAL) + appendValue(traceSegments, TTraceSegment(horizontalBeginPos, verticalBeginPos, segmentLength, +TraceBitMap_::DIAGONAL)); + else if (traceValue & TraceBitMap_::VERTICAL) + appendValue(traceSegments, TTraceSegment(horizontalBeginPos, verticalBeginPos, segmentLength, +TraceBitMap_::VERTICAL)); + else if (traceValue & TraceBitMap_::HORIZONTAL) + appendValue(traceSegments, TTraceSegment(horizontalBeginPos, verticalBeginPos, segmentLength, +TraceBitMap_::HORIZONTAL)); + // everything else is not tracked. +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_TRACE_SEGMENT_H_ diff --git a/seqan/align/dp_traceback_adaptor.h b/seqan/align/dp_traceback_adaptor.h new file mode 100644 index 0000000..f9e495f --- /dev/null +++ b/seqan/align/dp_traceback_adaptor.h @@ -0,0 +1,321 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Rene Rahn +// ========================================================================== +// Adaptor methods to transcribe a set of trace segments into the +// alignment representing structure. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_TRACEBACK_ADAPTOR_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_TRACEBACK_ADAPTOR_H_ + +namespace seqan { + +// ---------------------------------------------------------------------------- +// Function _writeTraceSegmentToFile() +// ---------------------------------------------------------------------------- + +template +inline void _writeTraceSegmentToFile(TFile & file, TSeq0Value const & seq0Val, TSeq1Value const & seq1Val) +{ + file << '(' << seq0Val << ',' << seq1Val << ")\n"; +} + +// ---------------------------------------------------------------------------- +// Function _adaptTraceSegmentsTo() [Gaps] +// ---------------------------------------------------------------------------- + +template +void +_adaptTraceSegmentsTo(Gaps & gapsHorizontal, + Gaps & gapsVertical, + String, TStringSpec> const & traceSegments) +{ + typedef Gaps TGapsHorizontal; + typedef Gaps TGapsVertical; + typedef typename Iterator::Type TIteratorHorizontal; + typedef typename Iterator::Type TIteratorVertical; + typedef TraceSegment_ TTraceSegment; + typedef typename Iterator const>::Type TTraceIterator; + + clearGaps(gapsHorizontal); + clearClipping(gapsHorizontal); + + clearGaps(gapsVertical); + clearClipping(gapsVertical); + + // Set clipping to 0 + if (empty(traceSegments)) + { + setClippedBeginPosition(gapsHorizontal, 0); + setClippedEndPosition(gapsHorizontal, 0); + setClippedBeginPosition(gapsVertical, 0); + setClippedEndPosition(gapsVertical, 0); + return; + } + + TTraceIterator srcIter = end(traceSegments) - 1; + TTraceIterator srcEnd = begin(traceSegments) - 1; + + // we build the gap structure here. + // set the clipped begin position of the alignment. + setBeginPosition(gapsHorizontal, _getBeginHorizontal(value(srcIter))); // begin of source + setBeginPosition(gapsVertical, _getBeginVertical(value(srcIter))); + + TIteratorHorizontal it0 = begin(gapsHorizontal); + TIteratorVertical it1 = begin(gapsVertical); + + while (srcIter != srcEnd) + { + TSize segmentSize = value(srcIter)._length; + switch (value(srcIter)._traceValue) + { + case TraceBitMap_<>::HORIZONTAL: + insertGaps(it1, segmentSize); + break; + + case TraceBitMap_<>::VERTICAL: + insertGaps(it0, segmentSize); + break; + } + goFurther(it0, segmentSize); + goFurther(it1, segmentSize); + --srcIter; + } + setClippedEndPosition(gapsHorizontal, position(it0) + clippedBeginPosition(gapsHorizontal)); + setClippedEndPosition(gapsVertical, position(it1) + clippedBeginPosition(gapsVertical)); +} + +// ---------------------------------------------------------------------------- +// Function _adaptTraceSegmentsTo() [AlignmentGraph] +// ---------------------------------------------------------------------------- + +template +inline void +_adaptTraceSegmentsTo(Graph > & g, + TSequenceIdH const & seqHId, + TSequenceIdV const & seqVId, + String, TStringSpec> const & traceSegments) +{ + typedef TraceSegment_ TTraceSegment; + // check begin and end positions of the graph. + + // Not safe! + + if (empty(traceSegments)) + return; + + // insert leading gaps + TTraceSegment traceBegin = traceSegments[length(traceSegments) - 1]; + if (_getBeginVertical(traceBegin) != 0) + addVertex(g, seqVId, 0, _getBeginVertical(traceBegin)); + if (_getBeginHorizontal(traceBegin) != 0) + addVertex(g, seqHId, 0, _getBeginHorizontal(traceBegin)); + + + for (TSize i = 0; i < length(traceSegments); ++i) + { + + switch (traceSegments[i]._traceValue) + { + case TraceBitMap_<>::DIAGONAL: + addEdge(g, addVertex(g, seqHId, traceSegments[i]._horizontalBeginPos, traceSegments[i]._length), + addVertex(g, seqVId, traceSegments[i]._verticalBeginPos, traceSegments[i]._length)); + break; + + case TraceBitMap_<>::VERTICAL: + addVertex(g, seqVId, traceSegments[i]._verticalBeginPos, traceSegments[i]._length); + break; + + case TraceBitMap_<>::HORIZONTAL: + addVertex(g, seqHId, traceSegments[i]._horizontalBeginPos, traceSegments[i]._length); + } + } + + // insert trailing gaps + TTraceSegment traceEnd = traceSegments[0]; + + if (_getEndVertical(traceEnd) != length(value(stringSet(g), idToPosition(stringSet(g), seqVId)))) + addVertex(g, seqVId, _getEndVertical(traceEnd), + length(value(stringSet(g), idToPosition(stringSet(g), seqVId))) - _getEndVertical(traceEnd)); + + if (_getEndHorizontal(traceEnd) != length(value(stringSet(g), idToPosition(stringSet(g), seqHId)))) + addVertex(g, seqHId, _getEndHorizontal(traceEnd), + length(value(stringSet(g), idToPosition(stringSet(g), seqHId))) - _getEndHorizontal(traceEnd)); +} + +// ---------------------------------------------------------------------------- +// Function _adaptTraceSegmentsTo() [File] +// ---------------------------------------------------------------------------- + +template +inline void +_adaptTraceSegmentsTo(TFile & file, + TSequenceH const & seqH, + TSequenceV const & seqV, + String, TStringSpec> const & traceSegments) +{ + for (TSize k = length(traceSegments); k > (TSize) 0; --k) + { + switch (traceSegments[k - 1]._traceValue) + { + case TraceBitMap_<>::DIAGONAL: + { + int j = traceSegments[k - 1]._verticalBeginPos; + for (int i = traceSegments[k - 1]._horizontalBeginPos; i < (int) (traceSegments[k - 1]._horizontalBeginPos + traceSegments[k - 1]._length); ++i) + { + _writeTraceSegmentToFile(file, seqH[i], seqV[j]); + ++j; + } + break; + } + + case TraceBitMap_<>::VERTICAL: + { + for (int i = traceSegments[k - 1]._verticalBeginPos; i < (int) (traceSegments[k - 1]._verticalBeginPos + traceSegments[k - 1]._length); ++i) + _writeTraceSegmentToFile(file, gapValue(), seqV[i]); + break; + } + + case TraceBitMap_<>::HORIZONTAL: + { + for (int i = traceSegments[k - 1]._horizontalBeginPos; i < (int) (traceSegments[k - 1]._horizontalBeginPos + traceSegments[k - 1]._length); ++i) + _writeTraceSegmentToFile(file, seqH[i], gapValue()); + } + } + } +} + +// ---------------------------------------------------------------------------- +// Function _adaptTraceSegmentsTo() [Fragments] +// ---------------------------------------------------------------------------- + +template +inline void +_adaptTraceSegmentsTo(String, TStringSpec> & matches, + TSequenceH const & seqHId, + TSequenceV const & seqVId, + String, TStringSpec2> const & traceSegments) +{ + typedef Fragment TFragment; + + for (TSize2 i = 0; i < length(traceSegments); ++i) + if (traceSegments[i]._traceValue == TraceBitMap_<>::DIAGONAL) + appendValue( + matches, + TFragment(seqHId, traceSegments[i]._horizontalBeginPos, seqVId, + traceSegments[i]._verticalBeginPos, traceSegments[i]._length), + Generous()); +} + +// ---------------------------------------------------------------------------- +// Function _adaptTraceSegmentsTo() [VertexDescriptor] +// ---------------------------------------------------------------------------- + +//// TODO (rmaerker): Check if we really need this! +//template +//inline void +//_adaptTraceSegmentsTo(String > & /*nodeString*/, +// TSequence0 const & /*seq0*/, +// TSequence1 const & /*seq1*/, +// String, TStringSpec> const & /*traceSegments*/) +//{ +// typedef String TVertexDescriptorString; +// typedef typename Size::Type TSize; +// typedef typename Iterator::Type TStringIter; +// TVertexDescriptor nilVertex = getNil(); + + +// TODO (rmaerker): see how to adapt this code here for the new structure. +// // TraceBack values +// TTraceValue Diagonal = 0; TTraceValue Horizontal = 1; TTraceValue Vertical = 2; +// +// if (segLen == 0) return; +// // Number of vertex descriptors in the first string at any position (e.g., group of 5 sequences = group of 5 vertex descriptors) +// TSize len1 = length(getValue(getValue(str,0), 0)); +// // Number of vertex descriptors in the second string at any position (e.g., group of 5 sequences = group of 5 vertex descriptors) +// TSize len2 = length(getValue(getValue(str,1), 0)); +// +// // Resize the node string +// TSize index = length(nodeString); +// resize(nodeString, index + segLen); +// +// if (tv == Horizontal) { +// for (int i = pos1 + segLen - 1; i>= (int) pos1;--i) { +// resize(value(nodeString, index), len1 + len2, nilVertex); +// TStringIter it = begin(value(nodeString, index)); +// for(TPos all = 0;all= (int) pos2;--i) { +// resize(value(nodeString, index), len1 + len2, nilVertex); +// TStringIter it = begin(value(nodeString, index)); +// it+=len1; +// for(TPos all = 0;all= (int) pos1;--i) { +// resize(value(nodeString, index), len1 + len2); +// TStringIter it = begin(value(nodeString, index)); +// for(TPos all = 0;all +// ========================================================================== +// Implements the traceback algorithm. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_TRACEBACK_IMPL_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_DP_TRACEBACK_IMPL_H_ + +// TODO(holtgrew): GapsRight traceback is currently untested. +// TODO(rmaerker): Change Tracback to TraceConfig | TraceBackOff + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class TracebackCoordinator_ +// ---------------------------------------------------------------------------- + +template +class TracebackCoordinator_ +{ +public: + TPosition _currColumn; + TPosition _currRow; + TPosition _endColumn; + TPosition _endRow; + TPosition _breakpoint1; // First breakpoint where banded trace switches to unbanded trace. + TPosition _breakpoint2; // Second breakpoint where unbanded trace switches back to banded trace. Only if begin of upper diagonal is bigger than end of lower diagonal. + bool _isInBand; + + template + TracebackCoordinator_(TPosition currColumn, + TPosition currRow, + DPBandConfig const & band, + TSizeH seqHSize, + TSizeV seqVSize) + : _currColumn(currColumn), + _currRow(currRow), + _endColumn(0u), + _endRow(0u), + _breakpoint1(0u), + _breakpoint2(0u), + _isInBand(false) + { + _initTracebackCoordinator(*this, band, seqHSize, seqVSize); + } + + template + TracebackCoordinator_(TPosition currColumn, + TPosition currRow, + TPosition endColumn, + TPosition endRow, + DPBandConfig const & band, + TSizeH seqHSize, + TSizeV seqVSize) + : _currColumn(currColumn), + _currRow(currRow), + _endColumn(endColumn), + _endRow(endRow), + _breakpoint1(0u), + _breakpoint2(0u), + _isInBand(false) + { + _initTracebackCoordinator(*this, band, seqHSize, seqVSize); + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction PreferGapsAtEnd_ +// ---------------------------------------------------------------------------- + +// Checks whether the gaps at the end should be preferred over a matching area. +template +struct PreferGapsAtEnd_ : False{}; + +template +struct PreferGapsAtEnd_ > : True{}; + +template +struct PreferGapsAtEnd_ > > > : True{}; + + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _hasReachedEnd() +// ---------------------------------------------------------------------------- + +template +inline bool +_hasReachedEnd(TracebackCoordinator_ const & coordinator) +{ + return coordinator._currColumn <= coordinator._endColumn || coordinator._currRow <= coordinator._endRow; +} + +// ---------------------------------------------------------------------------- +// Function _initTracebackCoordinator() +// ---------------------------------------------------------------------------- + +template +inline void +_initTracebackCoordinator(TracebackCoordinator_ & coordinator, + DPBandConfig const & band, + TSizeH seqHSize, + TSizeV seqVSize) +{ + typedef typename Position >::Type TBandPosition; + if (IsSameType::VALUE) + { + // Adapt the current column value when the lower diagonal is positive (shift right in horizontal direction). + if (lowerDiagonal(band) >= 0) + coordinator._currColumn += static_cast(lowerDiagonal(band)); + // Adapt the current row value when the current column comes after the upper diagonal (shift down in vertical direction). + if (static_cast(coordinator._currColumn) > upperDiagonal(band)) + coordinator._currRow += coordinator._currColumn - upperDiagonal(band); + // Adapt the end row value when the end column comes after the upper diagonal (shift down in vertical direction). + if (static_cast(coordinator._endColumn) > upperDiagonal(band)) + coordinator._endRow += coordinator._endColumn - upperDiagonal(band); + + coordinator._breakpoint1 = _min(seqHSize, static_cast(_max(0, upperDiagonal(band)))); + coordinator._breakpoint2 = _min(seqHSize, static_cast(_max(0, static_cast(seqVSize) + + lowerDiagonal(band)))); + // Update the current row if the current column is before the upper diagoal or the first column where the maximal band size is reached. + if (coordinator._currColumn < _min(coordinator._breakpoint1, coordinator._breakpoint2)) + coordinator._currRow -= _min(coordinator._breakpoint1, coordinator._breakpoint2) - coordinator._currColumn; + coordinator._isInBand = true; + } +} + +// ---------------------------------------------------------------------------- +// Function _isInBand() +// ---------------------------------------------------------------------------- + +template +inline bool +_isInBand(TracebackCoordinator_ const & coordinator) +{ + if (!coordinator._isInBand) + return coordinator._isInBand; + return (coordinator._currColumn > coordinator._breakpoint1 || coordinator._currColumn <= coordinator._breakpoint2); +} + + +// ---------------------------------------------------------------------------- +// Function _doTracebackGoDiagonal() +// ---------------------------------------------------------------------------- + +template +inline void +_doTracebackGoDiagonal(TTarget & target, + TDPTraceMatrixNavigator & matrixNavigator, + TTraceValue & traceValue, + TTraceValue & lastTraceValue, + TSize & fragmentLength, + TracebackCoordinator_ & tracebackCoordinator, + TGapCosts const &) +{ + if (!(lastTraceValue & TraceBitMap_<>::DIAGONAL)) // the old trace value was not diagonal + { + _recordSegment(target, tracebackCoordinator._currColumn, tracebackCoordinator._currRow, fragmentLength, + lastTraceValue); + + lastTraceValue = TraceBitMap_<>::DIAGONAL; + fragmentLength = 0; + } + _traceDiagonal(matrixNavigator, _isInBand(tracebackCoordinator)); + traceValue = scalarValue(matrixNavigator); + --tracebackCoordinator._currColumn; + --tracebackCoordinator._currRow; + ++fragmentLength; +} + +// ---------------------------------------------------------------------------- +// Function _doTracebackGoVertical() +// ---------------------------------------------------------------------------- + +template +inline void +_doTracebackGoVertical(TTarget & target, + TDPTraceMatrixNavigator & matrixNavigator, + TTraceValue & traceValue, + TTraceValue & lastTraceValue, + TSize & fragmentLength, + TracebackCoordinator_ & tracebackCoordinator, + TGapCosts const &) +{ + if (!(lastTraceValue & TraceBitMap_<>::VERTICAL)) // the old trace value was not diagonal + { + _recordSegment(target, tracebackCoordinator._currColumn, tracebackCoordinator._currRow, fragmentLength, + lastTraceValue); + + lastTraceValue = TraceBitMap_<>::VERTICAL; + fragmentLength = 0; + } + // We are in a vertical gap. So continue after we reach the end of the vertical gap. + if (IsSameType::VALUE) + { + while ((!(traceValue & TraceBitMap_<>::VERTICAL_OPEN) || (traceValue & TraceBitMap_<>::VERTICAL)) && (tracebackCoordinator._currRow != 1)) + { + _traceVertical(matrixNavigator, _isInBand(tracebackCoordinator)); + traceValue = scalarValue(matrixNavigator); + --tracebackCoordinator._currRow; + ++fragmentLength; + } + // We have to ensure, that we do not continue in vertical direction if we reached a vertical_open sign. + _traceVertical(matrixNavigator, _isInBand(tracebackCoordinator)); + // Forbid continuing in vertical direction. + traceValue = scalarValue(matrixNavigator); // & (TraceBitMap_<>::NO_VERTICAL_TRACEBACK | TraceBitMap_<>::MAX_FROM_HORIZONTAL_MATRIX); + --tracebackCoordinator._currRow; + ++fragmentLength; + } + else + { + _traceVertical(matrixNavigator, _isInBand(tracebackCoordinator)); + traceValue = scalarValue(matrixNavigator); + --tracebackCoordinator._currRow; + ++fragmentLength; + } +} + +// ---------------------------------------------------------------------------- +// Function _doTracebackMaxFromVertical() +// ---------------------------------------------------------------------------- + +template +inline void +_doTracebackMaxFromVertical(TTarget & target, + TDPTraceMatrixNavigator & matrixNavigator, + TTraceValue & traceValue, + TTraceValue & lastTraceValue, + TSize & fragmentLength, + TracebackCoordinator_ & tracebackCoordinator, + TGapCosts const &) +{ + if (!(lastTraceValue & TraceBitMap_<>::VERTICAL)) // the old trace value was not diagonal + { + _recordSegment(target, tracebackCoordinator._currColumn, tracebackCoordinator._currRow, fragmentLength, + lastTraceValue); + lastTraceValue = TraceBitMap_<>::VERTICAL; + fragmentLength = 0; + } + _traceVertical(matrixNavigator, _isInBand(tracebackCoordinator)); + // Forbid continuing in vertical direction. + traceValue = scalarValue(matrixNavigator); // & (TraceBitMap_<>::NO_VERTICAL_TRACEBACK | TraceBitMap_<>::MAX_FROM_HORIZONTAL_MATRIX); + --tracebackCoordinator._currRow; + ++fragmentLength; +} + +// ---------------------------------------------------------------------------- +// Function _doTracebackGoHorizontal() +// ---------------------------------------------------------------------------- + +template +inline void +_doTracebackGoHorizontal(TTarget & target, + TDPTraceMatrixNavigator & matrixNavigator, + TTraceValue & traceValue, + TTraceValue & lastTraceValue, + TSize & fragmentLength, + TracebackCoordinator_ & tracebackCoordinator, + TGapCosts const &) +{ + if (!(lastTraceValue & TraceBitMap_<>::HORIZONTAL)) // the old trace value was not diagonal + { + _recordSegment(target, tracebackCoordinator._currColumn, tracebackCoordinator._currRow, fragmentLength, + lastTraceValue); + + lastTraceValue = TraceBitMap_<>::HORIZONTAL; + fragmentLength = 0; + } + if (IsSameType::VALUE) + { + while ((!(traceValue & TraceBitMap_<>::HORIZONTAL_OPEN) || (traceValue & TraceBitMap_<>::HORIZONTAL)) && (tracebackCoordinator._currColumn != 1)) + { + _traceHorizontal(matrixNavigator, _isInBand(tracebackCoordinator)); + traceValue = scalarValue(matrixNavigator); + --tracebackCoordinator._currColumn; + ++fragmentLength; + } + _traceHorizontal(matrixNavigator, _isInBand(tracebackCoordinator)); + // Forbid continuing in horizontal direction. + traceValue = scalarValue(matrixNavigator); // & (TraceBitMap_<>::NO_HORIZONTAL_TRACEBACK | TraceBitMap_<>::MAX_FROM_VERTICAL_MATRIX); + --tracebackCoordinator._currColumn; + ++fragmentLength; + } + else + { + _traceHorizontal(matrixNavigator, _isInBand(tracebackCoordinator)); + traceValue = scalarValue(matrixNavigator); + --tracebackCoordinator._currColumn; + ++fragmentLength; + } +} + +// ---------------------------------------------------------------------------- +// Function _doTracebackMaxFromHorizontal() +// ---------------------------------------------------------------------------- + +template +inline void +_doTracebackMaxFromHorizontal(TTarget & target, + TDPTraceMatrixNavigator & matrixNavigator, + TTraceValue & traceValue, + TTraceValue & lastTraceValue, + TSize & fragmentLength, + TracebackCoordinator_ & tracebackCoordinator, + TGapCosts const &) +{ + if (!(lastTraceValue & TraceBitMap_<>::HORIZONTAL)) // the old trace value was not diagonal + { + _recordSegment(target, tracebackCoordinator._currColumn, tracebackCoordinator._currRow, fragmentLength, + lastTraceValue); + lastTraceValue = TraceBitMap_<>::HORIZONTAL; + fragmentLength = 0; + } + _traceHorizontal(matrixNavigator, _isInBand(tracebackCoordinator)); + // Forbid continuing in horizontal direction. + traceValue = scalarValue(matrixNavigator); // & (TraceBitMap_<>::NO_HORIZONTAL_TRACEBACK | TraceBitMap_<>::MAX_FROM_VERTICAL_MATRIX); + --tracebackCoordinator._currColumn; + ++fragmentLength; +} + +// ---------------------------------------------------------------------------- +// Function _doTraceback() +// ---------------------------------------------------------------------------- + +template +inline void +_doTraceback(TTarget & target, + TDPTraceMatrixNavigator & matrixNavigator, + TTraceValue & traceValue, + TTraceValue & lastTraceValue, + TSize & fragmentLength, + TracebackCoordinator_ & tracebackCoordinator, + TGapCosts const & gapsCost, + TIsGapsLeft const & /*isGapsLeft*/) +{ + if (TIsGapsLeft::VALUE) // Gaps should be placed on the left. + { + if (traceValue & TraceBitMap_<>::DIAGONAL) + { + _doTracebackGoDiagonal(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, gapsCost); + } // In case of Gotoh we prefer the longest possible way in this direction. + else if (traceValue & TraceBitMap_<>::MAX_FROM_VERTICAL_MATRIX && traceValue & TraceBitMap_<>::VERTICAL) + { + _doTracebackGoVertical(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, gapsCost); + } + else if (traceValue & TraceBitMap_<>::MAX_FROM_VERTICAL_MATRIX && traceValue & TraceBitMap_<>::VERTICAL_OPEN) + { + _doTracebackMaxFromVertical(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, gapsCost); + } + else if (traceValue & TraceBitMap_<>::MAX_FROM_HORIZONTAL_MATRIX && traceValue & TraceBitMap_<>::HORIZONTAL) + { + _doTracebackGoHorizontal(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, gapsCost); + } + else if (traceValue & TraceBitMap_<>::MAX_FROM_HORIZONTAL_MATRIX && traceValue & TraceBitMap_<>::HORIZONTAL_OPEN) + { + _doTracebackMaxFromHorizontal(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, gapsCost); + } // In case of Gotoh we prefer the longest possible way in this direction. + else // the trace back is either NONE or something else + { + if (traceValue == TraceBitMap_<>::NONE) + { + return; + } + SEQAN_ASSERT_FAIL("Reached undefined traceback value!"); + } + } + else // Gaps should be placed on the right. + { + if (traceValue & TraceBitMap_<>::MAX_FROM_VERTICAL_MATRIX && traceValue & TraceBitMap_<>::VERTICAL) + { + _doTracebackGoVertical(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, gapsCost); + } + else if (traceValue & TraceBitMap_<>::MAX_FROM_VERTICAL_MATRIX && traceValue & TraceBitMap_<>::VERTICAL_OPEN) + { + _doTracebackMaxFromVertical(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, gapsCost); + } + else if (traceValue & TraceBitMap_<>::MAX_FROM_HORIZONTAL_MATRIX && traceValue & TraceBitMap_<>::HORIZONTAL) + { + _doTracebackGoHorizontal(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, gapsCost); + } + else if (traceValue & TraceBitMap_<>::MAX_FROM_HORIZONTAL_MATRIX && traceValue & TraceBitMap_<>::HORIZONTAL_OPEN) + { + _doTracebackMaxFromHorizontal(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, gapsCost); + } // In case of Gotoh we prefer the longest possible way in this direction. + else if (traceValue & TraceBitMap_<>::DIAGONAL) + { + _doTracebackGoDiagonal(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, gapsCost); + } // In case of Gotoh we prefer the longest possible way in this direction. + else // the trace back is either NONE or something else + { + if (traceValue == TraceBitMap_<>::NONE) + { + return; + } + SEQAN_ASSERT_FAIL("Reached undefined traceback value!"); + } + } +} + +// ---------------------------------------------------------------------------- +// Function _retrieveInitialTraceDirection() +// ---------------------------------------------------------------------------- + +template +inline TTraceValue +_retrieveInitialTraceDirection(TTraceValue & traceValue, TDPProfile const & /*dpProfile*/) +{ + if (PreferGapsAtEnd_::VALUE) + { + if (traceValue & TraceBitMap_<>::MAX_FROM_VERTICAL_MATRIX) + { + traceValue &= (TraceBitMap_<>::VERTICAL | TraceBitMap_<>::VERTICAL_OPEN | TraceBitMap_<>::MAX_FROM_VERTICAL_MATRIX); + return TraceBitMap_<>::VERTICAL; + } + else if (traceValue & TraceBitMap_<>::MAX_FROM_HORIZONTAL_MATRIX) + { + traceValue &= (TraceBitMap_<>::HORIZONTAL | TraceBitMap_<>::HORIZONTAL_OPEN | TraceBitMap_<>::MAX_FROM_HORIZONTAL_MATRIX); + return TraceBitMap_<>::HORIZONTAL; + } + return TraceBitMap_<>::DIAGONAL; // We set the last value to the + } + + if (traceValue & TraceBitMap_<>::DIAGONAL) + return TraceBitMap_<>::DIAGONAL; + if (traceValue & (TraceBitMap_<>::VERTICAL | TraceBitMap_<>::MAX_FROM_VERTICAL_MATRIX)) + return TraceBitMap_<>::VERTICAL; + if (traceValue & (TraceBitMap_<>::HORIZONTAL | TraceBitMap_<>::MAX_FROM_HORIZONTAL_MATRIX)) + return TraceBitMap_<>::HORIZONTAL; + + return TraceBitMap_<>::NONE; +} + +// ---------------------------------------------------------------------------- +// Function _computeTraceback() +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_DISABLE_IF(Is >, void) +_computeTraceback(TTarget & target, + TDPTraceMatrixNavigator & matrixNavigator, + unsigned maxHostPosition, + TSizeH const & seqHSize, + TSizeV const & seqVSize, + DPBandConfig const & band, + DPProfile_ const & dpProfile) +{ + typedef typename Container::Type TContainer; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef typename TraceBitMap_<>::Type TTraceValue; + + if (IsSameType::VALUE) + return; + + // Determine whether or not we place gaps to the left. + typedef typename IsGapsLeft_::Type TIsGapsLeft; + + // Set the navigator to the position where the maximum was found. + _setToPosition(matrixNavigator, maxHostPosition); + + SEQAN_ASSERT_LEQ(coordinate(matrixNavigator, +DPMatrixDimension_::HORIZONTAL), seqHSize); + SEQAN_ASSERT_LEQ(coordinate(matrixNavigator, +DPMatrixDimension_::VERTICAL), seqVSize); + + TTraceValue traceValue = scalarValue(matrixNavigator); + TTraceValue lastTraceValue = _retrieveInitialTraceDirection(traceValue, dpProfile); + + TracebackCoordinator_ tracebackCoordinator(coordinate(matrixNavigator, +DPMatrixDimension_::HORIZONTAL), + coordinate(matrixNavigator, +DPMatrixDimension_::VERTICAL), + band, seqHSize, seqVSize); + + if (TraceTail_::VALUE) + { + if (tracebackCoordinator._currRow != seqVSize) + _recordSegment(target, seqHSize, tracebackCoordinator._currRow, seqVSize - tracebackCoordinator._currRow, + +TraceBitMap_<>::VERTICAL); + if (tracebackCoordinator._currColumn != seqHSize) + _recordSegment(target, tracebackCoordinator._currColumn, tracebackCoordinator._currRow, seqHSize - + tracebackCoordinator._currColumn, +TraceBitMap_<>::HORIZONTAL); + } + + TSize fragmentLength = 0; + while (!_hasReachedEnd(tracebackCoordinator) && traceValue != TraceBitMap_<>::NONE) + _doTraceback(target, matrixNavigator, traceValue, lastTraceValue, fragmentLength, tracebackCoordinator, TGapCosts(), TIsGapsLeft()); + + // Record last detected fragment. + _recordSegment(target, tracebackCoordinator._currColumn, tracebackCoordinator._currRow, fragmentLength, lastTraceValue); + if (TraceHead_::VALUE) + { + // Record leading gaps if any. + if (tracebackCoordinator._currRow != 0u) + _recordSegment(target, 0, 0, tracebackCoordinator._currRow, +TraceBitMap_<>::VERTICAL); + if (tracebackCoordinator._currColumn != 0u) + _recordSegment(target, 0, 0, tracebackCoordinator._currColumn, +TraceBitMap_<>::HORIZONTAL); + } +} + +//// Needed as a delegation method to allow invocation of both methods with host position and dpScout. +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +_computeTraceback(TTarget & target, + TDPTraceMatrixNavigator & matrixNavigator, + unsigned maxHostPosition, + TSequenceH const & seqH, + TSequenceV const & seqV, + DPBandConfig const & band, + DPProfile_ const & dpProfile) +{ + _computeTraceback(target, matrixNavigator, maxHostPosition, length(seqH), length(seqV), band, dpProfile); +} + +template +inline SEQAN_FUNC_DISABLE_IF(Is >, void) +_computeTraceback(TTarget & target, + TDPTraceMatrixNavigator & matrixNavigator, + DPScout_ const & dpScout, + TSizeH const & seqHSize, + TSizeV const & seqVSize, + DPBandConfig const & band, + DPProfile_ const & dpProfile) +{ + _computeTraceback(target, matrixNavigator, maxHostPosition(dpScout), seqHSize, seqVSize, band, dpProfile); +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +_computeTraceback(TTarget & target, + TDPTraceMatrixNavigator & matrixNavigator, + DPScout_ const & dpScout, + TSequenceH const & seqH, + TSequenceV const & seqV, + DPBandConfig const & band, + DPProfile_ const & dpProfile) +{ + _computeTraceback(target, matrixNavigator, maxHostPosition(dpScout), length(seqH), length(seqV), band, dpProfile); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_DP_TRACEBACK_IMPL_H_ diff --git a/seqan/align/evaluate_alignment.h b/seqan/align/evaluate_alignment.h new file mode 100644 index 0000000..e242f2e --- /dev/null +++ b/seqan/align/evaluate_alignment.h @@ -0,0 +1,331 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Compute alignment score given a pairwise alignment. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_ALIGN_EVALUATE_ALIGNMENT_H_ +#define INCLUDE_SEQAN_ALIGN_EVALUATE_ALIGNMENT_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class AlignmentStats +// ---------------------------------------------------------------------------- + +/*! + * @class AlignmentStats + * @headerfile + * @brief Statistics about a tabular alignment. + * + * @signature struct AlignmentStats; + * + * @see computeAlignmentStats + * + * @fn AlignmentStats::AlignmentStats + * @brief Constructor + * + * @signature AlignmentStats::AlignmentStats(); + * + * All members are initialized to 0. + * + * @var unsigned AlignmentStats::numGaps; + * @brief Number of gap characters (sum of numGapOpens and numGapExtensions) + * + * @var unsigned AlignmentStats::numGapOpens; + * @brief Number of gap open events. + * + * @var unsigned AlignmentStats::numGapExtensions; + * @brief Number of gap extension events. + * + * @var unsigned AlignmentStats::numInsertions; + * @brief Number of gaps in reference relative to query. + * + * @var unsigned AlignmentStats::numDeletions; + * @brief Number of gaps in query relative to reference. + * + * @var unsigned AlignmentStats::numMatches; + * @brief Number of match (identity) events. + * + * @var unsigned AlignmentStats::numMismatches; + * @brief Number of mismatch (not identity) events. + * + * @var unsigned AlignmentStats::numPositiveScores; + * @brief Number of residues aligned with positive score (0 is counted as positive). + * + * @var unsigned AlignmentStats::numNegativeScores; + * @brief Number of residues aligned with negative score. + * + * @var unsigned AlignmentStats::alignmentLength; + * @brief Length of the aligned region + * + * @var float AlignmentStats::alignmentSimilarity; + * @brief The resulting alignment percent similarity (positive). + * + * @var float AlignmentStats::alignmentIdentity; + * @brief The resulting alignment percent identity (match). + * + * @var int AlignmentStats::alignmentScore; + * @brief The resulting alignment score. + */ + +struct AlignmentStats +{ + // Number of gap characters/opens/gap extensions. + unsigned numGaps; + unsigned numGapOpens; + unsigned numGapExtensions; + // Number of insertions and deletions. + unsigned numInsertions; + unsigned numDeletions; + // Number of matches, mismatches. + unsigned numMatches; + unsigned numMismatches; + // Number of aligned residues with positive/negative scores. + unsigned numPositiveScores; + unsigned numNegativeScores; + + // length of the alignment + unsigned alignmentLength; + + // the alignment identity and similarity scores + float alignmentSimilarity; + float alignmentIdentity; + + // The alignment score. + int alignmentScore; + + AlignmentStats() : numGaps(0), numGapOpens(0), numGapExtensions(0), numInsertions(0), numDeletions(0), + numMatches(0), numMismatches(0), numPositiveScores(0), numNegativeScores(0), + alignmentLength(0), alignmentSimilarity(0.0), alignmentIdentity(0.0), alignmentScore(0) + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +/*! + * @fn AlignmentStats#clear + * @brief Resets all members to 0. + * + * @signature void clear(stats); + * + * @param[in,out] stats AlignmentStats object to clear. + */ + +inline +void clear(AlignmentStats & stats) +{ + stats.numGaps = 0; + stats.numGapOpens = 0; + stats.numGapExtensions = 0; + stats.numInsertions = 0; + stats.numDeletions = 0; + stats.numMatches = 0; + stats.numMismatches = 0; + stats.numPositiveScores = 0; + stats.numNegativeScores = 0; + stats.alignmentLength = 0; + stats.alignmentSimilarity = 0.0; + stats.alignmentIdentity = 0.0; + stats.alignmentScore = 0; +} + +// ---------------------------------------------------------------------------- +// Function computeAlignmentStats() +// ---------------------------------------------------------------------------- + +/*! + * @fn computeAlignmentStats + * @headerfile + * @brief Compute alignment statistics. + * + * @signature TScoreVal computeAlignmentStats(stats, align, scoringScheme); + * @signature TScoreVal computeAlignmentStats(stats, row0, row1, scoringScheme); + * + * @param[out] stats The @link AlignmentStats @endlink object to store alignment statistics in. + * @param[in] align The @link Align @endlink object to score. + * @param[in] row0 The first row (@link Gaps @endlink object). + * @param[in] row1 The second row (@link Gaps @endlink object). + * @param[in] score The @link Score @endlink object to use for the scoring scheme. + * + * @return TScoreVal The score value of the alignment, of the same type as the value type of scoringScheme + * + * @see AlignmentStats + * + * @section Examples + * + * @include demos/dox/align/compute_alignment_stats.cpp + * + * The output is as follows: + * + * @include demos/dox/align/compute_alignment_stats.cpp.stdout + */ + +template +TScoreVal computeAlignmentStats(AlignmentStats & stats, + Gaps const & row0, + Gaps const & row1, + Score const & scoringScheme) +{ + clear(stats); + + typedef typename Iterator const, Standard>::Type TGapsIter0; + typedef typename Iterator const, Standard>::Type TGapsIter1; + typedef typename Value::Type TAlphabet; + + // Get iterators. + TGapsIter0 it0 = begin(row0); + TGapsIter0 itEnd0 = end(row0); + TGapsIter1 it1 = begin(row1); + TGapsIter1 itEnd1 = end(row1); + + // State whether we have already opened a gap. + bool isGapOpen0 = false, isGapOpen1 = false; + + for (; it0 != itEnd0 && it1 != itEnd1; ++it0, ++it1) + { + if (isGap(it0)) + { + if (!isGapOpen0) + { + stats.numGapOpens += 1; + stats.alignmentScore += scoreGapOpen(scoringScheme); + } + else + { + stats.numGapExtensions += 1; + stats.alignmentScore += scoreGapExtend(scoringScheme); + } + stats.numDeletions += 1; + isGapOpen0 = true; + } + else + { + isGapOpen0 = false; + } + + if (isGap(it1)) + { + if (!isGapOpen1) + { + stats.numGapOpens += 1; + stats.alignmentScore += scoreGapOpen(scoringScheme); + } + else + { + stats.numGapExtensions += 1; + stats.alignmentScore += scoreGapExtend(scoringScheme); + } + stats.numInsertions += 1; + isGapOpen1 = true; + } + else + { + isGapOpen1 = false; + } + + if (!isGap(it0) && !isGap(it1)) + { + // Compute the alignment score and register in stats. + TAlphabet c0 = *it0; + TAlphabet c1 = static_cast(*it1); + TScoreVal scoreVal = score(scoringScheme, c0, c1); + stats.alignmentScore += scoreVal; + // Register other statistics. + bool isMatch = (c0 == c1); + bool isPositive = (scoreVal > 0); + stats.numMatches += isMatch; + stats.numMismatches += !isMatch; + stats.numPositiveScores += isPositive; + stats.numNegativeScores += !isPositive; + } + } + SEQAN_ASSERT(it0 == itEnd0); + SEQAN_ASSERT(it1 == itEnd1); + + stats.numGaps = stats.numGapOpens + stats.numGapExtensions; + + // Finally, compute the alignment similarity from the various counts + stats.alignmentLength = length(row0); + stats.alignmentSimilarity = 100.0 * static_cast(stats.numPositiveScores) + / static_cast(stats.alignmentLength); + stats.alignmentIdentity = 100.0 * static_cast(stats.numMatches) + / static_cast(stats.alignmentLength); + + return stats.alignmentScore; +} + +template +TScoreVal computeAlignmentStats(AlignmentStats & stats, + Align const & align, + Score const & scoringScheme) +{ + SEQAN_ASSERT_EQ_MSG(length(rows(align)), 2u, "Only works with pairwise alignments."); + SEQAN_ASSERT_EQ_MSG(length(row(align, 0)), length(row(align, 1)), "Invalid alignment!"); + + return computeAlignmentStats(stats, row(align, 0), row(align, 1), scoringScheme); +} + +// NOTE(h-2): this interface is deprecated. Don't use it. +template +TScoreVal computeAlignmentStats(Align const & align, + Score const & scoringScheme) +{ + AlignmentStats stats; + (void)stats; + return computeAlignmentStats(stats, align, scoringScheme); +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_ALIGN_EVALUATE_ALIGNMENT_H_ diff --git a/seqan/align/fragment.h b/seqan/align/fragment.h new file mode 100644 index 0000000..de6ae1e --- /dev/null +++ b/seqan/align/fragment.h @@ -0,0 +1,571 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Tobias Rausch +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_FRAGMENT_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_FRAGMENT_H_ + +namespace seqan +{ + +////////////////////////////////////////////////////////////////////////////// +// Fragment Specs +////////////////////////////////////////////////////////////////////////////// + +/*! + * @class ExactFragment + * @extends Fragment + * @headerfile + * @brief A type for ungapped, pairwise segment matches. + * + * @signature template <[typename TSize[, typename TSpec]]> + * class Fragment >; + * + * @tparam TSize The size type of the underlying sequence. Default: Size<CharString>Type. + * @tparam TSpec Specializing type. Default: ExactFragment<>. + */ + +template +struct ExactFragment; + + +/*! + * @class ExactReversableFragment + * @extends Fragment + * @headerfile + * @brief A type for ungapped, pairwise segment matches that maybe in reverse orientation. + * + * Compared to the @link ExactFragment @endlink ExactReversableFragment is a specialized type of @link Fragment @endlink. A @link + * ExactReversableFragment @endlink stores an additional bool value to indicate whether a match is in reverse + * orientation or not. + * + * @signature template <[typename TSize[, typename TSpec]]> + * class Fragment >; + * + * @tparam TSize The size type of the underlying sequence. Default: Size<CharString>Type. + * @tparam TSpec Specializing type. Default: ExactFragment<>. + */ + +template +struct ExactReversableFragment; + + +////////////////////////////////////////////////////////////////////////////// +// Default Fragment is the exact one +////////////////////////////////////////////////////////////////////////////// + +/*! + * @class Fragment + * @headerfile + * @brief A type for pairwise segment matches. + * + * @signature template <[typename TSize[, typename TSpec]]> + * class Fragment; + * + * @tparam TSize The size type of the underlying sequence. Default: Size<CharString>Type. + * @tparam TSpec Specializing type. Default: ExactFragment<>. + * + * @section Examples + * + * @code{.cpp} + * // Construct fragment. + * unsigned seqId1 = 0, beg1 = 0, seqId2 = 32, beg2 = 42, len = 33; + * Fragment<> fragment(seqId1, beg1, seqId2, beg2, len); + * + * // Update fragment's properties. + * fragmentBegin(fragment, 0) = 10; + * fragmentBegin(fragment, 1) = 10; + * sequenceId(fragment, 0) = 33; + * sequenceId(fragment, 1) = 44; + * fragmentLength(fragment) += 42; + * @endcode + */ + + +template >::Type, typename TSpec = ExactFragment<> > +class Fragment; + + +////////////////////////////////////////////////////////////////////////////// +// Size Metafunction +////////////////////////////////////////////////////////////////////////////// + +template +struct Size > { + typedef TSize Type; +}; + + +template +struct Size const> { + typedef TSize Type; +}; + + +////////////////////////////////////////////////////////////////////////////// +// Exact Fragment +////////////////////////////////////////////////////////////////////////////// + + +template +class Fragment > { +public: + typedef typename Id::Type TId; + + TId seqId1; + TSize begin1; + TId seqId2; + TSize begin2; + TSize len; + +/*! + * @fn ExactFragment::Fragment + * @brief Constructor. + * + * @signature Fragment::Fragment(); + * @signature Fragment::Fragment(seqID1, beg1, seqID2, beg2, l); + * + * @param[in] seqID1 ID of the first sequence. Type: TId. + * @param[in] beg1 Begin position of segment match in first sequence. Type: TSize. + * @param[in] seqID2 ID of the second sequence. Type: TId. + * @param[in] beg2 Begin position of segment match in second sequence. Type: TSize. + * @param[in] l The length of the segment match. Type: TSize. + */ + + Fragment() : seqId1(0), begin1(0), seqId2(0), begin2(0), len(0) {} + + Fragment(TId sqId1, TSize beg1, TId sqId2, TSize beg2, TSize l) : + seqId1(sqId1), begin1(beg1), seqId2(sqId2), begin2(beg2), len(l) + {} + +}; + +template +inline bool +operator==(Fragment > const & left, + Fragment > const & right) +{ + return (left.seqId1 == right.seqId1 && + left.begin1 == right.begin1 && + left.seqId2 == right.seqId2 && + left.begin2 == right.begin2 && + left.len == right.len); +} + +template +inline bool +operator<(Fragment > const & left, + Fragment > const & right) +{ + if (left.seqId1 < right.seqId1) + return true; + if (left.seqId1 > right.seqId1) + return false; + if (left.begin1 < right.begin1) + return true; + if (left.begin1 > right.begin1) + return false; + if (left.seqId2 < right.seqId2) + return true; + if (left.seqId2 > right.seqId2) + return false; + if (left.begin2 < right.begin2) + return true; + if (left.begin2 > right.begin2) + return false; + if (left.len < right.len) + return true; + // if (left.len > right.len) + // return false; + return false; +} + +////////////////////////////////////////////////////////////////////////////// +// Exact Fragment that is a forward or reverse match +////////////////////////////////////////////////////////////////////////////// + + +template +class Fragment > { +public: + typedef typename Id::Type TId_; + + TId_ seqId1; + TSize begin1; + TId_ seqId2; + TSize begin2; + TSize len; + bool reversed; + +/*! + * @fn ExactReversableFragment::Fragment + * @brief Constructor. + * + * @signature Fragment::Fragment(); + * @signature Fragment::Fragment(seqID1, beg1, seqID2, beg2, l[, reversed]); + * + * @param[in] seqID1 ID of the first sequence. Type: TId. + * @param[in] beg1 Begin position of segment match in first sequence. Type: TSize. + * @param[in] seqID2 ID of the second sequence. Type: TId. + * @param[in] beg2 Begin position of segment match in second sequence. Type: TSize. + * @param[in] l The length of the segment match. Type: TSize. + * @param[in] reversed A bool; true if the segments match in reverse orientation, false otherwise. + */ + + + Fragment() : seqId1(0), begin1(0), seqId2(0), begin2(0), len(0), reversed(false) {} + + Fragment(TId_ sqId1, TSize beg1, TId_ sqId2, TSize beg2, TSize l) : + seqId1(sqId1), begin1(beg1), seqId2(sqId2), begin2(beg2), len(l), reversed(false) + {} + + Fragment(TId_ sqId1, TSize beg1, TId_ sqId2, TSize beg2, TSize l, bool rev) : + seqId1(sqId1), begin1(beg1), seqId2(sqId2), begin2(beg2), len(l), reversed(rev) + {} +}; + +template +inline bool +operator==(Fragment > const & left, + Fragment > const & right) +{ + return (left.seqId1 == right.seqId1 && + left.begin1 == right.begin1 && + left.seqId2 == right.seqId2 && + left.begin2 == right.begin2 && + left.len == right.len && + left.reversed == right.reversed); +} + +template +inline bool +operator<(Fragment > const & left, + Fragment > const & right) +{ + if (left.seqId1 < right.seqId1) + return true; + if (left.seqId1 > right.seqId1) + return false; + if (left.begin1 < right.begin1) + return true; + if (left.begin1 > right.begin1) + return false; + if (left.seqId2 < right.seqId2) + return true; + if (left.seqId2 > right.seqId2) + return false; + if (left.begin2 < right.begin2) + return true; + if (left.begin2 > right.begin2) + return false; + if (left.len < right.len) + return true; + if (left.len > right.len) + return false; + if (left.reversed < right.reversed) + return true; + // if (left.reversed > right.reversed) + // return false; + return false; +} + +////////////////////////////////////////////////////////////////////////////// + +/*! + * @fn Fragment#label + * @brief Access to the Fragment's label. + * + * @signature TInfix label(frag, stringSet, seqID); + * + * @param[in] frag The Fragment to query. + * @param[in] stringSet The @link StringSet @endlink with the sequences. + * @param[in] seqID The id of the sequence for which the label should be retrieved. + */ + +template +inline typename Infix::Type>::Type +label(Fragment const& f, + TStringSet& str, + TVal const seqId) +{ + typedef typename Id >::Type TId; + return ((TId) seqId == (f.seqId1)) ? infix(getValueById(str, (TId) seqId), f.begin1, f.begin1 + f.len) : infix(getValueById(str, (TId) seqId), f.begin2, f.begin2 + f.len); +} + +////////////////////////////////////////////////////////////////////////////// + +/*! + * @fn Fragment#sequenceId + * @brief Access to the sequence ID of a fragment. + * + * @signature TId sequenceId(frag, seqNum); + * + * @param[in] frag A Fragment. + * @param[in] seqNum The sequence number for which the id should be retrieved. Note that @link Fragment @endlink + stores information about exactly two sequences which can be accessed with seqNum 0 or 1 but whose + ids may differ from their seqNum. + * + * @return TId Reference to the sequence fragment id member. + */ + +template +inline typename Id >::Type & +sequenceId(Fragment & f, + TVal const seqId) +{ + return (seqId == (TVal)0) ? f.seqId1 : f.seqId2; +} + +template +inline typename Id >::Type const & +sequenceId(Fragment const & f, + TVal const seqId) +{ + return (seqId == (TVal)0) ? f.seqId1 : f.seqId2; +} + +////////////////////////////////////////////////////////////////////////////// + +/*! + * @fn Fragment#fragmentBegin + * @brief Return fragment begin. + * + * @signature TSize fragmentBegin(frag, seqId); + * + * @param[in] frag The Fragment to query. + * @param[in] seqId The id of the sequence to get the begin for. + * + * @return TSize Reference to the fragment begin position member. + */ + +template +inline TSize& +fragmentBegin(Fragment const& f, + TVal const seqId) +{ + typedef typename Id >::Type TId; + return ((TId) seqId == f.seqId1) ? const_cast(f.begin1) : const_cast(f.begin2); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline TSize& +fragmentLength(Fragment const& f, + TVal const) +{ + return const_cast(f.len); +} + +////////////////////////////////////////////////////////////////////////////// + +/*! + * @fn Fragment#fragmentLength + * @brief Return fragment begin. + * + * @signature TSize fragmentLength(frag); + * + * @param[in] frag The Fragment to query for its length. + * + * @return TSize Reference to the Fragment's length. + */ + +template +inline TSize& +fragmentLength(Fragment const& f) +{ + return const_cast(f.len); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +getProjectedPosition(Fragment > const& f, + TId1 const seqId, + TPosition1 const pos, + TId2& seqId2, + TPosition2& pos2) +{ + typedef typename Id >::Type TId; + + if ((TId) seqId == f.seqId1) { + SEQAN_ASSERT((TPosition1)f.begin1<=pos); + SEQAN_ASSERT(pos - f.begin1 < f.len) ; + pos2 = f.begin2 + (pos - f.begin1); + seqId2 = f.seqId2; + return; + } else { + SEQAN_ASSERT((TPosition1)f.begin2<=pos); + SEQAN_ASSERT(pos - f.begin2 < f.len); + pos2 = f.begin1 + (pos - f.begin2); + seqId2 = f.seqId1; + return; + } +} + + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +getProjectedPosition(Fragment > const& f, + TValue seg_num, + TId1 const seqId, + TPosition1 const pos, + TId2& seqId2, + TPosition2& pos2) +{ + (void) seqId; // When compiled without assertions. + SEQAN_ASSERT((seg_num == 0 && seqId == f.seqId1) || (seg_num == 1 && seqId == f.seqId2)); + + if (seg_num == 0) { + SEQAN_ASSERT((TPosition1)f.begin1<=pos); + SEQAN_ASSERT(pos - f.begin1 < f.len) ; + pos2 = f.begin2 + (pos - f.begin1); + seqId2 = f.seqId2; + return; + } else { + SEQAN_ASSERT((TPosition1)f.begin2<=pos); + SEQAN_ASSERT(pos - f.begin2 < f.len); + pos2 = f.begin1 + (pos - f.begin2); + seqId2 = f.seqId1; + return; + } +} + + + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +getProjectedPosition(Fragment > const& f, + TId1 const seqId, + TPosition1 const pos, + TId2& seqId2, + TPosition2& pos2) +{ + typedef typename Id >::Type TId; + + if ((TId) seqId == f.seqId1) { + SEQAN_ASSERT((TPosition1)f.begin1<=pos); + SEQAN_ASSERT(pos - f.begin1 < f.len) ; + if (f.reversed) pos2 = (f.begin2 + f.len - 1) - (pos - f.begin1); + else pos2 = f.begin2 + (pos - f.begin1); + seqId2 = f.seqId2; + return; + } else { + SEQAN_ASSERT((TPosition1)f.begin2<=pos); + SEQAN_ASSERT(pos - f.begin2 < f.len); + if (f.reversed) pos2 = (f.begin1 + f.len - 1) - (pos - f.begin2); + else pos2 = f.begin1 + (pos - f.begin2); + seqId2 = f.seqId1; + return; + } +} + + +///////////////////////////////////////////////////////////// + +template +inline void +getProjectedPosition(Fragment > const& f, + TValue seg_num, + TId1 const seqId, + TPosition1 const pos, + TId2& seqId2, + TPosition2& pos2) +{ + (void) seqId; // When compiled without assertions. + SEQAN_ASSERT((seg_num == 0 && seqId==f.seqId1) || (seg_num == 1 && seqId==f.seqId2)); + + if (seg_num == 0) { + SEQAN_ASSERT((TPosition1)f.begin1<=pos); + SEQAN_ASSERT(pos - f.begin1 < f.len) ; + if (f.reversed) pos2 = (f.begin2 + f.len - 1) - (pos - f.begin1); + else pos2 = f.begin2 + (pos - f.begin1); + seqId2 = f.seqId2; + return; + } else { + SEQAN_ASSERT((TPosition1)f.begin2<=pos); + SEQAN_ASSERT(pos - f.begin2 < f.len); + if (f.reversed) pos2 = (f.begin1 + f.len - 1) - (pos - f.begin2); + else pos2 = f.begin1 + (pos - f.begin2); + seqId2 = f.seqId1; + return; + } +} + +////////////////////////////////////////////////////////////////////////////// + +/*! + * @fn ExactReversableFragment#isReversed + * @brief Return whether a segment match is in reverse orientation. + * + * @signature bool isReversed(frag); + * + * @param[in] frag The Fragment to query for reverseness. + * + * @return bool true if the fragment is reversed and false otherwise. + */ + +template +inline bool +isReversed(Fragment > const& f) +{ + return f.reversed; +} + +// Compare lexicographically as tuple. + +template +inline bool operator>(Fragment > const & lhs, + Fragment > const & rhs) +{ + if (lhs.seqId1 > rhs.seqId1) + return true; + if (lhs.seqId1 == rhs.seqId1 && lhs.begin1 > rhs.begin1) + return true; + if (lhs.seqId1 == rhs.seqId1 && lhs.begin1 == rhs.begin1 && lhs.seqId2 > rhs.seqId2) + return true; + if (lhs.seqId1 == rhs.seqId1 && lhs.begin1 == rhs.begin1 && lhs.seqId2 == rhs.seqId2 && lhs.begin2 > rhs.begin2) + return true; + if (lhs.seqId1 == rhs.seqId1 && lhs.begin1 == rhs.begin1 && lhs.seqId2 == rhs.seqId2 && lhs.begin2 == rhs.begin2 && lhs.len > rhs.len) + return true; + return false; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_FRAGMENT_H_ diff --git a/seqan/align/gap_anchor.h b/seqan/align/gap_anchor.h new file mode 100644 index 0000000..1a625fd --- /dev/null +++ b/seqan/align/gap_anchor.h @@ -0,0 +1,380 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAP_ANCHOR_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GAP_ANCHOR_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// TODO(holtgrew): Document? +// Sorting tags (just for lower_bound and upper_bound, positions are always sorted) + +struct SortSeqPos_; +typedef Tag const SortSeqPos; + +struct SortGapPos_; +typedef Tag const SortGapPos; + +// ---------------------------------------------------------------------------- +// Specialization GapAnchor +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Make a class instead of a struct? + +/*! + * @class GapAnchor + * @implements ComparableConcept + * @headerfile + * @brief Stores the position of an alignment character in sequence-space and gap-space in @link AnchorGaps @endlink. + * + * @signature template + * struct GapAnchor; + * + * @tparam TPos Type to store gapped/ungapped positions. + * + * @section Remarks + * + * Used as value type for the gaps strings in @link ReadStoreElement @endlink and @link ContigStoreElement + * @endlink. + * + * @see AnchorGaps + */ + +// We store gap anchors only for the first text character behind a gap or a clipped sequence character + +template +struct GapAnchor +{ +/*! + * @var TPos GapAnchor::seqPos + * @brief Sequence character position in the ungapped sequence. + */ + TPos seqPos; // sequence character position in the ungapped sequence + +/*! + * @var TPos GapAnchor::gapPos + * @brief Sequence character position in the gapped sequence. + */ + TPos gapPos; // sequence character position in the gapped sequence + +/*! + * @fn GapAnchor::GapAnchor + * @brief Constructor. + * + * @signature GapAnchor::GapAnchor([other]); + * @signature GapAnchor::GapAnchor(seqPos, gapPos); + * + * @param[in] other GapAnchor object to copy from. + * @param[in] seqPos Sequence character position in the ungapped sequence (of type TPos). + * @param[in] gapPos Sequence character position in the gapped sequence (of type TPos). + * + * @section Remarks + * + * The default constructor sets both positions to 0. + */ + + GapAnchor() : seqPos(0), gapPos(0) {} + GapAnchor(TPos sP, TPos gP) : seqPos(sP), gapPos(gP) {} + + template + GapAnchor(GapAnchor const &other) + { + seqPos = other.seqPos; + gapPos = other.gapPos; + } + + template + inline GapAnchor const & + operator = (GapAnchor const &other) + { + seqPos = other.seqPos; + gapPos = other.gapPos; + return *this; + } + + template + inline bool + operator == (TOther const &other) const + { + return seqPos == other.seqPos && gapPos == other.gapPos; + } + + template + inline bool + operator != (TOther const &other) const + { + return !(*this == other); + } + + template + inline bool + operator < (TOther const &other) const + { + return seqPos < other.seqPos || gapPos < other.gapPos; + } + + template + inline bool + operator > (TOther const &other) const + { + return seqPos > other.seqPos || gapPos > other.gapPos; + } + + template + inline bool + operator <= (TOther const &other) const + { + return seqPos < other.seqPos || gapPos <= other.gapPos; + } + + template + inline bool + operator >= (TOther const &other) const + { + return seqPos > other.seqPos || gapPos >= other.gapPos; + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Size [GapAnchor] +// ---------------------------------------------------------------------------- + +template +struct Size > +{ + typedef TPos Type; +}; + +template +struct Size const> : public Size > +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Position [GapAnchor] +// ---------------------------------------------------------------------------- + +template +struct Position > +{ + typedef TPos Type; +}; + +template +struct Position const> : public Position > +{}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Functor _LessGapAnchor +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Leading underscore should become a trailing one. + +template +struct _LessGapAnchor; + +template +struct _LessGapAnchor : + public std::binary_function +{ + inline bool + operator() (TGapAnchor const& a1, TGapAnchor const& a2) const { + return (a1.seqPos) < (a2.seqPos); + } +}; + +template +struct _LessGapAnchor : + public std::binary_function +{ + inline bool + operator() (TGapAnchor const& a1, TGapAnchor const& a2) const { + return (a1.gapPos) < (a2.gapPos); + } +}; + +// ---------------------------------------------------------------------------- +// Function lowerBoundGapAnchor() +// ---------------------------------------------------------------------------- + +template +inline typename Iterator::Type +lowerBoundGapAnchor(TGapAnchor const & gaps, + TSearchValue const val, + SortSeqPos) +{ + typedef typename Value::Type TGapAnchorElement; + TGapAnchorElement el; + el.seqPos = val; + return std::lower_bound( + begin(gaps, Standard()), + end(gaps, Standard()), + el, + _LessGapAnchor::Type, SortSeqPos const>() ); +} + +template +inline typename Iterator::Type +lowerBoundGapAnchor(TGapAnchor & gaps, + TSearchValue const val, + SortSeqPos) +{ + typedef typename Value::Type TGapAnchorElement; + TGapAnchorElement el; + el.seqPos = val; + return std::lower_bound( + begin(gaps, Standard()), + end(gaps, Standard()), + el, + _LessGapAnchor::Type, SortSeqPos const>() ); +} + +template +inline typename Iterator::Type +lowerBoundGapAnchor(TGapAnchor const & gaps, + TSearchValue const val, + SortGapPos) +{ + typedef typename Value::Type TGapAnchorElement; + TGapAnchorElement el; + el.gapPos = val; + return std::lower_bound( + begin(gaps, Standard()), + end(gaps, Standard()), + el, + _LessGapAnchor::Type, SortGapPos const>() ); +} + +template +inline typename Iterator::Type +lowerBoundGapAnchor(TGapAnchor & gaps, + TSearchValue const val, + SortGapPos) +{ + typedef typename Value::Type TGapAnchorElement; + TGapAnchorElement el; + el.gapPos = val; + return std::lower_bound( + begin(gaps, Standard()), + end(gaps, Standard()), + el, + _LessGapAnchor::Type, SortGapPos const>() ); +} + +// ---------------------------------------------------------------------------- +// Function upperBoundGapAnchor() +// ---------------------------------------------------------------------------- + +template +inline typename Iterator::Type +upperBoundGapAnchor(TGapAnchors const & gaps, + TSearchValue const val, + SortSeqPos) +{ + typedef typename Value::Type TGapAnchorElement; + TGapAnchorElement el; + el.seqPos = val; + return std::upper_bound( + begin(gaps, Standard()), + end(gaps, Standard()), + el, + _LessGapAnchor::Type, SortSeqPos const>() ); +} + +template +inline typename Iterator::Type +upperBoundGapAnchor(TGapAnchors & gaps, + TSearchValue const val, + SortSeqPos) +{ + typedef typename Value::Type TGapAnchorElement; + TGapAnchorElement el; + el.seqPos = val; + return std::upper_bound( + begin(gaps, Standard()), + end(gaps, Standard()), + el, + _LessGapAnchor::Type, SortSeqPos const>() ); +} + +template +inline typename Iterator::Type +upperBoundGapAnchor(TGapAnchors const & gaps, + TSearchValue const val, + SortGapPos) +{ + typedef typename Value::Type TGapAnchorElement; + TGapAnchorElement el; + el.gapPos = val; + return std::upper_bound( + begin(gaps, Standard()), + end(gaps, Standard()), + el, + _LessGapAnchor::Type, SortGapPos const>() ); +} + +template +inline typename Iterator::Type +upperBoundGapAnchor(TGapAnchors & gaps, + TSearchValue const val, + SortGapPos) +{ + typedef typename Value::Type TGapAnchorElement; + TGapAnchorElement el; + el.gapPos = val; + return std::upper_bound( + begin(gaps, Standard()), + end(gaps, Standard()), + el, + _LessGapAnchor::Type, SortGapPos const>() ); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAP_ANCHOR_H_ diff --git a/seqan/align/gapped_value_type.h b/seqan/align/gapped_value_type.h new file mode 100644 index 0000000..855f1d3 --- /dev/null +++ b/seqan/align/gapped_value_type.h @@ -0,0 +1,87 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPPED_VALUE_TYPE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GAPPED_VALUE_TYPE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +/*! + * @mfn GappedValueType + * @headerfile + * @brief Returns a value type that contains a black value '-'. + * + * @signature GappedValueType::Type + * + * @tparam T The value type that should be expanded (if needed) by '-'. + * + * @return Type A type that can store the values of T and the value '-'. + */ + +// TODO(holtgrew): Would it be enough to define it for Nothing instead of having a default implementation. + +// We need a default implementation since we need it for Nothing. +template +struct GappedValueType +{ + typedef T Type; +}; + +template +struct GappedValueType > +{ + typedef SimpleType THost_; + typedef ModifiedAlphabet > Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPPED_VALUE_TYPE_H_ diff --git a/seqan/align/gaps_anchor.h b/seqan/align/gaps_anchor.h new file mode 100644 index 0000000..c75042d --- /dev/null +++ b/seqan/align/gaps_anchor.h @@ -0,0 +1,938 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// ========================================================================== +// Implementation of Gaps class using pairs of gapped sequence and source +// sequence position as anchors. +// ========================================================================== + +// TODO(holtgrew): Clipping in leading and trailing gaps is not possible right now. Dave and I have to discuss this further. +// TODO(holtgrew): Also, inserting gaps in the front changes the clipped begin position which is unexpected. + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ANCHOR_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ANCHOR_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +/*! + * @tag GapsSpecTag#AnchorGaps + * @headerfile + * @brief Tag for the Anchor Gaps specialization. + * + * @signature template + * struct AnchorGaps; + */ + +template +struct AnchorGaps; + +template +inline void _reinitAnchorGaps(Gaps > & gaps); + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Specialization AnchorGaps +// ---------------------------------------------------------------------------- + +/*! + * @class AnchorGaps + * @extends Gaps + * @headerfile + * @brief Stores gaps as anchors of the first characters behind gaps. + * + * @signature template > > + * class Gaps >; + * + * @tparam TSource The type of the underlying sequence. + * @tparam TGapAnchors The type of the string of @link GapAnchor @endlink objects. + */ + +/*! + * @fn AnchorGaps::Gaps + * @brief Constructor + * + * @signature Gaps::Gaps([other]); + * @signature Gaps::Gaps(source[, anchors]); + * @signature Gaps::Gaps(anchors); + * + * @param[in] other Another @link AnchorGaps @endlink object to copy from. + * @param[in] source The underlying sequence to construct the Gaps object from. + * @param[in] anchors The string of anchors to construct with. + * + * An AnchorGaps object has a default constructor, can be constructed from the underlying source, and/or a string of + * gap anchors. + */ + + +template > > +struct AnchorGaps +{}; + +template +class Gaps > +{ +public: + // ----------------------------------------------------------------------- + // Internal Typedefs + // ----------------------------------------------------------------------- + + typedef typename Value::Type TGapAnchor_; + typedef typename Position::Type TViewPosition_; + typedef typename Position::Type TPosition_; + typedef typename Value::Type TValue_; + + typedef typename RemoveReference::Type>::Type TSourceNoConstNoRef; + typedef TSourceNoConstNoRef const & TSourceConstRef; + + // ----------------------------------------------------------------------- + // Member Variables + // ----------------------------------------------------------------------- + + Holder data_source; + Holder data_gaps; + int data_cutBegin; // number of gap positions cut from the beginning + int data_cutEnd; // number of gap positions cut from the end + int data_viewCutBegin; // how many alignment chars should be clipped at the beginning (can be negative too) + int data_viewCutEnd; // how ... end ... + + // ----------------------------------------------------------------------- + // Constructors + // ----------------------------------------------------------------------- + + Gaps() : + data_cutBegin(0), + data_cutEnd(0), + data_viewCutBegin(0), + data_viewCutEnd(0) + { + } + + Gaps(TSource & source) : + data_source(source), + data_cutBegin(0), + data_cutEnd(0), + data_viewCutBegin(0), + data_viewCutEnd(0) + { + } + + Gaps(TGapAnchors & anchors) : + data_gaps(anchors), + data_cutBegin(0), + data_cutEnd(0), + data_viewCutBegin(0), + data_viewCutEnd(0) + { + } + + Gaps(TGapAnchors const & anchors) : + data_gaps(anchors), + data_cutBegin(0), + data_cutEnd(0), + data_viewCutBegin(0), + data_viewCutEnd(0) + { + } + + // everybody has const & constructors + Gaps(TSourceNoConstNoRef const & source, TGapAnchors & anchors) : + data_source(source), + data_gaps(anchors), + data_cutBegin(0), + data_cutEnd(0), + data_viewCutBegin(0), + data_viewCutEnd(0) + { + } + + Gaps(TSourceNoConstNoRef const & source, TGapAnchors const & anchors) : + data_source(source), + data_gaps(anchors), + data_cutBegin(0), + data_cutEnd(0), + data_viewCutBegin(0), + data_viewCutEnd(0) + { + } + + // if source is not const & (but possibly const) there are also regular & constructors + Gaps(TSourceNoConstNoRef & source, TGapAnchors & anchors, + SEQAN_CTOR_DISABLE_IF(IsSameType)) : + data_source(source), + data_gaps(anchors), + data_cutBegin(0), + data_cutEnd(0), + data_viewCutBegin(0), + data_viewCutEnd(0) + { + ignoreUnusedVariableWarning(dummy); + } + + Gaps(TSourceNoConstNoRef & source, TGapAnchors const & anchors, + SEQAN_CTOR_DISABLE_IF(IsSameType)) : + data_source(source), + data_gaps(anchors), + data_cutBegin(0), + data_cutEnd(0), + data_viewCutBegin(0), + data_viewCutEnd(0) + { + ignoreUnusedVariableWarning(dummy); + } + + // ----------------------------------------------------------------------- + // Array Subscript Operator + // ----------------------------------------------------------------------- + + inline typename Reference::Type + operator[](TPosition_ const clippedViewPos) + { + return value(*this, clippedViewPos); + } + + inline typename Reference::Type + operator[](TPosition_ const clippedViewPos) const + { + return value(*this, clippedViewPos); + } + +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function swap() +// ---------------------------------------------------------------------------- + +template +void swap(Gaps > & lhs, + Gaps > & rhs) +{ + swap(lhs.data_source, rhs.data_source); + swap(lhs.data_gaps, rhs.data_gaps); + + std::swap(lhs.data_cutBegin, rhs.data_cutBegin); + std::swap(lhs.data_cutEnd, rhs.data_cutEnd); + std::swap(lhs.data_viewCutBegin, rhs.data_viewCutBegin); + std::swap(lhs.data_viewCutEnd, rhs.data_viewCutEnd); +} + +// ---------------------------------------------------------------------------- +// Helper Function _reinitAnchorGaps() +// ---------------------------------------------------------------------------- + +// Reset the array gaps DS such that represents the ungapped sequence. + +template +inline void _reinitAnchorGaps(Gaps > & gaps) +{ + clear(value(gaps.data_gaps)); + gaps.data_cutBegin = 0; + gaps.data_cutEnd = 0; + gaps.data_viewCutBegin = 0; + gaps.data_viewCutEnd = 0; +} + +// ---------------------------------------------------------------------------- +// Function _dataSource() +// ---------------------------------------------------------------------------- + +template +inline Holder & +_dataSource(Gaps > & me) +{ + return me.data_source; +} + +template +inline Holder const & +_dataSource(Gaps > const & me) +{ + return me.data_source; +} + +// ---------------------------------------------------------------------------- +// Function _assignSourceLength() +// ---------------------------------------------------------------------------- + +template +inline void +_assignSourceLength(TSize & size, Gaps > const & me) +{ + if (IsSameType::VALUE) + size = maxValue() / 2; + else + size = length(value(me.data_source)); +} + +// ---------------------------------------------------------------------------- +// Function _dataAnchors() +// ---------------------------------------------------------------------------- + +template +inline TGapAnchors & +_dataAnchors(Gaps > & me) +{ + return value(me.data_gaps); +} + +template +inline TGapAnchors const & +_dataAnchors(Gaps > const & me) +{ + return value(const_cast &>(me.data_gaps)); +} + +// ---------------------------------------------------------------------------- +// Function _getAnchor() +// ---------------------------------------------------------------------------- + +template +inline void +_getAnchor(TAnchor & anchor, Gaps > const & me, TIdx idx) +{ + if (idx > (TIdx)length(_dataAnchors(me))) + { + _assignSourceLength(anchor.seqPos, me); + if (empty(_dataAnchors(me)) && idx == 1) + anchor.gapPos = anchor.seqPos; + else + { + // for the sick case that an anchor seq position is beyond the sequence end + if (!empty(_dataAnchors(me))) + { + // if there is no sequence but anchors -> assume infinite sequence + if (anchor.seqPos == 0) + anchor.seqPos = maxValue(anchor.gapPos); + // if the sequence has a length > 0, but there is an anchor behind the end + // -> elongate sequence + else if ((int64_t)anchor.seqPos < (int64_t)back(_dataAnchors(me)).seqPos) + anchor.seqPos = back(_dataAnchors(me)).seqPos; + } + anchor.gapPos = maxValue(anchor.gapPos); + } + } + else if (idx > 0) + anchor = _dataAnchors(me)[idx - 1]; + else + { + anchor.seqPos = 0; + if (idx == 0) + anchor.gapPos = 0; + else + anchor.gapPos = minValue(anchor.gapPos); + } +} + +// ---------------------------------------------------------------------------- +// Function _unclippedLength() +// ---------------------------------------------------------------------------- + +template +inline typename Size > >::Type +_unclippedLength(Gaps > const & me) +{ + typedef typename Value::Type TAnchor; + typedef typename Size::Type TSize; + TSize len; + _assignSourceLength(len, me); + if (!empty(_dataAnchors(me))) + { + TAnchor const & last = back(_dataAnchors(me)); + len += last.gapPos - last.seqPos; + } + return len - (me.data_cutBegin + me.data_cutEnd); +} + +// ---------------------------------------------------------------------------- +// Function unclippedLength() +// ---------------------------------------------------------------------------- + +template +inline typename Size > >::Type +unclippedLength(Gaps > const & me) +{ + // TODO(holtgrew): Merge into one public function. + return _unclippedLength(me); +} + +// ---------------------------------------------------------------------------- +// Function clearClipping() +// ---------------------------------------------------------------------------- + +template +inline void +clearClipping(Gaps > & gaps) +{ + gaps.data_viewCutBegin = 0; + gaps.data_viewCutEnd = 0; +} + +// ---------------------------------------------------------------------------- +// Function clearGaps() +// ---------------------------------------------------------------------------- + +template +inline void +clearGaps(Gaps > & gaps) +{ + _reinitAnchorGaps(gaps); +} + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +template +inline void +clear(Gaps > & gaps) +{ + clear(gaps.data_source); // clear source holder + + // clear gaps, but on holder level + clear(gaps.data_gaps); + gaps.data_cutBegin = 0; + gaps.data_cutEnd = 0; + gaps.data_viewCutBegin = 0; + gaps.data_viewCutEnd = 0; +} + +// ---------------------------------------------------------------------------- +// Function isGap() +// ---------------------------------------------------------------------------- + +template +inline bool +isGap(Gaps > const & gaps, TPosition clippedViewPos) +{ + // TODO(holtgrew): Implement without iterator? + return isGap(iter(gaps, clippedViewPos)); +} + +// ---------------------------------------------------------------------------- +// Function insertGaps() +// ---------------------------------------------------------------------------- + +template +inline void +insertGaps(Gaps > & gaps, TPosition clippedViewPos, TCount count) +{ + // TODO(holtgrew): Implement without iterator? + typedef Gaps > TGaps; + typedef typename Iterator::Type TIter; + + TIter it = iter(gaps, clippedViewPos); + insertGaps(it, count); +} + +// ---------------------------------------------------------------------------- +// Function removeGaps() +// ---------------------------------------------------------------------------- + +template +inline typename Size > >::Type +removeGaps(Gaps > & gaps, TPosition clippedViewPos, TCount count) +{ + // TODO(holtgrew): Implement without iterator? + return removeGaps(iter(gaps, clippedViewPos), count); +} + +// ---------------------------------------------------------------------------- +// Function length() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): We would rather like to have the const version only :( +template +inline typename Size > >::Type +length(Gaps > & me) +{ + return _unclippedLength(me) - (me.data_viewCutBegin + me.data_viewCutEnd); +} + +template +inline typename Size > >::Type +length(Gaps > const & me) +{ + return _unclippedLength(me) - (me.data_viewCutBegin + me.data_viewCutEnd); +} + +// ---------------------------------------------------------------------------- +// Function begin() +// ---------------------------------------------------------------------------- + +template +inline typename Iterator > >::Type +begin(Gaps > & me, Standard) +{ + return typename Iterator > >::Type(me); +} + +template +inline typename Iterator > const>::Type +begin(Gaps > const & me, Standard) +{ + return typename Iterator > const>::Type(me); +} + +template +inline typename Iterator > >::Type +begin(Gaps > & me, Rooted) +{ + return typename Iterator > >::Type(me); +} + +template +inline typename Iterator > const>::Type +begin(Gaps > const & me, Rooted) +{ + return typename Iterator > const>::Type(me); +} + +// ---------------------------------------------------------------------------- +// Function end() +// ---------------------------------------------------------------------------- + +template +inline typename Iterator > >::Type +end(Gaps > & me, Standard) +{ + return typename Iterator > >::Type(me, length(me)); +} + +template +inline typename Iterator > const>::Type +end(Gaps > const & me, Standard) +{ + return typename Iterator > const>::Type(me, length(me)); +} + +template +inline typename Iterator > >::Type +end(Gaps > & me, Rooted) +{ + return typename Iterator > >::Type(me, length(me)); +} + +template +inline typename Iterator > const>::Type +end(Gaps > const & me, Rooted) +{ + return typename Iterator > const>::Type(me, length(me)); +} + +// ---------------------------------------------------------------------------- +// Function beginPosition() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): We would rather like to have the const version only :( +template +inline typename Position::Type +beginPosition(Gaps > & gaps) +{ + return toSourcePosition(gaps, 0); +} + +template +inline typename Position::Type +beginPosition(Gaps > const & gaps) +{ + return toSourcePosition(gaps, 0); +} + +// ---------------------------------------------------------------------------- +// Function endPosition() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): We would rather like to have the const version only :( +template +inline typename Position::Type +endPosition(Gaps > & gaps) +{ + return toSourcePosition(gaps, _unclippedLength(gaps) - (gaps.data_viewCutEnd + gaps.data_viewCutBegin)); +} + +template +inline typename Position::Type +endPosition(Gaps > const & gaps) +{ + return toSourcePosition(gaps, _unclippedLength(gaps) - (gaps.data_viewCutEnd + gaps.data_viewCutBegin)); +} + +// ---------------------------------------------------------------------------- +// Function setBeginPosition() +// ---------------------------------------------------------------------------- + +template +inline void +setBeginPosition(Gaps > & gaps, TPosition sourcePosition) +{ + setClippedBeginPosition(gaps, toViewPosition(gaps, sourcePosition) + clippedBeginPosition(gaps)); +} + +// ---------------------------------------------------------------------------- +// Function setEndPosition() +// ---------------------------------------------------------------------------- + +template +inline void +setEndPosition(Gaps > & gaps, TPosition sourcePosition) +{ + setClippedEndPosition(gaps, toViewPosition(gaps, sourcePosition) + clippedBeginPosition(gaps)); +} + +// ---------------------------------------------------------------------------- +// Function createSource() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Remove? Switch to Hosted Type Interface? + +template +inline void createSource(Gaps > & gaps) +{ + create(gaps.data_source); +} + +// ---------------------------------------------------------------------------- +// Function source() +// ---------------------------------------------------------------------------- + +template +inline typename Source > >::Type & +source(Gaps > const & gaps) +{ + return value(gaps.data_source); +} + +// ---------------------------------------------------------------------------- +// Function setSource() +// ---------------------------------------------------------------------------- + +template +inline void +setSource(Gaps > & gaps, TSequence & source) +{ + setValue(gaps.data_source, source); +} + +template +inline void +setSource(Gaps > & gaps, TSequence & source) +{ + setValue(gaps.data_source, source); +} + +// ---------------------------------------------------------------------------- +// Function assignSource() +// ---------------------------------------------------------------------------- + +template +inline void +assignSource(Gaps > & gaps, TSequence2 const & source) +{ + value(gaps.data_source) = source; +} + +// ---------------------------------------------------------------------------- +// Function positionGapToSeq() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Deprecate in favour of toViewPosition/toSourcePosition? + +/*! + * @fn AnchorGaps#positionGapsToSeq + * @brief Convert from gap space in the global alignment to the sequence space on the reference. + * + * @signature TPos positionGapToSeq(gaps, pos); + * + * @param[in] gaps Contig AnchorGaps (e.g. from FragmentStore). + * @param[in] pos Position in gap space. + * + * @return TPos Position in sequence space (Metafunction: @link ContainerConcept#Position @endlink). + * + * See the example below to construct the Gaps object. Note that this construction is fast since it is only a thin wrapper + * around underlying objects. + * + * @section Examples + * + * Convert from gap space to positions pace when the contig required to be loaded. * Converts position aligned read with + * index idx in the aligned read store. + * + * @code{.cpp} + * typedef typename TFragmentStore::TContigStore TContigStore; + * typedef typename Value::Type TContig; + * typedef typename TFragmentStore::TContigSeq TContigSeq; + * typedef Gaps > TContigGaps; + * + * typedef typename TFragmentStore::TAlignedReadStore TAlignedReadStore; + * typedef typename Value::Type TAlignedRead; + * typedef typename TAlignedRead::TPos TAlignedReadPos; + * + * unsigned contigId = alignedReadStore[idx].contigId; + * TContigGaps contigGaps(contigStore[contigId].seq, contigStore[contigId].gaps); + * TAlignedRead const & alignedRead = alignedReadStore[idx]; + * // Translate end position from aligned read record to sequence space in reference. + * TAlignedReadPos endPos = positionGapToSeq(contigGaps, alignedRead.endPos); + * @endcode + * + * Convert from gap space to position space when the contigs are not required. + * Converts position aligned read with index $idx$ in the aligned read store. + * + * @code{.cpp} + * typedef typename TFragmentStore::TContigStore TContigStore; + * typedef typename Value::Type TContig; + * typedef Gaps > TContigGaps; + * + * typedef typename TFragmentStore::TAlignedReadStore TAlignedReadStore; + * typedef typename Value::Type TAlignedRead; + * typedef typename TAlignedRead::TPos TAlignedReadPos; + * + * unsigned contigId = alignedReadStore[idx].contigId; + * TContigGaps contigGaps(Nothing(), contigStore[contigId].gaps); + * TAlignedRead const & alignedRead = alignedReadStore[idx]; + * // Translate end position from aligned read record to sequence space in reference. + * TAlignedReadPos endPos = positionGapToSeq(contigGaps, alignedRead.endPos); + * @endcode + */ + +template +inline TPosition +positionGapToSeq(Gaps > const & me, TPosition const pos, TProjectionDir const & /*dir*/) +{ + typedef typename Position::Type>::Type TAnchorPos; + + GapAnchor prevAnchor, nextAnchor; + TPosition seqPos; + int anchorIdx; + + if (isNegative(pos)) + anchorIdx = -1; + else + { + TGapAnchors const & anchors = _dataAnchors(me); + TAnchorPos seqLength; + _assignSourceLength(seqLength, me); + if (!empty(anchors)) + { + anchorIdx = upperBoundGapAnchor(anchors, pos, SortGapPos()) - begin(anchors, Standard()); + if (anchorIdx < (int)length(anchors)) + if (anchors[anchorIdx].gapPos == (TAnchorPos)pos && anchors[anchorIdx].seqPos != seqLength) + ++anchorIdx; + } + else + anchorIdx = ((TAnchorPos)pos < seqLength) ? 0 : 1; + } + _getAnchor(prevAnchor, me, anchorIdx); + _getAnchor(nextAnchor, me, anchorIdx + 1); + + // View position points to a source. + if (nextAnchor.seqPos - prevAnchor.seqPos > (int)pos - prevAnchor.gapPos) + seqPos = prevAnchor.seqPos + (pos - prevAnchor.gapPos); + else // View position points to a gap + seqPos = (IsSameType::VALUE) ? nextAnchor.seqPos : + (_max(static_cast(nextAnchor.seqPos) - 1, static_cast(0))); + return seqPos; +} + +template +inline TPosition +positionGapToSeq(Gaps > const & me, TPosition pos) +{ + return positionGapToSeq(me, pos, RightOfViewPos()); +} + +// ---------------------------------------------------------------------------- +// Function positionSeqToGap() +// ---------------------------------------------------------------------------- + +/*! + * @fn AnchorGaps#positionSeqToGap + * @brief Convert from sequence space on the reference to gap space in the global alignment. + * + * @signature TPos positionSeqToGap(gaps, pos); + * + * @param[in] gaps The AnchorGaps object to use for the translation. + * @param[in] pos The gap space position to convert to sequence space. + * + * @return TPos The resulting position in sequence space (Metafunction: @link ContainerConcept#Position @endlink). + * + * See the example below to construct the gaps object. Note that this construction is fast since it is only a thin + * wrapper around underlying objects. + * + * @section Example + * + * Convert from gap space to position space on contig $contigId$ when the contigs required to be loaded. + * + * @code{.cpp} + * typedef typename TFragmentStore::TContigStore TContigStore; + * typedef typename Value::Type TContig; + * typedef typename TFragmentStore::TContigSeq TContigSeq; + * typedef Gaps > TContigGaps; + * + * TContigGaps contigGaps(contigStore[contigId].seq, contigStore[contigId].gaps); + * TAlignedReadPos pos = positionGapToSeq(contigGaps, 33); + * @endcode + * + * Convert from gap space to position space on contig $contigId$ when the contigs are not required. + * + * @code{.cpp} + * typedef typename TFragmentStore::TContigStore TContigStore; + * typedef typename Value::Type TContig; + * typedef Gaps > TContigGaps; + * + * TContigGaps contigGaps(Nothing(), contigStore[contigId].gaps); + * TAlignedReadPos endPos = positionGapToSeq(contigGaps, 33); + * @endcode + */ + +template +inline TPosition +positionSeqToGap(Gaps > const & me, TPosition pos) +{ + typedef typename Position::Type>::Type TAnchorPos; + + GapAnchor prevAnchor, nextAnchor; + TPosition gapPos; + int anchorIdx; + + if (isNegative(pos)) + anchorIdx = -1; + else + { + TGapAnchors const & anchors = _dataAnchors(me); + TAnchorPos seqLength; + _assignSourceLength(seqLength, me); + if (!empty(anchors)) + { + anchorIdx = upperBoundGapAnchor(anchors, pos, SortSeqPos()) - begin(anchors, Standard()); + if (anchorIdx < (int)length(anchors)) + if (anchors[anchorIdx].seqPos == (TAnchorPos)pos) + ++anchorIdx; + } + else + anchorIdx = ((TAnchorPos)pos < seqLength) ? 0 : 1; + } + _getAnchor(prevAnchor, me, anchorIdx); + _getAnchor(nextAnchor, me, anchorIdx + 1); + + if (nextAnchor.gapPos - prevAnchor.gapPos > (int)pos - prevAnchor.seqPos) + gapPos = prevAnchor.gapPos + (pos - prevAnchor.seqPos); + else + gapPos = nextAnchor.gapPos; + return gapPos; +} + +// ---------------------------------------------------------------------------- +// Function toViewPosition() +// ---------------------------------------------------------------------------- + +template +inline typename Position > >::Type +toViewPosition(Gaps > const & gaps, TPosition const sourcePosition) +{ + return positionSeqToGap(gaps, sourcePosition) - gaps.data_viewCutBegin - gaps.data_cutBegin; +} + +// ---------------------------------------------------------------------------- +// Function toSourcePosition() +// ---------------------------------------------------------------------------- + +template +inline typename Position::Type +toSourcePosition(Gaps > const & gaps, + TPosition const clippedViewPos, + TProjectionDir const /*dir*/) +{ + // TODO(weese): possibly change positionGapToSeq interface to consider a different zero + // shifted by data_cutBegin + return positionGapToSeq(gaps, clippedViewPos + gaps.data_viewCutBegin + gaps.data_cutBegin, TProjectionDir()); +} + +// ---------------------------------------------------------------------------- +// Function setClippedBeginPosition() +// ---------------------------------------------------------------------------- + +template +inline void +setClippedBeginPosition(Gaps > & gaps, TPosition unclippedViewPosition) +{ + gaps.data_viewCutBegin = unclippedViewPosition; +} + +// ---------------------------------------------------------------------------- +// Function setClippedEndPosition() +// ---------------------------------------------------------------------------- + +template +inline void +setClippedEndPosition(Gaps > & gaps, TPosition unclippedViewPosition) +{ + gaps.data_viewCutEnd = _unclippedLength(gaps) - unclippedViewPosition; +} + +// ---------------------------------------------------------------------------- +// Function clippedBeginPosition() +// ---------------------------------------------------------------------------- + +template +inline typename Position > >::Type +clippedBeginPosition(Gaps > const & gaps) +{ + return gaps.data_viewCutBegin; +} + +// ---------------------------------------------------------------------------- +// Function clippedEndPosition() +// ---------------------------------------------------------------------------- + +template +inline typename Position > >::Type +clippedEndPosition(Gaps > const & gaps) +{ + return _unclippedLength(gaps) - gaps.data_viewCutEnd; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ANCHOR_H_ diff --git a/seqan/align/gaps_array.h b/seqan/align/gaps_array.h new file mode 100644 index 0000000..840cbbb --- /dev/null +++ b/seqan/align/gaps_array.h @@ -0,0 +1,917 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// Author: Manuel Holtgrewe +// ========================================================================== + +// SEQAN_NO_GENERATED_FORWARDS + +// TODO(holtgrew): Currently, operations are a function of the whole gap count, could be of clipped region only. +// TODO(holtgrew): Problem with the gap value, getValue(), value(). + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ARRAY_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ARRAY_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// Internally used tag for creating iterators at the begin of containers. +struct Begin__; +typedef Tag Begin_; + +// Internally used tag for creating iterators at the end of containers. +struct End__; +typedef Tag End_; + +// Internally used tag for creating iterators inside of containers. +struct Position__; +typedef Tag Position_; + +struct ArrayGaps_; +typedef Tag ArrayGaps; + +template class Gaps; + +template +inline void _reinitArrayGaps(Gaps & gaps); + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +struct ArrayGaps_; +typedef Tag ArrayGaps; + +/*! + * @class ArrayGaps + * @headerfile + * @extends Gaps + * @brief Stores length of gap- and non-gap runs in an array. + * + * @signature template + * class Gaps + * + * @tparam TSequence The type of the underling sequence. + */ + +/*! + * @fn ArrayGaps::Gaps + * @headerfile + * @brief Constructor. + * + * @signature Gaps::Gaps([other]); + * @signature Gaps::Gaps(seq); + * + * @param[in] other Other Gaps object to copy from. + * @param[in] seq Sequence concept to construct the gaps for. + */ + +template +class Gaps +{ +public: + // ----------------------------------------------------------------------- + // Internal Typedefs + // ----------------------------------------------------------------------- + + typedef typename Size::Type TSize_; + typedef typename Size::Type TSequenceSize_; + typedef typename Position::Type TPosition_; + typedef typename Position::Type TSequencePosition_; + typedef typename Value::Type TValue_; + + typedef String TArray_; + typedef typename Position::Type TArrayPos_; + + // ----------------------------------------------------------------------- + // Member Variables + // ----------------------------------------------------------------------- + + // Holder of the underlying sequence. + Holder _source; + + // The array with the alternating gap/source char counts. + TArray_ _array; + + // Begin and end position in the source. + TSequencePosition_ _sourceBeginPos, _sourceEndPos; + // Begin and end position in the view. + TPosition_ _clippingBeginPos, _clippingEndPos; + // TODO(holtgrew): The following is a possible optimization. + // // Index of clipping begin and end in the _array seq/gap char count array. + // // This identifies a slice of the view. + // TArrayPos_ _clippingBeginIdx, _clippingEndIdx; + // // Offset within the slice. + // TSequenceSize_ _clippingBeginOffset, _clippingEndOffset; + + // ----------------------------------------------------------------------- + // Constructors + // ----------------------------------------------------------------------- + + Gaps() : _sourceBeginPos(0), _sourceEndPos(0), _clippingBeginPos(0), _clippingEndPos(0)//, + // _clippingBeginIdx(0), _clippingEndIdx(0), _clippingBeginOffset(0), _clippingEndOffset(0) + {} + + explicit + Gaps(TSequence & seq) : + _source(seq), _sourceBeginPos(0), _sourceEndPos(length(seq)), + _clippingBeginPos(0), _clippingEndPos(length(seq))//, + // _clippingBeginIdx(0), _clippingEndIdx(0), _clippingBeginOffset(0), + // _clippingEndOffset(0) + { + // Initialize array gaps object for ungapped sequence. + _reinitArrayGaps(*this); + } + + Gaps(Gaps const & other) : + _source(other._source), _array(other._array), _sourceBeginPos(other._sourceBeginPos), + _sourceEndPos(other._sourceEndPos), _clippingBeginPos(other._clippingBeginPos), + _clippingEndPos(other._clippingEndPos) + {} + + // ----------------------------------------------------------------------- + // Array Subscript Operator + // ----------------------------------------------------------------------- + + inline Gaps & + operator=(Gaps const & other) + { + setValue(_source, source(other)); + _array = other._array; + _sourceBeginPos = other._sourceBeginPos; + _sourceEndPos = other._sourceEndPos; + _clippingBeginPos = other._clippingBeginPos; + _clippingEndPos = other._clippingEndPos; + return *this; + } + + // ----------------------------------------------------------------------- + // Array Subscript Operator + // ----------------------------------------------------------------------- + + inline typename Reference::Type + operator[](TPosition_ const clippedViewPos) + { + return value(*this, clippedViewPos); + } + + inline typename Reference::Type + operator[](TPosition_ const clippedViewPos) const + { + return value(*this, clippedViewPos); + } +}; + +// ---------------------------------------------------------------------------- +// Function swap() +// ---------------------------------------------------------------------------- + +template +void swap(Gaps & lhs, Gaps & rhs) +{ + swap(lhs._source, rhs._source); + swap(lhs._array, rhs._array); + + std::swap(lhs._sourceBeginPos, rhs._sourceBeginPos); + std::swap(lhs._sourceEndPos, rhs._sourceEndPos); + std::swap(lhs._clippingBeginPos, rhs._clippingBeginPos); + std::swap(lhs._clippingEndPos, rhs._clippingEndPos); +} + +// ============================================================================ +// Metafunctions +// ============================================================================ + + + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function detach() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Remove? Only used by module blast. + +template +void detach(Gaps & gaps) +{ + detach(gaps._source); +} + +// ---------------------------------------------------------------------------- +// Function _setLength() +// ---------------------------------------------------------------------------- + +// Set the length, only use if TSequence is Nothing. + +template +inline void _setLength(Gaps & gaps, TSize newLen) +{ + // Reset array. + resize(gaps._array, 3); + gaps._array[0] = 0; + gaps._array[1] = newLen; + gaps._array[2] = 0; + // Reset clipping information. + gaps._clippingBeginPos = 0; + gaps._clippingEndPos = newLen; + gaps._sourceBeginPos = 0; + gaps._sourceEndPos = gaps._clippingEndPos; + // gaps._clippingBeginIdx = 1; + // gaps._clippingBeginOffset = 0; + // gaps._clippingEndIdx = 1; + // gaps._clippingEndOffset = value(gaps._source)[1]; +} + +// ---------------------------------------------------------------------------- +// Helper Function _reinitArrayGaps() +// ---------------------------------------------------------------------------- + +// Reset the array gaps DS such that represents the ungapped sequence. + +template +inline void _reinitArrayGaps(Gaps & gaps) +{ + _setLength(gaps, length(value(gaps._source))); +} + +// ---------------------------------------------------------------------------- +// Function begin() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): We'd rather have "TTag const &" here. +template +inline typename Iterator >::Type +begin(Gaps & gaps, Tag const /*tag*/) +{ + typedef typename Iterator >::Type TIter; + return TIter(gaps, Begin_()); +} + +// TODO(holtgrew): We'd rather have "TTag const &" here. +template +inline typename Iterator const>::Type +begin(Gaps const & gaps, Tag const /*tag*/) +{ + typedef typename Iterator const>::Type TIter; + return TIter(gaps, Begin_()); +} + +// ---------------------------------------------------------------------------- +// Function end() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): We'd rather have "TTag const &" here. +template +inline typename Iterator >::Type +end(Gaps & gaps, Tag const /*tag*/) +{ + typedef typename Iterator >::Type TIter; + return TIter(gaps, End_()); +} + +// TODO(holtgrew): We'd rather have "TTag const &" here. +template +inline typename Iterator const>::Type +end(Gaps const & gaps, Tag const /*tag*/) +{ + typedef typename Iterator const>::Type TIter; + return TIter(gaps, End_()); +} + +// ---------------------------------------------------------------------------- +// Function iter() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): We'd rather have "TTag const &" here. +template +inline typename Iterator >::Type +iter(Gaps & gaps, TPosition pos, Tag const /*tag*/) +{ + typedef typename Iterator >::Type TIter; + return TIter(gaps, pos, Position_()); +} + +// TODO(holtgrew): We'd rather have "TTag const &" here. +template +inline typename Iterator const>::Type +iter(Gaps const & gaps, TPosition pos, Tag const /*tag*/) +{ + typedef typename Iterator const>::Type TIter; + return TIter(gaps, pos, Position_()); +} + +// ---------------------------------------------------------------------------- +// Function length() +// ---------------------------------------------------------------------------- + +template +inline typename Size >::Type +length(Gaps const & gaps) +{ + SEQAN_ASSERT_GEQ(gaps._clippingEndPos, gaps._clippingBeginPos); + return gaps._clippingEndPos - gaps._clippingBeginPos; +} + +// ---------------------------------------------------------------------------- +// Function unclippedLength() +// ---------------------------------------------------------------------------- + +template +inline typename Size >::Type +unclippedLength(Gaps const & gaps) +{ + typedef typename Size >::Type TSize; + + TSize result = 0; + for (unsigned i = 0; i < length(gaps._array); ++i) + result += gaps._array[i]; + + return result; +} + +// ---------------------------------------------------------------------------- +// Function createSource() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Remove? Switch to Hosted Type Interface? + +template +inline void createSource(Gaps & gaps) +{ + create(gaps._source); +} + +// ---------------------------------------------------------------------------- +// Function source() +// ---------------------------------------------------------------------------- + +template +inline typename Source const>::Type & +source(Gaps const & gaps) +{ + return value(gaps._source); +} + +template +inline typename Source >::Type & +source(Gaps & gaps) +{ + return value(gaps._source); +} + +// ---------------------------------------------------------------------------- +// Function setSource() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Test with clippings, also for AnchorGaps. + +template +inline void +setSource(Gaps & gaps, TSequence & source) +{ + setValue(gaps._source, source); + _reinitArrayGaps(gaps); +} + +template +inline void +setSource(Gaps & gaps, TSequence & source) +{ + setValue(gaps._source, source); + _reinitArrayGaps(gaps); +} + +// ---------------------------------------------------------------------------- +// Function assignSource() +// ---------------------------------------------------------------------------- + +template +inline void +assignSource(Gaps & gaps, TSequence2 const & source) +{ + value(gaps._source) = source; + _reinitArrayGaps(gaps); +} + +// ---------------------------------------------------------------------------- +// Function toSourcePosition() +// ---------------------------------------------------------------------------- + +template +inline typename Position::Type +toSourcePosition(Gaps const & gaps, TPosition const clippedViewPos, LeftOfViewPos const & /*tag*/) +{ + typedef Gaps TGaps; + typedef typename Position::Type TGapsPos; + typedef typename TGaps::TArrayPos_ TArrayPos; + typedef typename Position::Type TSourcePos; + + // Translate from clipped view position to unclipped view position. + TGapsPos unclippedViewPos = clippedViewPos + clippedBeginPosition(gaps); + + // Get index i of the according bucket and offset within bucket. + TSourcePos result = 0; + TArrayPos i = 1; + TSourcePos const iEnd = length(gaps._array); + + if (unclippedViewPos < static_cast(gaps._array[0])) + return 0; + + TSourcePos counter = unclippedViewPos - gaps._array[0]; + for (; counter > TGapsPos(0) && i < iEnd; ++i) + { + if (counter < gaps._array[i]) + break; + + if (i % 2) // character bucket + result += gaps._array[i]; + counter -= gaps._array[i]; + } + if (i % 2) // character bucket. + { + if (i == length(gaps._array)) // We pointing behind the last bucket. + return --result; + result += counter; // If maps into char bucket. + if (counter == gaps._array[i]) + --result; + return result; + } + return --result; +} + +template +inline typename Position::Type +toSourcePosition(Gaps const & gaps, TPosition const clippedViewPos, RightOfViewPos const & /*tag*/) +{ + typedef Gaps TGaps; + typedef typename Position::Type TGapsPos; + typedef typename TGaps::TArrayPos_ TArrayPos; + typedef typename Position::Type TSourcePos; + + // Translate from clipped view position to unclipped view position. + TGapsPos unclippedViewPos = clippedViewPos + clippedBeginPosition(gaps); + + // Get index i of the according bucket and offset within bucket. + TSourcePos result = 0; + TArrayPos i = 0; + TSourcePos const iEnd = length(gaps._array); + + for (TSourcePos counter = unclippedViewPos; counter > TGapsPos(0) && i < iEnd;) + { + if (counter > gaps._array[i]) + { + if (i % 2) // character bucket + result += gaps._array[i]; + counter -= gaps._array[i]; + i += 1; + } + else if (counter <= gaps._array[i]) + { + if (i % 2) // character bucket + result += counter; + counter = 0; + } + } + + return result; +} + +// ---------------------------------------------------------------------------- +// Function toViewPosition() +// ---------------------------------------------------------------------------- + +// Parameter rightOfGaps moves to the right end of gaps if the character at sourcePosition is followed by a gap in the +// view. +template +inline typename Position >::Type +toViewPosition(Gaps const & gaps, TPosition sourcePosition, bool rightOfGaps = true) +{ + typedef Gaps TGaps; + typedef typename Position::Type TGapsPosition; + typedef typename TGaps::TArray_ TArray; + typedef typename TGaps::TArrayPos_ TArrayPos; + typedef typename Value::Type TArrayValue; + + if (sourcePosition == TPosition(0)) + return gaps._array[0] - clippedBeginPosition(gaps); + + // First, convert to unclipped source position. + TGapsPosition unclippedViewPosition = 0; + TArrayPos i = 0; + for (TArrayValue counter = sourcePosition; counter > TArrayValue(0); ++i) + { + if (i % 2 /*== 1*/) // sequence bucket + { + if (counter > gaps._array[i]) + { + unclippedViewPosition += gaps._array[i]; + counter -= gaps._array[i]; + } + else if (counter < gaps._array[i]) + { + unclippedViewPosition += counter; + counter = 0; + } + else // counter == gaps._array[i] + { + unclippedViewPosition += counter; + if (rightOfGaps && i + 2 < length(gaps._array)) + unclippedViewPosition += gaps._array[i + 1]; + counter = 0; + } + } + else // gaps bucket + { + unclippedViewPosition += gaps._array[i]; + } + } + + // Return after clipping. + return unclippedViewPosition - clippedBeginPosition(gaps); +} + +// ---------------------------------------------------------------------------- +// Function insertGaps() +// ---------------------------------------------------------------------------- + +template +inline void +insertGaps(Gaps & gaps, TPosition clippedViewPos, TCount count) +{ + typedef Gaps TGaps; + typedef typename Position::Type TGapsPosition; + typedef typename TGaps::TArray_ TArray; + typedef typename TGaps::TArrayPos_ TArrayPos; + typedef typename Position::Type TSeqPos; + + // Translate from clipped view position to unclipped view position. + TGapsPosition unclippedViewPos = clippedViewPos + clippedBeginPosition(gaps); + + // Get index i of the according bucket and offset within bucket. + TArrayPos i = 0; + TSeqPos offset = 0; + for (TSeqPos counter = unclippedViewPos; counter > 0;) + { + SEQAN_ASSERT_LT(i, length(gaps._array)); + if (counter > gaps._array[i]) + { + counter -= gaps._array[i]; + i += 1; + } + else + { + offset = counter; + counter = 0; + } + } + + SEQAN_ASSERT_GEQ(gaps._array[i], offset); + + // Insert gaps, simple and fast if we are in a gaps bucket, a bit harder + // otherwise. + if (i % 2) // character bucket + { + if (gaps._array[i] > offset) // In the middle of the bucket. + { + TArray arr; + resize(arr, 2, 0); + arr[0] = count; + arr[1] = gaps._array[i] - offset; + gaps._array[i] = offset; + insert(gaps._array, i + 1, arr); + } + else // At the end of the bucket. + { + if (i + 1 < length(gaps._array)) // Not at end of array. + { + gaps._array[i + 1] += count; + } + else // At end of array. + { + resize(gaps._array, length(gaps._array) + 2, 0); + gaps._array[i + 1] = count; + gaps._array[i + 2] = 0; + } + } + } + else // gap bucket + { + gaps._array[i] += count; + } + + // Adjust clipping information. + gaps._clippingEndPos += count; +} + +// ---------------------------------------------------------------------------- +// Function removeGaps() +// ---------------------------------------------------------------------------- + +template +inline typename Size >::Type +removeGaps(Gaps & gaps, TPosition clippedViewPos, TCount count) +{ + typedef Gaps TGaps; + typedef typename Position::Type TGapsPosition; + typedef typename TGaps::TArray_ TArray; + typedef typename TGaps::TArrayPos_ TArrayPos; + typedef typename Value::Type TArrayValue; + typedef typename Position::Type TSeqPos; + + // Translate from clipped view position to unclipped view position. + TGapsPosition pos = clippedViewPos + clippedBeginPosition(gaps); + + // Get index i of the according bucket and offset within bucket. + SEQAN_ASSERT_GEQ(length(gaps._array), 2u); + // Start at position 1 if there are no leading gaps. + TArrayPos i = (gaps._array[0] == 0); + TSeqPos offset = 0; + for (TSeqPos counter = pos; counter > 0;) + { + SEQAN_ASSERT_LT(i, length(gaps._array)); + if (counter > gaps._array[i]) + { + counter -= gaps._array[i]; + i += 1; + } + else + { + offset = counter; + counter = 0; + } + } + + // Advance into next bucket if at end of current. + if (offset > 0 && offset == gaps._array[i]) + { + i += 1; + offset = 0; + } + + // If we are inside a non-gap bucket then we cannot remove any gaps. + if (i % 2) + return 0; + + // Otherwise, we can remove gaps right of the current position but not + // more than there are. + TSeqPos toRemove = count; + if (toRemove > gaps._array[i] - offset) + toRemove = gaps._array[i] - offset; + gaps._array[i] -= toRemove; + // In some cases, we remove the whole gap and merge the character buckets. + if (gaps._array[i] == TArrayValue(0)) + { + // No merging for leading and trailing gap. + if (i != TArrayPos(0) && i != TArrayPos(length(gaps._array) - 1)) + { + gaps._array[i - 1] += gaps._array[i + 1]; + erase(gaps._array, i, i + 2); + } + } + + // Also update the right clipping position. + gaps._clippingEndPos -= toRemove; + + // Finally, return number of removed gaps. + return toRemove; +} + +// ---------------------------------------------------------------------------- +// Function clearGaps() +// ---------------------------------------------------------------------------- + +template +inline void +clearGaps(Gaps & gaps) +{ + _reinitArrayGaps(gaps); +} + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +template +inline void +clear(Gaps & gaps) +{ + clear(gaps._source); + clear(gaps._array); + gaps._sourceBeginPos = 0; + gaps._sourceEndPos = 0; + gaps._clippingBeginPos = 0; + gaps._clippingEndPos = 0; + // cannot use clearGaps() here, since that calls value() on _source + // which instates the Holder to Owner; we want it to be empty +} + +// ---------------------------------------------------------------------------- +// Function isGap() +// ---------------------------------------------------------------------------- + +template +inline bool +isGap(Gaps const & gaps, TPosition clippedViewPos) +{ + typedef Gaps TGaps; + typedef typename Position::Type TGapsPosition; + typedef typename TGaps::TArrayPos_ TArrayPos; + typedef typename Position::Type TSeqPos; + + // Translate from clipped view position to unclipped view position. + TGapsPosition pos = clippedViewPos + clippedBeginPosition(gaps); + + // Get index i of the according bucket and offset within bucket. + SEQAN_ASSERT_GEQ(length(gaps._array), 2u); + // Start at position 1 if there are no leading gaps. + TArrayPos i = (gaps._array[0] == 0); + TSeqPos offset = 0; + for (TSeqPos counter = pos; counter > TSeqPos(0);) + { + SEQAN_ASSERT_LT(i, length(gaps._array)); + if (counter > gaps._array[i]) + { + counter -= gaps._array[i]; + i += 1; + } + else + { + offset = counter; + counter = 0; + } + } + + // Advance into next bucket if at end of current. + if (offset > TSeqPos(0) && offset == gaps._array[i]) + i += 1; + + return !(i % 2); +} + +// ---------------------------------------------------------------------------- +// Function clearClipping() +// ---------------------------------------------------------------------------- + +template +inline void +clearClipping(Gaps & gaps) +{ + typedef Gaps TGaps; + typedef typename TGaps::TArrayPos_ TArrayPos; + + gaps._sourceBeginPos = 0; + gaps._sourceEndPos = length(value(gaps._source)); + gaps._clippingBeginPos = 0; + gaps._clippingEndPos = 0; + for (TArrayPos i = 0; i < length(gaps._array); ++i) + gaps._clippingEndPos += gaps._array[i]; + + SEQAN_ASSERT_LEQ(static_cast(gaps._sourceEndPos), static_cast(gaps._clippingEndPos)); +} + +// ---------------------------------------------------------------------------- +// Function setClippedBeginPosition() +// ---------------------------------------------------------------------------- + +template +inline void +setClippedBeginPosition(Gaps & gaps, TPosition unclippedViewPosition) +{ + gaps._sourceBeginPos = toSourcePosition(gaps, unclippedViewPosition - clippedBeginPosition(gaps)); + gaps._clippingBeginPos = unclippedViewPosition; +} + +// ---------------------------------------------------------------------------- +// Function setClippedEndPosition() +// ---------------------------------------------------------------------------- + +template +inline void +setClippedEndPosition(Gaps & gaps, TPosition unclippedViewPosition) +{ + gaps._sourceEndPos = toSourcePosition(gaps, unclippedViewPosition - clippedBeginPosition(gaps)); + //if (isGap(gaps, unclippedViewPosition - clippedBeginPosition(gaps))) + // gaps._sourceEndPos += 1; + gaps._clippingEndPos = unclippedViewPosition; +} + +// ---------------------------------------------------------------------------- +// Function clippedBeginPosition() +// ---------------------------------------------------------------------------- + +template +inline typename Position >::Type +clippedBeginPosition(Gaps const & gaps) +{ + return gaps._clippingBeginPos; +} + +// ---------------------------------------------------------------------------- +// Function clippedEndPosition() +// ---------------------------------------------------------------------------- + +template +inline typename Position >::Type +clippedEndPosition(Gaps const & gaps) +{ + return gaps._clippingEndPos; +} + +// ---------------------------------------------------------------------------- +// Function setBeginPosition() +// ---------------------------------------------------------------------------- + +template +inline void +setBeginPosition(Gaps & gaps, TPosition sourcePosition) +{ + setClippedBeginPosition(gaps, toViewPosition(gaps, sourcePosition) + clippedBeginPosition(gaps)); +} + +// ---------------------------------------------------------------------------- +// Function setEndPosition() +// ---------------------------------------------------------------------------- + +template +inline void +setEndPosition(Gaps & gaps, TPosition sourcePosition) +{ + setClippedEndPosition(gaps, toViewPosition(gaps, sourcePosition) + clippedBeginPosition(gaps)); +} + +// ---------------------------------------------------------------------------- +// Function beginPosition() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): We would rather like to have the const version only :( +template +inline typename Position::Type +beginPosition(Gaps const & gaps) +{ + return gaps._sourceBeginPos; +} + +template +inline typename Position::Type +beginPosition(Gaps & gaps) +{ + return gaps._sourceBeginPos; +} + +// ---------------------------------------------------------------------------- +// Function endPosition() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): We would rather like to have the const version only :( +template +inline typename Position::Type +endPosition(Gaps const & gaps) +{ + return gaps._sourceEndPos; +} + +template +inline typename Position::Type +endPosition(Gaps & gaps) +{ + return gaps._sourceEndPos; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ARRAY_H_ diff --git a/seqan/align/gaps_base.h b/seqan/align/gaps_base.h new file mode 100644 index 0000000..e187688 --- /dev/null +++ b/seqan/align/gaps_base.h @@ -0,0 +1,1234 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +// TODO(holtgrew): Switch to Host interface. + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_BASE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_BASE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +template +struct GapsIterator; + +/*! + * @defgroup GapsSpecTag Gaps Specialization Tags + * @brief Tags for specializing the Gaps class. + */ + +/*! + * @tag GapsSpecTag#ArrayGaps + * @headerfile + * @brief Tag for the Array Gaps specialization. + * + * @signature struct ArrayGaps_; + * @signature typedef Tag ArrayGaps; + */ + +struct ArrayGaps_; +typedef Tag ArrayGaps; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @defgroup GapDirectionTags Gap Direction Tags + * @brief Tags to select the direction to which side of a view position an operation should be projected. + */ + +/*! + * @tag GapDirectionTags#LeftOfViewPos + * @headerfile + * @brief Projects to the left side of the current view position. + * + * @signature struct LeftOfViewPos_; + * typedef Tag LeftOfViewPos; + */ + +struct LeftOfViewPos_; +typedef Tag LeftOfViewPos; + +/*! + * @tag GapDirectionTags#RightOfViewPos + * @headerfile + * @brief Projects to the right side of the current view position. + * + * @signature struct RightOfViewPos_; + * typedef Tag RightOfViewPos; + */ + +struct RightOfViewPos_; +typedef Tag RightOfViewPos; + +// ---------------------------------------------------------------------------- +// Class Gaps +// ---------------------------------------------------------------------------- + +/*! + * @class Gaps + * @implements ContainerConcept + * @headerfile + * @brief Store the gapped version of a sequence. + * + * @signature template + * class Gaps; + * + * @tparam TSequence The type of the underlying sequence. + * @tparam TSpec Tag for specialization. + * + * Gaps wrap a @link ContainerConcept Sequence @endlink and allows one to (1) insert gaps into the sequence and (2) select + * an infix of the gapped sequence (clipping). The gaps are not inserted into the underlying sequence (source) but + * stored separately. Using the clipping is optional and meant for selecting parts of the alignment as a part of the + * result of a local alignment algorithm. + * + * + * + * In the figure above, the source sequence has seven characters, the gapped sequence has four gaps and thus consists + * of eleven characters. The gapped sequence is clipped to start at position 0 in the gapped sequence and to end at + * position 8 in the gapped sequence (the positions given as half-open intervals [begin, end)). + * + * The figure shows the three coordinate systems that are used with Gaps objects. The source position is the position + * in the underlying sequence. The unclipped view position is the position in the gapped sequence without gaps. The + * view position is the position in the gapped sequence but including the clipping: All (clipped) view positions have + * the clipping begin position subtracted from them. + * + * @section Examples + * + * The following example shows the construction of the gaps object from the image above together with some calls to + * toViewPosition and toSourcePosition. + * + * @include demos/dox/align/gaps_example.cpp + * + * The output is as follows: + * + * @include demos/dox/align/gaps_example.cpp.stdout + */ + +template +class Gaps; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Value +// ---------------------------------------------------------------------------- + +template +struct Value > +{ + typedef typename Value::Type TAlphabet; + typedef typename GappedValueType::Type Type; +}; + +template +struct Value const> : Value > +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Iterator +// ---------------------------------------------------------------------------- + +template +struct Iterator, TIteratorSpec> +{ + typedef Iter, GapsIterator > Type; +}; + +template +struct Iterator const, TIteratorSpec> +{ + typedef Iter const, GapsIterator > Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction GetValue +// ---------------------------------------------------------------------------- + +template +struct GetValue > : Value > +{}; + +template +struct GetValue const> : GetValue > +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Position +// ---------------------------------------------------------------------------- + +template +struct Position > +{ + typedef typename Position::Type TSeqPos_; + typedef typename MakeSigned::Type Type; +}; + +template +struct Position const> : Position > +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Reference +// ---------------------------------------------------------------------------- + +template +struct Reference > +{ + typedef typename Iterator, Standard>::Type TIterator_; + typedef Proxy > Type; +}; + +template +struct Reference const> +{ + typedef typename Iterator const, Standard>::Type TIterator_; + typedef Proxy > Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Size +// ---------------------------------------------------------------------------- + +template +struct Size > +{ + typedef typename Size::Type Type; +}; + +template +struct Size const> : Size > +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Source +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Switch to Hosted Type interface + +template +struct Source > +{ + typedef TSequence Type; +}; + +template +struct Source const> : Source > +{}; + +// TODO(holtgrew): Also prefix/suffix/infix? Should work! + +// ---------------------------------------------------------------------------- +// Metafunction IsSequence +// ---------------------------------------------------------------------------- + +template +struct IsSequence > +{ + typedef True Type; + static const bool VALUE = true; +}; + +template +struct IsSequence const> : IsSequence > +{}; + + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function value() +// ---------------------------------------------------------------------------- + +template +inline typename Reference >::Type +value(Gaps & gaps, + TPosition const clippedViewPos) +{ + return typename Reference >::Type(begin(gaps, Standard()) + clippedViewPos); +} + +template +inline typename Reference const>::Type +value(Gaps const & gaps, + TPosition const clippedViewPos) +{ + return typename Reference const>::Type(begin(gaps, Standard()) + clippedViewPos); +} + +// ---------------------------------------------------------------------------- +// Function iter() +// ---------------------------------------------------------------------------- + +// From ContainerConcept, only overwriting documentation here. + +/*! + * @fn Gaps#iter + * @brief Return an iterator to a specific position in the current clipping. + * + * @signature TIterator iter(gaps, viewPos[, tag]); + * + * @param[in] gaps The Gaps object to get an iterator into. + * @param[in] viewPos View position to get an iterator to (Metafunction: @link ContainerConcept#Position @endlink). + * @param[in] tag An optional tag for selecting the iterator type. + * + * @return TIterator The resulting iterator. The type is Iterator::Type where TTag is + * the type of tag. + */ + +// TODO(holtgrew): Adding links to implemented sequence. This should be cleaned up once we have better documentation with concepts. +// ---------------------------------------------------------------------------- +// Function setSource() +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Function createSource() +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Function clearClipping() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#clearClipping + * @brief Clear clipping from Gaps objects. + * + * @signature void clearClipping(gaps); + * + * @param[in,out] gaps Object to clear clipping from. + */ + +// ---------------------------------------------------------------------------- +// Function clearGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#clearGaps + * @brief Clear gaps from Gaps objects. + * + * @signature void clearGaps(gaps); + * + * @param[in,out] gaps Object to clear gaps from. + */ + +// ---------------------------------------------------------------------------- +// Function length() +// ---------------------------------------------------------------------------- + +// From ContainerConcept, only overwriting documentation here. + +/*! + * @fn Gaps#length + * @brief Return number of gap and characters between the beginning and the end of the clipping. + * + * @signature TSize length(gaps); + * + * @param[in] gaps The @link Gaps @endlink object to query for its length. + * + * @return TSize The number of gaps and characters between the beginning and the end of the clipping (Metafunction: + * @link ContainerConcept#Size @endlink). + */ + +// ---------------------------------------------------------------------------- +// Function unclippedLength() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#unclippedLength + * @brief Return length of the gapped sequence without clipping. + * + * @signature TSize unclippedLength(gaps); + * + * @param[in] gaps The Gaps object to query. + * + * @return TSize The result (Metafunction: @link ContainerConcept#Size @endlink). + */ + +// ---------------------------------------------------------------------------- +// Function toViewPosition() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#toViewPosition + * @brief Conversion from source (without gaps or clipping) to view position (including gaps and clipping). + * + * @signature TPos toViewPosition(gaps, sourcePos); + * + * @param[in] gaps The gaps object to use for translation. + * @param[in] sourcePos The source position (in the underlying sequence) to translate. + * + * @return TPos The resulting position in the view (Metafunction: @link ContainerConcept#Position @endlink). + */ + +// ---------------------------------------------------------------------------- +// Function toSourcePosition() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#toSourcePosition + * @brief Conversion from view position (including gaps and clipping) to source (without gaps or clipping). + * + * @signature TPos toSourcePosition(gaps, viewPos); + * + * @param[in] gaps The gaps object to use for translation. + * @param[in] sourcePos The view position (including gaps and clipping) to translate. + * + * @return TPos The resulting position in the underlying sequence (Metafunction: @link ContainerConcept#Position + * @endlink). + */ + +template +inline typename Position::Type +toSourcePosition(Gaps const & gaps, TPosition const clippedViewPos) +{ + return toSourcePosition(gaps, clippedViewPos, RightOfViewPos()); +} + +// ---------------------------------------------------------------------------- +// Function isGap() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#isGap + * @brief Query positions in a Gaps object for being a gap. + * + * @signature bool isGap(gaps, viewPos); + * + * @param[in] gaps The Gaps object to query. + * @param[in] viewPos The view position (including clipping and gaps). + * + * @return bool The query result. + */ + +template +bool isGap(Gaps const & gaps, TPos clippedViewPos) +{ + return isGap(iter(gaps, clippedViewPos, Standard())); +} + +// ---------------------------------------------------------------------------- +// Function isCharacter() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#isCharacer + * @brief Query positions in a Gaps object for being a character. + * + * @signature bool isGap(gaps, viewPos); + * + * @param[in] gaps The Gaps object to query. + * @param[in] viewPos The view position (including clipping and gaps). + * + * @return bool The query result. + */ + +template +bool isCharacter(Gaps const & gaps, TPos clippedViewPos) +{ + return isCharacter(iter(gaps, clippedViewPos, Standard())); +} + +// ---------------------------------------------------------------------------- +// Function insertGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#insertGaps + * @brief Insert gap characters. + * + * @signature void insertGaps(gaps, viewPos, count); + * + * @param[in,out] gaps The Gaps object to insert gaps into. + * @param[in] viewPos The view position (including clipping and gaps) to insert gaps at. + * @param[in] count The number of gaps to insert. + */ + +// ---------------------------------------------------------------------------- +// Function insertGap() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#insertGap + * @brief Insert one gap character. + * + * @signature void insertGap(gaps, viewPos); + * + * @param[in,out] gaps The Gaps object to insert gap into. + * @param[in] viewPos The view position (including clipping and gaps) to insert the gap at. + */ + +// Forward to removeGaps() which has to be implemented in each subclass. + +template +inline void +insertGap(Gaps & gaps, TPosition clippedViewPos) +{ + insertGaps(gaps, clippedViewPos, 1u); +} + +// ---------------------------------------------------------------------------- +// Function removeGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#removeGaps + * @brief Remove gaps from a Gaps object. + * + * @signature TSize removeGaps(gaps, viewPos, count); + * + * @param[in,out] gaps The gaps object to remove gap characters from. + * @param[in] viewPos The view positions to remove gap characters from. + * @param[in] count The number of gap characters to remove. + * + * @return TSize The number of gap characters removed (Metafunction: @link ContainerConcept#Size @endlink). + */ + +// ---------------------------------------------------------------------------- +// Function removeGap() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#removeGap + * @brief Remove one gap from a Gaps object. + * + * @signature TSize removeGap(gaps, viewPos); + * + * @param[in,out] gaps The gaps object to remove one gap character from. + * @param[in] viewPos The view positions to remove one gap character from. + * + * @return TSize The number of gap characters removed (Metafunction: @link ContainerConcept#Size @endlink). + */ + +// Forward to removeGaps() which has to be implemented in each subclass. + +template +inline typename Size >::Type +removeGap(Gaps & gaps, TPosition clippedViewPos) +{ + return removeGaps(gaps, clippedViewPos, 1u); +} + +// ---------------------------------------------------------------------------- +// Function countGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#countGaps + * @brief The number of gaps following a position. + * + * @signature TSize countGaps(gaps, viewPos[, dir]); + * + * @param[in] gaps The Gaps object to query. + * @param[in] viewPos View position (including clipping and gaps) to query at. + * @param[in] dir A tag to specify the counting direction. One of @link GapDirectionTags @endlink. + * Defaults to @link GapDirectionTags#RightOfViewPos @endlink. + * + * @return TSize The number of gap characters at viewPos (Metafunction: @link ContainerConcept#Size + * @endlink). + * + * If the the direction tag is @link GapDirectionTags#RightOfViewPos @endlink the current view position will be + * included in the count, and excluded when @link GapDirectionTags#LeftOfViewPos @endlink is selected. + */ + +template +typename Size >::Type +countGaps(Gaps const & gaps, TPos const clippedViewPos, TDirSpec const & /*tag*/) +{ + return countGaps(iter(gaps, clippedViewPos, Standard()), TDirSpec()); +} + +template +typename Size >::Type +countGaps(Gaps const & gaps, TPos const clippedViewPos) +{ + return countGaps(gaps, clippedViewPos, RightOfViewPos()); +} + +// ---------------------------------------------------------------------------- +// Function countLeadingGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#countLeadingGaps + * @brief The number of leading gaps. + * + * @signature TSize countLeadingGaps(gaps); + * + * @param[in] gaps The Gaps object to query. + * + * @return TSize The number of leading gap characters (Metafunction: @link ContainerConcept#Size @endlink). + */ + +template +inline typename Size::Type +countLeadingGaps(TGaps const & gaps) +{ + return toViewPosition(gaps, 0); +} + +// ---------------------------------------------------------------------------- +// Function countTrailingGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#countTrailingGaps + * @brief The number of trailing gaps. + * + * @signature TSize countTrailingGaps(gaps); + * + * @param[in] gaps The Gaps object to query. + * + * @return TSize The number of trailing gap characters (Metafunction: @link ContainerConcept#Size @endlink). + */ + +template +inline typename Size::Type +countTrailingGaps(TGaps const & gaps) +{ + return length(gaps) - toViewPosition(gaps, length(source(gaps)) - 1) - 1; +} + +// ---------------------------------------------------------------------------- +// Function countGapOpens() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#countGapOpens + * @brief The number of gap openings. + * + * @signature TSize countGapOpens(gaps); + * + * @param[in] gaps The Gaps object to query. + * + * @return TSize The total number of gap openings (Metafunction: @link ContainerConcept#Size @endlink). + */ + +template +inline typename Size::Type +countGapOpens(TGaps const & gaps) +{ + typedef typename Iterator::Type TIter; + typedef typename Size::Type TCount; + + TCount count = 0; + + TIter it = begin(gaps, Standard()); + TIter itEnd = end(gaps, Standard()); + + while (it != itEnd) + { + count += isGap(it); + it += std::max(countGaps(it), (TCount)1); + } + + SEQAN_ASSERT(it == itEnd); + + return count; +} + +// ---------------------------------------------------------------------------- +// Function countGapExtensions() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#countGapExtensions + * @brief The number of gap extensions. + * + * @signature TSize countGapExtensions(gaps); + * + * @param[in] gaps The Gaps object to query. + * + * @return TSize The total number of gap extensions (Metafunction: @link ContainerConcept#Size @endlink). + */ + +template +inline typename Size::Type +countGapExtensions(TGaps const & gaps) +{ + typedef typename Iterator::Type TIter; + typedef typename Size::Type TCount; + + TCount count = 0; + + TIter it = begin(gaps, Standard()); + TIter itEnd = end(gaps, Standard()); + + while (it != itEnd) + { + count += countGaps(it); + it += std::max(countGaps(it), (TCount)1); + } + + SEQAN_ASSERT(it == itEnd); + + return count; +} + +// ---------------------------------------------------------------------------- +// Function countCharacters() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#countCharacters + * @brief The number of characters following a position. + * + * @signature TSize countCharacters(gaps, viewPos[, dir]); + * + * @param[in] gaps The Gaps object to query. + * @param[in] viewPos View position (including clipping and gaps) to query at. + * @param[in] dir A tag to specify the counting direction. One of @link GapDirectionTags @endlink. + * Defaults to @link GapDirectionTags#RightOfViewPos @endlink. + * + * @return TSize The number of non-gaps characters characters at viewPos (Metafunction: @link + * ContainerConcept#Size @endlink). + * + * If the the direction tag is @link GapDirectionTags#RightOfViewPos @endlink the current view position will be + * included in the count, and excluded when @link GapDirectionTags#LeftOfViewPos @endlink is selected. + */ + +template +typename Size >::Type +countCharacters(Gaps const & gaps, + TPos const clippedViewPos, + TDirSpec const & /*dir*/) +{ + return countCharacters(iter(gaps, clippedViewPos, Standard()), TDirSpec()); +} + +template +typename Size >::Type +countCharacters(Gaps const & gaps, TPos const clippedViewPos) +{ + return countCharacters(gaps, clippedViewPos, RightOfViewPos()); +} + +// ---------------------------------------------------------------------------- +// Function setClippedBeginPosition() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#setClippedBeginPosition + * @brief Set the begin position of the clipping. + * + * @signature void setClippedBeginPosition(gaps, unclippedViewPos); + * + * @param[in,out] gaps The Gaps object to set the clipping begin position of. + * @param[in] unclippedViewPos View position (including gaps but excluding clipping) to set the clipping begin to. + */ + +// ---------------------------------------------------------------------------- +// Function setClippedEndPosition() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#setClippedEndPosition + * @brief Set the end position of the clipping. + * + * @signature void setClippedEndPosition(gaps, unclippedViewPos); + * + * @param[in,out] gaps The Gaps object to set the clipping end position of. + * @param[in] unclippedViewPos View position (including gaps but excluding clipping) to set the clipping end to. + */ + +// ---------------------------------------------------------------------------- +// Function clippedBeginPosition() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#clippedBeginPosition + * @brief Return begin position of the clipping. + * + * @signature TPos clippedBeginPosition(gaps); + * + * @param[in] gaps The Gaps object to query. + * + * @return TPos The begin position of the unclipped view (Metafunction: @link ContainerConcept#Position @endlink). + * + * @section Example + * + * In the following gaps configuration, the result of clippedBeginPosition(gaps) is 1. + * + * @code{.txt} + * clipping [ ) + * (half-open interval) + * + * gapped sequence: X--XXX-XX- + * + * source position: 0111234456 + * unclipped view position: 0123456789 + * clipped view position: 0123456 + * @endcode + */ + +// ---------------------------------------------------------------------------- +// Function clippedEndPosition() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#clippedEndPosition + * @brief Return end position of the clipping. + * + * @signature TPos clippedEndPosition(gaps); + * + * @param[in] gaps The Gaps object to query. + * + * @return TPos The end position of the unclipped view (Metafunction: @link ContainerConcept#Position @endlink). + * + * @section Example + * + * In the following gaps configuration, the result of clippedEndPosition(gaps) is 7. + * + * @code{.txt} + * clipping [ ) + * (half-open interval) + * + * gapped sequence: X--XXX-XX- + * + * source position: 0111234456 + * unclipped view position: 0123456789 + * clipped view position: 0123456 + * @endcode + */ + +// ---------------------------------------------------------------------------- +// Function setBeginPosition() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#setBeginPosition + * @brief Set the begin position of the clipped gapped sequence, given a source position. + * + * @signature void setBeginPosition(gaps, sourcePos); + * + * @param[in,out] gaps The Gaps object to set the begin position in. + * @param[in] sourcePos Position in the underlying sequence to set clipping to. + */ + +// ---------------------------------------------------------------------------- +// Function setEndPosition() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#setEndPosition + * @brief Set the end position of the clipped gapped sequence, given a source position. + * + * @signature void setEndPosition(gaps, sourcePos); + * + * @param[in,out] gaps The Gaps object to set the end position in. + * @param[in] sourcePos Position in the underlying sequence to set clipping to. + */ + +// ---------------------------------------------------------------------------- +// Function beginPosition() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#beginPosition + * @brief Return the clipping begin position as a source position. + * + * @signature TPos beginPosition(gaps); + * + * @param[in] gaps The Gaps object to query. + * + * @return TPos The clipping begin position in the source (Metafunction: @link ContainerConcept#Position @endlink). + * + * @section Example + * + * In the following gaps configuration, the result of beginPosition(gaps) is $1$. The clipping starts in a + * gap and the source position of the first non-gap character right of the clipping begin has source position 1. + * + * @code{.txt} + * clipping [ ) + * (half-open interval) + * + * gapped sequence: X--XXX-XX- + * + * source position: 0111234456 + * unclipped view position: 0123456789 + * clipped view position: 0123456 + * @endcode + */ + +// ---------------------------------------------------------------------------- +// Function endPosition() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#endPosition + * @brief Return the clipping end position as a source position. + * + * @signature TPos endPosition(gaps); + * + * @param[in] gaps The Gaps object to query for the end position as a source position. + * + * @return TPos The end position as a source position (Metafunction: @link ContainerConcept#Position @endlink). + * + * @section Example + * + * In the following gaps configuration, the result of endPositioN(gaps) is 4. + * + * @code{.txt} + * clipping [ ) + * (half-open interval) + * + * gapped sequence: X--XXX-XX- + * + * source position: 0111234456 + * unclipped view position: 0123456789 + * clipped view position: 0123456 + * @endcode + */ + +// ---------------------------------------------------------------------------- +// Function write() +// ---------------------------------------------------------------------------- + +template +inline void +write(TTarget & target, + Gaps const & source) +{ + // Print gaps row + typedef typename Iterator const>::Type TIter; + TIter begin_ = begin(source); + TIter end_ = end(source); + for (; begin_ != end_; ++begin_) { + if (isGap(begin_)) + writeValue(target, gapValue()); + else + writeValue(target, convert(getValue(begin_))); + } +} + +// ---------------------------------------------------------------------------- +// Function operator<<() [stream operator] +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Document appropriately. + +template +inline TTarget & +operator<<(TTarget & target, Gaps const & gaps) +{ + typename DirectionIterator::Type it = directionIterator(target, Output()); + write(it, gaps); + return target; +} + +// ---------------------------------------------------------------------------- +// Function _pumpTraceToGaps() +// ---------------------------------------------------------------------------- + +// Internal function for converting AlignTrace<> objects into alignments in two Gaps objects. Note that the traceback +// in the trace is stored in reverse, from back to front. We insert the gaps in descending order of their position. +// The reason is that Gaps<> objects store the gaps in ascending order of coordinates in String<> objects and inserting +// at the end is in O(1) while inserting in the front is O(n). + +template +void _pumpTraceToGaps(Gaps & gapsH, + Gaps & gapsV, + AlignTraceback const & trace) +{ + typedef Gaps TGapsH; + typedef typename Iterator::Type TGapsHIter; + + typedef Gaps TGapsV; + typedef typename Iterator::Type TGapsVIter; + + // TODO(holtgrew): I don't understand the following. Originally, this function used Align objects, but I did not understand it there either. + // TODO(rausch): Pump trace into align_ (note: this is relatively slow code here. it could be improved if specialized to the Align Specs). + clearGaps(gapsH); + clearClipping(gapsH); + clearGaps(gapsV); + clearClipping(gapsV); + + TSize i = length(trace.sizes); // Scan trace backwards. + TGapsHIter itH = begin(gapsH); + TGapsVIter itV = begin(gapsV); + while (i > 0) + { + --i; + TSize size = trace.sizes[i]; + switch ((int) trace.tvs[i]) + { + case 1: // Go horizontal. + insertGaps(itV, size); + break; + + case 2: // Go vertical. + insertGaps(itH, size); + break; + } + goFurther(itH, size); + goFurther(itV, size); + } +} + +// ---------------------------------------------------------------------------- +// Function source() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Document TSource via metafunctio. + +/*! + * @fn Gaps#source + * @brief Return underlying object. + * + * @signature TSource source(gaps); + * + * @param[in] gaps The Gaps object to return the underling sequence for. + * + * @return TSource Reference to the source of the Gaps. + */ + +// ---------------------------------------------------------------------------- +// Function sourceSegment() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Rename/remove? + +// We need some forwards for function sourceSegment(). + +template +inline typename Position >::Type clippedBeginPosition(Gaps const & gaps); +template +inline typename Position >::Type clippedEndPosition(Gaps const & gaps); +template +inline typename Position::Type +toSourcePosition(Gaps const & gaps, TPosition clippedViewPos); + +template +inline typename Infix::Type +sourceSegment(Gaps const & gaps) +{ + return infix(source(gaps), toSourcePosition(gaps, clippedBeginPosition(gaps)), toSourcePosition(gaps, clippedEndPosition(gaps))); +} + +template +inline typename Infix::Type +sourceSegment(Gaps & gaps) +{ + return infix(source(gaps), toSourcePosition(gaps, clippedBeginPosition(gaps)), toSourcePosition(gaps, clippedEndPosition(gaps))); +} + +// ---------------------------------------------------------------------------- +// Function assignSource() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#assignSource + * @brief Assign the source of a gaps object, copying data. + * + * @signature void assignSource(gaps, seq); + * + * @param[in,out] gaps The Gaps object to assign the source of. + * @param[in] seq The @link ContainerConcept sequence @endlink to assign to the underlying string. + */ + +// TOOD(holtgrew): Switch to Hosted Type? + +template +inline void +assignSource(Gaps & gaps, TValue const & value) +{ + assign(source(gaps), value); +} + +// ---------------------------------------------------------------------------- +// Function setSource() +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// Function copyGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#copyGaps + * @brief Copy gaps from one Gaps object to another (in the clipped view of both arguments). + * + * The user is responsible for ensuring that the gaps are over sequences of same length and appropriate clipping. + * + * @signature void copyGaps(dest, source); + * + * @param[in,out] dest The destination Gaps object (appropriate clipping, no gaps). + * @param[in] source The source Gaps object. + */ + +template +void copyGaps(Gaps & dest, Gaps const & source) +{ + typedef Gaps TLhs; + typedef typename Iterator::Type TLhsIter; + typedef Gaps const TRhs; + typedef typename Iterator::Type TRhsIter; + + TLhsIter lhsIt = begin(dest, Standard()); + //TLhsIter lhsItEnd = end(dest, Standard()); + TRhsIter rhsIt = begin(source, Standard()); + TRhsIter rhsItEnd = end(source, Standard()); + + for (unsigned num = 0; rhsIt != rhsItEnd; lhsIt += num, rhsIt += num) + { + if (isGap(rhsIt)) + { + num = countGaps(rhsIt); + insertGaps(lhsIt, num); + } + else + { + num = countCharacters(rhsIt); + } + + SEQAN_ASSERT_NOT((lhsIt == end(dest, Standard())) && num > 0); + } +} + +// ---------------------------------------------------------------------------- +// Function copyClipping() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#copyClipping + * @brief Copy clipping information from one Gaps object to another. + * + * @signature void copyClipping(dest, source); + * + * @param[in,out] dest The destination Gaps object. + * @param[in] source The source Gaps object. + */ + +template +void copyClipping(Gaps & dest, Gaps const & source) +{ + setClippedBeginPosition(dest, clippedBeginPosition(source)); + setClippedEndPosition(dest, clippedEndPosition(source)); +} + +// ---------------------------------------------------------------------------- +// Function clipSemiGlobal() +// ---------------------------------------------------------------------------- + +/*! + * @fn Gaps#clipSemiGlobal + * @brief Clip the Gaps objects to reflect a semi-global alignment. + * + * Leading and trailing gaps are clipped in the local Gaps object. The global Gaps object is updated accordingly. + * + * @signature void clipSemiGlobal(global, local); + * + * @param[in,out] global The global Gaps object. + * @param[in,out] local The local Gaps object. + */ + +template +inline void clipSemiGlobal(TGlobalGaps & global, TLocalGaps & local) +{ + typedef typename Size::Type TGapsSize; + + TGapsSize leadingGaps = countLeadingGaps(local); + TGapsSize trailingGaps = countTrailingGaps(local); + TGapsSize globalLenght = length(global); + TGapsSize localLength = length(local); + + setClippedBeginPosition(global, leadingGaps); + setClippedBeginPosition(local, leadingGaps); + setClippedEndPosition(global, globalLenght - trailingGaps); + setClippedEndPosition(local, localLength - trailingGaps); +} + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +template +inline void clearGaps(Gaps & gaps); +template +inline void clearClipping(Gaps & gaps); + +template +inline void clear(Gaps & gaps) +{ + clearGaps(gaps); + clearClipping(gaps); +} + +// ---------------------------------------------------------------------------- +// Function operator==() +// ---------------------------------------------------------------------------- + +template +inline bool operator==(Gaps const & lhs, + Gaps const & rhs) +{ + typename Comparator >::Type lex(lhs, rhs); + return isEqual(lex); +} + +template +inline bool operator==(Gaps const & lhs, + TRightHandSide const & rhs) +{ + typename Comparator >::Type lex(lhs, rhs); + return isEqual(lex); +} + +// ---------------------------------------------------------------------------- +// Function operator!=() +// ---------------------------------------------------------------------------- + +template +inline bool operator!=(Gaps const & lhs, + Gaps const & rhs) +{ + return !(lhs == rhs); +} + + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_BASE_H_ diff --git a/seqan/align/gaps_iterator_anchor.h b/seqan/align/gaps_iterator_anchor.h new file mode 100644 index 0000000..775af98 --- /dev/null +++ b/seqan/align/gaps_iterator_anchor.h @@ -0,0 +1,781 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ITERATOR_ANCHOR_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ITERATOR_ANCHOR_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// Iterator for AnchorGaps objects. + +template //Gaps > +class Iter > > +{ +public: + typedef TGaps_ TGaps; + typedef typename Source::Type TSource; + typedef TGapAnchors_ TGapAnchors; + + // TODO(holtgrew): Why is the following commented out? +// typedef typename Value::Type TGapAnchor; + typedef typename Size::Type>::Type TGapAnchorSize_; + typedef GapAnchor::Type> TGapAnchor; + typedef typename MakeSigned::Type>::Type TGapPos; + typedef typename Iterator::Type TAnchorIter; + + TGaps * data_container; //the gaps object + TGapPos seqLength; + mutable TGapAnchor current; + mutable TGapAnchor prevAnchor; + mutable TGapAnchor nextAnchor; + mutable TGapAnchor viewBegin; + mutable TGapAnchor viewEnd; + mutable int anchorIdx; + +public: + Iter() + { + data_container = NULL; + seqLength = 0; + } +/* Iter(Iter const & other_): + data_container(other_.data_container), + seqLength(other_.seqLength), + current(other_.current), + prevAnchor(other_.prevAnchor), + nextAnchor(other_.nextAnchor), + anchorIdx(other_.anchorIdx) + { + } +*/ Iter(TGaps & container_): + data_container(&container_) + { + _assignSourceLength(seqLength, container_); + _goToGapAnchorIterator(*this, data_container->data_viewCutBegin + data_container->data_cutBegin); + viewBegin = current; + viewEnd.gapPos = _unclippedLength(*data_container) + data_container->data_cutBegin - data_container->data_viewCutEnd; + viewEnd.seqPos = positionGapToSeq(*data_container, viewEnd.gapPos); + } + Iter(TGaps & container_, TGapPos clippedViewPosition): + data_container(&container_) + { + _assignSourceLength(seqLength, container_); + _goToGapAnchorIterator(*this, clippedViewPosition + data_container->data_viewCutBegin + data_container->data_cutBegin); + viewBegin.gapPos = data_container->data_viewCutBegin + data_container->data_cutBegin; + viewEnd.gapPos = _unclippedLength(*data_container) + data_container->data_cutBegin - data_container->data_viewCutEnd; + viewBegin.seqPos = positionGapToSeq(*data_container, viewBegin.gapPos); + viewEnd.seqPos = positionGapToSeq(*data_container, viewEnd.gapPos); + } + ~Iter() + { + } + + Iter const & operator = (Iter const & other_) + { + data_container = other_.data_container; + seqLength = other_.seqLength; + current = other_.current; + prevAnchor = other_.prevAnchor; + nextAnchor = other_.nextAnchor; + anchorIdx = other_.anchorIdx; + viewBegin = other_.viewBegin; + viewEnd = other_.viewEnd; + return *this; + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function container() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Can go if data_container were _container, dupe in _base.h + +template +inline TGaps & +container(Iter > > & me) +{ + return *me.data_container; +} + +template +inline TGaps & +container(Iter > > const & me) +{ + return *me.data_container; +} + +// ---------------------------------------------------------------------------- +// Function source() +// ---------------------------------------------------------------------------- + +template +inline typename Source > > const>::Type +source(Iter > > & me) +{ + return begin(source(*me.data_container), Rooted()) + me.current.seqPos; +} + +template +inline typename Source > > >::Type +source(Iter > > const & me) +{ + return begin(source(*me.data_container), Rooted()) + me.current.seqPos; +} + +// ---------------------------------------------------------------------------- +// Function getValue() +// ---------------------------------------------------------------------------- + +template +inline typename GetValue< Iter > > >::Type +getValue(Iter > > & me) +{ + typedef typename Value > >::Type TValue; + if (isGap(me)) return gapValue(); + else if (isUnknown(me)) return unknownValue(); + else return getValue(source(me)); +} + +template +inline typename GetValue< Iter > > const>::Type +getValue(Iter > > const & me) +{ + typedef typename Value > const>::Type TValue; + if (isGap(me)) return gapValue(); + else if (isUnknown(me)) return unknownValue(); + else return getValue(source(me)); +} + +// ---------------------------------------------------------------------------- +// Function value() +// ---------------------------------------------------------------------------- + +template +inline typename Reference< Iter > > >::Type +value(Iter > > & it) +{ + typedef typename Reference > > >::Type TProxy; + return TProxy(it); +} + +template +inline typename Reference< Iter > > const>::Type +value(Iter > > const & it) +{ + typedef typename Reference > > const>::Type TProxy; + return TProxy(it); +} + +// ---------------------------------------------------------------------------- +// Function isGap() +// ---------------------------------------------------------------------------- + +template +inline bool +isGap(Iter > > const & me) +{ + return me.current.seqPos == me.nextAnchor.seqPos; +} + +// ---------------------------------------------------------------------------- +// Function isUnknown() +// ---------------------------------------------------------------------------- + +template +inline bool +isUnknown(Iter > > const & me) +{ + int len; + _assignSourceLength(len, *me.data_container); + return me.current.seqPos < 0 || me.current.seqPos >= len; +} + +// ---------------------------------------------------------------------------- +// Function isClipped() +// ---------------------------------------------------------------------------- + +template +inline bool +isClipped(Iter > > const & me) +{ + return me.current.gapPos == me.nextAnchor.gapPos; +} + +// ---------------------------------------------------------------------------- +// Function countGaps() +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +countGaps(Iter > > const & me, LeftOfViewPos const & /*dir*/) +{ + typedef Iter > > TIter; + typedef typename TIter::TGapAnchor TGapAnchor; + + if (isGap(me)) + { + if (me.prevAnchor.gapPos < me.viewBegin.gapPos) + return me.current.gapPos - me.viewBegin.gapPos; + return me.current.gapPos - me.prevAnchor.gapPos - (me.current.seqPos - me.prevAnchor.seqPos); + } + // In case we are at the beginning of a new anchor we need to get back the previous one. + if (me.prevAnchor.gapPos == me.current.gapPos) + { + TGapAnchor tmp; + _getAnchor(tmp, *me.data_container, me.anchorIdx - 1); + if (tmp.gapPos < me.viewBegin.gapPos) + tmp.gapPos = me.viewBegin.gapPos; + return me.current.gapPos - tmp.gapPos - (me.current.seqPos - tmp.seqPos); + } + return 0; +} + +template +inline typename Size::Type +countGaps(Iter > > const & me, RightOfViewPos const & /*dir*/) +{ + if (!isGap(me)) + return 0; + if (me.nextAnchor.gapPos > me.viewEnd.gapPos) + return me.viewEnd.gapPos - me.current.gapPos; + return me.nextAnchor.gapPos - me.current.gapPos; +} + +// ---------------------------------------------------------------------------- +// Function countCharacters() +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +countCharacters(Iter > > const & me, LeftOfViewPos const & /*dir*/) +{ + if (!isGap(me)) + return me.current.seqPos - me.prevAnchor.seqPos; + // In case we are at the beginning of a new anchor we need to get back the previous one. + if (me.current.seqPos - me.prevAnchor.seqPos == me.current.gapPos - me.prevAnchor.gapPos) + return me.current.seqPos - me.prevAnchor.seqPos; + return 0; +} + +template +inline typename Size::Type +countCharacters(Iter > > const & me, RightOfViewPos const & /*dir*/) +{ + if (isGap(me)) + return 0; + if (me.nextAnchor.seqPos > me.viewEnd.seqPos) + return me.viewEnd.seqPos - me.current.seqPos; + return me.nextAnchor.seqPos - me.current.seqPos; +} + +// ---------------------------------------------------------------------------- +// Function blockLength() +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +blockLength(Iter > > & me) +{ + if (isGap(me)) + return countGaps(me); + else + return countCharacters(me); +} + +// ---------------------------------------------------------------------------- +// Function atBegin() +// ---------------------------------------------------------------------------- + +template +inline bool +atBegin(Iter > > & me) +{ +// return me.current.seqPos == 0 && me.current.gapPos == 0; + return me.current <= me.viewBegin; +} + +template +inline bool +atBegin(Iter > > const & me) +{ +// return me.current.seqPos == 0 && me.current.gapPos == 0; + return me.current <= me.viewBegin; +} + +// ---------------------------------------------------------------------------- +// Function atEnd() +// ---------------------------------------------------------------------------- + +template +inline bool +atEnd(Iter > > & me) +{ +// return me.current == me.nextAnchor; + return me.current >= me.viewEnd; +} + +template +inline bool +atEnd(Iter > > const & me) +{ +// return me.current == me.nextAnchor; + return me.current >= me.viewEnd; +} + +// ---------------------------------------------------------------------------- +// Function operator==() +// ---------------------------------------------------------------------------- + +template +inline bool +operator == ( + Iter > > const & left, + Iter > > const & right) +{ + return left.current == right.current; +} + +// ---------------------------------------------------------------------------- +// Function operator!=() +// ---------------------------------------------------------------------------- + +template +inline bool +operator != ( + Iter > > const & left, + Iter > > const & right) +{ + return left.current != right.current; +} + +// ---------------------------------------------------------------------------- +// Function operator<() +// ---------------------------------------------------------------------------- + +template +inline bool +operator < ( + Iter > > const & left, + Iter > > const & right) +{ + return left.current < right.current; +} + +// ---------------------------------------------------------------------------- +// Function operator<=() +// ---------------------------------------------------------------------------- + +template +inline bool +operator<=( + Iter > > const & left, + Iter > > const & right) +{ + return !(left.current > right.current); +} + +// ---------------------------------------------------------------------------- +// Function operator>() +// ---------------------------------------------------------------------------- + +template +inline bool +operator > ( + Iter > > const & left, + Iter > > const & right) +{ + return left.current > right.current; +} + +// ---------------------------------------------------------------------------- +// Function operator>=() +// ---------------------------------------------------------------------------- + +template +inline bool +operator>=(Iter > > const & lhs, + Iter > > const & rhs) +{ + return !(lhs < rhs); +} + +// ---------------------------------------------------------------------------- +// Function insertGaps() +// ---------------------------------------------------------------------------- + +template +inline void +insertGaps(Iter > > const & me, + TCount size) +{ + TGapAnchors & anchors = _dataAnchors(*me.data_container); + typedef typename Iterator::Type TIter; + + if (size <= 0) return; + + // insert a new anchor + if (!isGap(me)) + { + if (me.prevAnchor.gapPos == me.current.gapPos) + { + me.nextAnchor = me.prevAnchor; + _getAnchor(me.prevAnchor, *me.data_container, --me.anchorIdx); + } + else + { + me.nextAnchor = me.current; + insertValue(anchors, me.anchorIdx, me.nextAnchor, Generous()); + } + } + else + { + if (me.anchorIdx >= (int)length(anchors)) + { + // add gap after the sequence and in (or at the right boundary of) the view + if (me.current.gapPos <= me.viewEnd.gapPos) + { + container(me).data_cutEnd -= size; + me.viewEnd.gapPos += size; + } + return; + } + if (empty(anchors)) + appendValue(anchors, me.nextAnchor, Generous()); + } + if (me.anchorIdx < (int)length(anchors)) + { + if (me.anchorIdx >= 0) + { + me.nextAnchor.gapPos += size; + TIter it = begin(anchors, Standard()); + TIter itEnd = end(anchors, Standard()); + if (me.anchorIdx >= 0) + it += me.anchorIdx; + for (; it != itEnd; ++it) + (*it).gapPos += size; + } + else + // add gap before the sequence and in (or at the left boundary of) the view + if (me.current.gapPos >= me.viewBegin.gapPos) + { + container(me).data_cutBegin -= size; + me.viewBegin.gapPos -= size; + me.current.gapPos -= size; + return; + } + } + if (me.current.gapPos <= me.viewEnd.gapPos) + me.viewEnd.gapPos += size; + +/* + Iter > > it2 = begin(*me.data_container) + me.current.gapPos; + if (me.current != it2.current || me.prevAnchor != it2.prevAnchor || me.nextAnchor != it2.nextAnchor || me.anchorIdx != it2.anchorIdx) + std::cout<<"*"; +*/ +} + +// ---------------------------------------------------------------------------- +// Function removeGaps() +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +removeGaps(Iter > > const & it, + TCount size_) +{ + TGapAnchors & anchors = _dataAnchors(*it.data_container); + typedef typename Iterator::Type TAnchorsIter; + + typedef Iter > > TIter; + typedef typename TIter::TGapAnchor TGapAnchor; + // typedef typename Value::Type TGapAnchor; + typedef typename Position::Type TPos; + + if (size_ <= 0 || !isGap(it)) + return 0; + TPos size = size_; + + // static_cast(Nothing()); + // static_cast(Nothing()); + if (it.current.gapPos + size > it.nextAnchor.gapPos) + size = it.nextAnchor.gapPos - it.current.gapPos; + + if (it.prevAnchor.gapPos + it.current.seqPos == it.current.gapPos + it.prevAnchor.seqPos && + it.current.gapPos + size == it.nextAnchor.gapPos) + { + // remove the gap + if (it.anchorIdx < (int)length(anchors)) + erase(anchors, it.anchorIdx); + _getAnchor(it.nextAnchor, *it.data_container, it.anchorIdx); + } + + // shift anchors + if (it.anchorIdx < (int)length(anchors)) + { + if (it.anchorIdx >= 0) + { + it.nextAnchor.gapPos -= size; + TAnchorsIter itA = begin(anchors, Standard()); + TAnchorsIter itAEnd = end(anchors, Standard()); + if (it.anchorIdx >= 0) + itA += it.anchorIdx; + for (; itA != itAEnd; ++itA) + (*itA).gapPos -= size; + } + else + // remove gap before the sequence and in (or at the left boundary of) the view + if (it.current.gapPos >= it.viewBegin.gapPos) + { + // assure that we don't remove more gaps than available + if (size > it.nextAnchor.gapPos - it.current.gapPos) + size = it.nextAnchor.gapPos - it.current.gapPos; + container(it).data_cutBegin += size; + it.viewBegin.gapPos += size; + it.current.gapPos += size; + return size; + } + } + else + { + if (it.current.gapPos <= it.viewEnd.gapPos) + container(it).data_cutEnd += size; + } + if (it.current.gapPos <= it.viewEnd.gapPos) + it.viewEnd.gapPos -= size; + + return size; +/* + Iter > > it2 = begin(*me.data_container) + me.current.gapPos; + if (me.current != it2.current || me.prevAnchor != it2.prevAnchor || me.nextAnchor != it2.nextAnchor || me.anchorIdx != it2.anchorIdx) + std::cout<<"*"; +*/ +} + +// ---------------------------------------------------------------------------- +// Helper Function _goNextGapAnchorIterator() +// ---------------------------------------------------------------------------- + +template +inline void +_goNextGapAnchorIterator(T & me) +{ + if (me.current.gapPos < me.nextAnchor.gapPos) + { + ++me.current.gapPos; + if (me.current.seqPos < me.nextAnchor.seqPos) + ++me.current.seqPos; + } + while (me.current.gapPos == me.nextAnchor.gapPos) + { + me.current = me.prevAnchor = me.nextAnchor; + _getAnchor(me.nextAnchor, *me.data_container, ++me.anchorIdx + 1); + } +} + +// ---------------------------------------------------------------------------- +// Helper Function _goPreviousGapAnchorIterator() +// ---------------------------------------------------------------------------- + +template +inline void +_goPreviousGapAnchorIterator(T & me) +{ + while (me.current.gapPos == me.prevAnchor.gapPos) + { + me.current = me.nextAnchor = me.prevAnchor; + _getAnchor(me.prevAnchor, *me.data_container, --me.anchorIdx); + } + --me.current.gapPos; + if (me.nextAnchor.seqPos - me.prevAnchor.seqPos > me.current.gapPos - me.prevAnchor.gapPos) + me.current.seqPos = me.prevAnchor.seqPos + (me.current.gapPos - me.prevAnchor.gapPos); + else + me.current.seqPos = me.nextAnchor.seqPos; +} + +// ---------------------------------------------------------------------------- +// Helper Function _goToGapAnchorIterator() +// ---------------------------------------------------------------------------- + +template +inline void +_goToGapAnchorIterator(T & me, TPos pos) +{ + typedef typename T::TGapAnchors TGapAnchors; + typedef typename Value::Type TGapAnchor; + typedef typename Position::Type TAnchorPos; + typedef typename MakeSigned::Type TAnchorSPos; + + if (isNegative(pos)) + me.anchorIdx = -1; + else + { + TGapAnchors const & anchors = _dataAnchors(*me.data_container); + if (!empty(anchors)) + { + me.anchorIdx = upperBoundGapAnchor(anchors, pos, SortGapPos()) - begin(anchors, Standard()); + if (me.anchorIdx < (int)length(anchors)) + if (anchors[me.anchorIdx].gapPos == (TAnchorPos)pos && anchors[me.anchorIdx].seqPos != (TAnchorPos)me.seqLength) + ++me.anchorIdx; + } + else + { + me.anchorIdx = ((TAnchorSPos)pos < me.seqLength)? 0: 1; + } + } + _getAnchor(me.prevAnchor, *me.data_container, me.anchorIdx); + _getAnchor(me.nextAnchor, *me.data_container, me.anchorIdx + 1); + + me.current.gapPos = pos; + if (me.nextAnchor.seqPos - me.prevAnchor.seqPos > (int)pos - me.prevAnchor.gapPos) + me.current.seqPos = me.prevAnchor.seqPos + ((int)pos - me.prevAnchor.gapPos); + else + me.current.seqPos = me.nextAnchor.seqPos; +} + +// ---------------------------------------------------------------------------- +// Function goNext() +// ---------------------------------------------------------------------------- + +template +inline void +goNext(Iter > > & me) +{ + _goNextGapAnchorIterator(me); +} + +// ---------------------------------------------------------------------------- +// Function goPrevious() +// ---------------------------------------------------------------------------- + +template +inline void +goPrevious(Iter > > & me) +{ + _goPreviousGapAnchorIterator(me); +} + +// ---------------------------------------------------------------------------- +// Function goFurther() +// ---------------------------------------------------------------------------- + +template +inline void +goFurther(Iter > > & me, TSize steps) +{ + _goToGapAnchorIterator(me, me.current.gapPos + steps); +} + +// ---------------------------------------------------------------------------- +// Function position() +// ---------------------------------------------------------------------------- + +// Returns clipped view position of gaps iterator. + +template +inline typename Position > > >::Type +position(Iter > > const & it) +{ + return it.current.gapPos - it.viewBegin.gapPos; +} + +// ---------------------------------------------------------------------------- +// Function difference() +// ---------------------------------------------------------------------------- + +template +inline typename Difference > > >::Type +difference(Iter > > const & lhs, + Iter > > const & rhs) +{ + return lhs.current.gapPos - rhs.current.gapPos; +} + +// ---------------------------------------------------------------------------- +// Function operator-() [difference] +// ---------------------------------------------------------------------------- + +template +inline typename Difference > > >::Type +operator-(Iter > > const & lhs, + Iter > > const & rhs) +{ + return difference(lhs, rhs); +} + +// ---------------------------------------------------------------------------- +// Function operator-() [copy movement] +// ---------------------------------------------------------------------------- + +template +inline Iter > > +operator-(Iter > > const & lhs, TDifference d) +{ + Iter > > result = lhs; + result -= d; + return result; +} + +// ---------------------------------------------------------------------------- +// Function operator+() [copy movement] +// ---------------------------------------------------------------------------- + +template +inline Iter > > +operator+(Iter > > const & lhs, TDifference d) +{ + Iter > > result = lhs; + result += d; + return result; +} + + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ITERATOR_ANCHOR_H_ diff --git a/seqan/align/gaps_iterator_array.h b/seqan/align/gaps_iterator_array.h new file mode 100644 index 0000000..b32de15 --- /dev/null +++ b/seqan/align/gaps_iterator_array.h @@ -0,0 +1,783 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ITERATOR_ARRAY_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ITERATOR_ARRAY_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +template +class Iter > +{ +public: + // ----------------------------------------------------------------------- + // Internal Typedefs + // ----------------------------------------------------------------------- + + typedef typename TGaps::TArrayPos_ TArrayPos_; + typedef typename TGaps::TArray_ TArray_; + typedef typename Value::Type TArrayValue_; + typedef typename Position::Type TGapsPos_; + typedef typename Source::Type TSource_; + typedef typename Position::Type TSourcePos_; + + // ----------------------------------------------------------------------- + // Member Variables + // ----------------------------------------------------------------------- + + // The following index and position members must be mutable since the + // insertion and deletion of gaps does not modify the iterator conceptually. + + // Pointer to the iterated container / gaps object. + TGaps * _container; + // Index in the bucket array of the gaps object. + mutable TArrayPos_ _bucketIndex; + // Offset within the current bucket. + mutable TArrayValue_ _bucketOffset; + // Source position of the iterator. + mutable TSourcePos_ _sourcePosition; + // View position of the iterator. + mutable TGapsPos_ _unclippedViewPosition; + + // ----------------------------------------------------------------------- + // Constructors + // ----------------------------------------------------------------------- + + // Default constructor. + Iter() : _container(0), _bucketIndex(0), _bucketOffset(0), _sourcePosition(0), _unclippedViewPosition(0) + {} + + // Copy constructor, required since we specify the one with complemented const below. + Iter(Iter const & other) : + _container(other._container), _bucketIndex(other._bucketIndex), _bucketOffset(other._bucketOffset), + _sourcePosition(other._sourcePosition), _unclippedViewPosition(other._unclippedViewPosition) + {} + + // Copy construtor for iterator -> const iterator conversion. + // TODO(holtgrew): Think of something smarter, to restrict source types? + template + Iter(TOtherIter const & other) : + _container(other._container), _bucketIndex(other._bucketIndex), _bucketOffset(other._bucketOffset), + _sourcePosition(other._sourcePosition), _unclippedViewPosition(other._unclippedViewPosition) + {} + + // Create at begin of gaps. + Iter(TGaps & container_, Begin_ const &) : + _container(&container_), _bucketIndex(0), _bucketOffset(0), _sourcePosition(0), + _unclippedViewPosition(0) + { + if (_container->_array[0] == 0u) + _bucketIndex = 1; + // Go to beginning of clipping. + goFurther(*this, container_._clippingBeginPos); + } + + // Create at end of gaps. + Iter(TGaps & container_, End_ const &) : + _container(&container_), _bucketIndex(0), _bucketOffset(0), _sourcePosition(0), + _unclippedViewPosition(0) + { + if (_container->_array[0] == 0u) + _bucketIndex = 1; + // Go to end of clipping position. + goFurther(*this, container_._clippingEndPos); + } + + // Create with position. + // TODO(holtgrew): Chain constructor call to Begin_() here in C++11. + template + Iter(TGaps & container_, TPos pos, Position_ const &) : + _container(&container_), _bucketIndex(0), _bucketOffset(0), _sourcePosition(0), + _unclippedViewPosition(0) + { + if (_container->_array[0] == 0u) + _bucketIndex = 1; + // pos is an unclipped view position, make it clipped. + pos += container_._clippingBeginPos; + // Initialized for begin position. Now, advance. + goFurther(*this, pos); + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function isGap() +// ---------------------------------------------------------------------------- + +template +inline bool +isGap(Iter > const & it) +{ + return !(it._bucketIndex % 2); +} + +// ---------------------------------------------------------------------------- +// Function value() +// ---------------------------------------------------------------------------- + +template +inline typename Reference > >::Type +value(Iter > & it) +{ + typedef typename Reference > >::Type TProxy; + return TProxy(it); +} + +template +inline typename Reference > const>::Type +value(Iter > const & it) +{ + typedef typename Reference > const>::Type TProxy; + return TProxy(it); +} + +// ---------------------------------------------------------------------------- +// Function getValue() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Ideally, we would only have one here. + +template +inline typename GetValue > >::Type +getValue(Iter > & it) +{ + typedef typename Value::Type TAlphabet; + if (isGap(it)) + return gapValue(); + else + return value(source(container(it)), it._sourcePosition); +} + +template +inline typename GetValue > const>::Type +getValue(Iter > const & it) +{ + typedef typename Value::Type TAlphabet; + if (isGap(it)) + return gapValue(); + else + return value(source(container(it)), it._sourcePosition); +} + +// ---------------------------------------------------------------------------- +// Function position() +// ---------------------------------------------------------------------------- + +// Returns clipped view position of gaps iterator. + +template +inline typename Position > >::Type +position(Iter > const & it) +{ + if (it._container == 0) + return 0; + + typedef Iter > TIter; + typedef typename Position::Type TPosition; + typedef typename TIter::TArrayPos_ TArrayPos; + + TPosition unclippedViewPosition = 0; + for (TArrayPos i = 0; i < it._bucketIndex; ++i) + unclippedViewPosition += it._container->_array[i]; + unclippedViewPosition += it._bucketOffset; + + // TODO(holtgrew): Simply return it._unclippedViewPosition? + SEQAN_ASSERT_EQ(it._unclippedViewPosition, unclippedViewPosition); + + return unclippedViewPosition - clippedBeginPosition(*it._container); +} + +// ---------------------------------------------------------------------------- +// Function countGaps() +// ---------------------------------------------------------------------------- + +// Count left. +template +inline typename Size::Type +countGaps(Iter > const & it, LeftOfViewPos const & /*tag*/) +{ + typedef typename Size::Type TSize; + TSize result = 0; + + // Get number of gaps left of current position ignoring any clipping. + if (isGap(it) && it._bucketOffset) + result = it._bucketOffset; + else if (!isGap(it) && !it._bucketOffset && it._bucketIndex) + result = it._container->_array[it._bucketIndex - 1]; + + // Limit to the clipping begin position. + if (it._unclippedViewPosition - result < (TSize)it._container->_clippingBeginPos) + result = it._unclippedViewPosition - it._container->_clippingBeginPos; + + return result; +} + +// Count right. +template +inline typename Size::Type +countGaps(Iter > const & it, RightOfViewPos const & /*tag*/) +{ + if (!isGap(it) || atEnd(it)) + return 0; // Not on a gap or at end, no gap here. + + typedef typename Size::Type TSize; + TSize result = it._container->_array[it._bucketIndex] - it._bucketOffset; + // Check whether gaps reach behind the clipping and trim gaps for counting. + if ((TSize)(it._unclippedViewPosition + result) > (TSize)it._container->_clippingEndPos) + result = it._container->_clippingEndPos - it._unclippedViewPosition; + return result; +} + +// ---------------------------------------------------------------------------- +// Function countCharacters() +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +countCharacters(Iter > const & it, LeftOfViewPos const & /*dir*/) +{ + typedef typename Size::Type TSize; + TSize result = 0; + + // Get number of characters left of current position ignoring any clipping. + if (!isGap(it) && it._bucketOffset) + result = it._bucketOffset; + else if (isGap(it) && !it._bucketOffset && it._bucketIndex) + result = it._container->_array[it._bucketIndex - 1]; + + // Limit to the clipping begin position. + if (it._unclippedViewPosition - result < (TSize)it._container->_clippingBeginPos) + result = it._unclippedViewPosition - it._container->_clippingBeginPos; + + return result; +} + +template +inline typename Size::Type +countCharacters(Iter > const & it, RightOfViewPos const & /*dir*/) +{ + if (isGap(it) || atEnd(it)) + return 0; // On a gap or at end, no characters here. + + typedef typename Size::Type TSize; + TSize result = it._container->_array[it._bucketIndex] - it._bucketOffset; + // Check whether gaps reach behind the clipping and trim gaps for counting. + if ((TSize)(it._unclippedViewPosition + result) > (TSize)it._container->_clippingEndPos) + result = it._container->_clippingEndPos - it._unclippedViewPosition; + return result; +} + +// ---------------------------------------------------------------------------- +// Function goPrevious() +// ---------------------------------------------------------------------------- + +template +inline bool +goPrevious(Iter > & it) +{ + typedef typename Position::Type TGapsPos; + + if (atBegin(it)) // Handle case of being at the beginning of the gaps. + return false; + + if (it._bucketOffset > TGapsPos(0)) + { + // Not at the beginning of a bucket. + it._bucketOffset -= 1; + } + else + { + // At the beginning of a bucket. + it._bucketIndex -= 1; + SEQAN_ASSERT_GT(it._container->_array[it._bucketIndex], 0u); + it._bucketOffset = it._container->_array[it._bucketIndex] - 1; + } + + // Adjust source position. + if (!isGap(it)) + it._sourcePosition -= 1; + // Adjust clipped view position. + it._unclippedViewPosition -= 1; + + return true; +} + +// ---------------------------------------------------------------------------- +// Function goNext() +// ---------------------------------------------------------------------------- + +template +inline bool +goNext(Iter > & it) +{ + if (atEnd(it)) // Handle case of being at the end of the gaps. + return false; + + // Adjust source position. + if (!isGap(it)) + it._sourcePosition += 1; + // Adjust clipped view position. + it._unclippedViewPosition += 1; + + if (it._bucketOffset + 1 != it._container->_array[it._bucketIndex]) + { + // Not on last entry of a bucket. + it._bucketOffset += 1; + } + else + { + // On last entry of a bucket. If we are not in the last bucket then go + // to next bucket. Otherwise, go over the bucket, marks iterator-at-end. + if (it._bucketIndex + 1 != length(it._container->_array)) + { + // Go to next. + it._bucketIndex += 1; + if (it._bucketIndex > length(it._container->_array)) + SEQAN_ASSERT_GT(it._container->_array[it._bucketIndex], 0u); + it._bucketOffset = 0; + } + else + { + // Go to end of bucket. + it._bucketOffset += 1; + SEQAN_ASSERT_EQ(it._bucketIndex + 1, length(it._container->_array)); + SEQAN_ASSERT_EQ(it._bucketOffset, back(it._container->_array)); + } + } + + return true; +} + + +// ---------------------------------------------------------------------------- +// Function goNext() +// ---------------------------------------------------------------------------- + +template +inline void +goFurther(Iter > & it, + TDifference delta) +{ + // TODO(holtgrew): Handle going backwards more efficiently. + if (delta == TDifference(0)) + return; + if (isNegative(delta)) + { + typedef typename MakeSigned::Type TSignedDifference; + for (; -static_cast(delta); ++delta) + goPrevious(it); + return; + } + + // Do nothing if we want are already at the end. + if (atEnd(it)) + return; + + // Case: Going forward. + + // Get shortcut to new unclipped view position that we want to go to and + // limit this to the clipping end pos of the gaps object. + unsigned posEnd = it._unclippedViewPosition + delta; + if (posEnd > static_cast(it._container->_clippingEndPos)) + posEnd = it._container->_clippingEndPos; + + // The variable counter is the number of view positions to go forward. + for (unsigned counter = posEnd - it._unclippedViewPosition; counter > 0u;) + { + // Number of elements in bucket and number of remaining (behind offset in bucket). + unsigned count = it._container->_array[it._bucketIndex]; + unsigned shift = count - it._bucketOffset; + + if (shift < counter) + { + it._unclippedViewPosition += shift; + if (it._bucketIndex % 2) + it._sourcePosition += shift; + it._bucketOffset = 0; + it._bucketIndex += 1; + counter -= shift; + } + else if (shift == counter) + { + it._unclippedViewPosition += shift; + if (it._bucketIndex % 2) + it._sourcePosition += shift; + + // On last entry of a bucket. If we are not in the last bucket then go to next bucket. + // Otherwise, go over the bucket, marks iterator-at-end. + if (it._bucketIndex + 1 != length(it._container->_array)) + { + // Go to next. + it._bucketIndex += 1; + if (it._bucketIndex > length(it._container->_array)) + SEQAN_ASSERT_GT(it._container->_array[it._bucketIndex], 0u); + it._bucketOffset = 0; + } + else + { + // Go to end of bucket. + it._bucketOffset += shift; + SEQAN_ASSERT_EQ(it._bucketIndex + 1, length(it._container->_array)); + SEQAN_ASSERT_EQ(it._bucketOffset, back(it._container->_array)); + } + counter = 0; + } + else // shift > counter + { + it._unclippedViewPosition += counter; + if (it._bucketIndex % 2) + it._sourcePosition += counter; + it._bucketOffset += counter; + counter = 0; + } + } +} + +// ---------------------------------------------------------------------------- +// Function atBegin() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Non-const version is superfluous :( +template +inline bool +atBegin(Iter > const & it) +{ + return it._unclippedViewPosition == it._container->_clippingBeginPos; +} + +template +inline bool +atBegin(Iter > & it) +{ + return it._unclippedViewPosition == it._container->_clippingBeginPos; +} + +// ---------------------------------------------------------------------------- +// Function atEnd() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Non-const version is superfluous :( +template +inline bool +atEnd(Iter > const & it) +{ + return it._unclippedViewPosition == it._container->_clippingEndPos; +} + +template +inline bool +atEnd(Iter > & it) +{ + return it._unclippedViewPosition == it._container->_clippingEndPos; +} + +// ---------------------------------------------------------------------------- +// Function insertGaps() +// ---------------------------------------------------------------------------- + +template +inline void +insertGaps(Iter > const & it, + TCount count) +{ + if (count == TCount(0)) + return; // Do nothing! + + typedef typename TGaps::TArray_ TArray; + typedef typename Position::Type TArrayPos; + + // Get shortcut to gaps. + TGaps & gaps = *it._container; + TArrayPos idx = it._bucketIndex; + + // Handle case of being at the start of a character bucket. + if (idx % 2 && it._bucketOffset == 0) + { + idx -= 1; + it._bucketIndex -= 1; + it._bucketOffset = gaps._array[idx]; + } + + // Insert gaps, simple and fast if we are in a gaps bucket, a bit harder + // otherwise. + if (idx % 2) // character bucket + { + if (gaps._array[idx] > it._bucketOffset) // In the middle of the bucket. + { + TArray arr; + resize(arr, 2, 0); + arr[0] = count; + arr[1] = gaps._array[idx] - it._bucketOffset; + gaps._array[idx] = it._bucketOffset; + insert(gaps._array, idx + 1, arr); + + // Update iterator. + it._bucketIndex += 1; + it._bucketOffset = 0; + } + else // At the end of the bucket. + { + if (idx + 1 < length(gaps._array)) // Not at end of array. + { + gaps._array[idx + 1] += count; + } + else // At end of array. + { + resize(gaps._array, length(gaps._array) + 2, 0); + gaps._array[idx + 1] = count; + gaps._array[idx + 2] = 0; + } + } + } + else // gap bucket + { + gaps._array[idx] += count; + } + + // Adjust clipping information. + gaps._clippingEndPos += count; +} + +// ---------------------------------------------------------------------------- +// Function removeGaps() +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +removeGaps(Iter > const & it, TCount count) +{ + typedef typename TGaps::TArray_ TArray; + typedef typename Position::Type TArrayPos; + typedef typename Value::Type TArrayValue; + typedef typename Source::Type TSource; + typedef typename Position::Type TSeqPos; + + if (count == TCount(0)) + return 0; // Do nothing! + + // Get shortcuts. + TGaps & gaps = *it._container; + TArrayPos idx = it._bucketIndex; + TSeqPos offset = it._bucketOffset; + + // If we are inside a non-gap bucket then we cannot remove any gaps. + if (idx % 2) + return 0; + + // Otherwise, we can remove gaps right of the current position but not + // more than there are. + TSeqPos toRemove = count; + if (toRemove > gaps._array[idx] - offset) + toRemove = gaps._array[idx] - offset; + gaps._array[idx] -= toRemove; + // TODO(holtgrew): We have to decrement idx and adjust offset in case of merging! + // In some cases, we remove the whole gap and merge the character buckets. + if (gaps._array[idx] == TArrayValue(0)) + { + // No merging for leading and trailing gap. + if (idx == TArrayPos(0) || idx == TArrayPos(length(gaps._array) - 1)) + { + gaps._array[idx - 1] += gaps._array[idx + 1]; + erase(gaps._array, idx, idx + 2); + } + } + + // Also update the right clipping position. + gaps._clippingEndPos -= toRemove; + + // Finally, return number of removed gaps. + return toRemove; +} + +// ---------------------------------------------------------------------------- +// Function operator<() +// ---------------------------------------------------------------------------- + +template +inline bool +operator<(Iter > const & lhs, + Iter > const & rhs) +{ + return lhs._bucketIndex < rhs._bucketIndex || + (lhs._bucketIndex == rhs._bucketIndex && lhs._bucketOffset < rhs._bucketOffset); +} + +// ---------------------------------------------------------------------------- +// Function operator>() +// ---------------------------------------------------------------------------- + +template +inline bool +operator>(Iter > const & lhs, + Iter > const & rhs) +{ + return lhs._bucketIndex > rhs._bucketIndex || + (lhs._bucketIndex == rhs._bucketIndex && lhs._bucketOffset > rhs._bucketOffset); +} + +// ---------------------------------------------------------------------------- +// Function operator<=() +// ---------------------------------------------------------------------------- + +template +inline bool +operator<=(Iter > const & lhs, + Iter > const & rhs) +{ + return !(lhs > rhs); +} + +// ---------------------------------------------------------------------------- +// Function operator>=() +// ---------------------------------------------------------------------------- + +template +inline bool +operator>=(Iter > const & lhs, + Iter > const & rhs) +{ + return !(lhs < rhs); +} + +// ---------------------------------------------------------------------------- +// Function operator==() +// ---------------------------------------------------------------------------- + +template +inline bool +operator==(Iter > const & _lhs, + Iter > const & _rhs) +{ + return _lhs._container == _rhs._container && + _lhs._bucketIndex == _rhs._bucketIndex && + _lhs._bucketOffset == _rhs._bucketOffset; +} + +// ---------------------------------------------------------------------------- +// Function operator!=() +// ---------------------------------------------------------------------------- + +template +inline bool +operator!=(Iter > const & _lhs, + Iter > const & _rhs) +{ + return _lhs._container != _rhs._container || + _lhs._bucketIndex != _rhs._bucketIndex || + _lhs._bucketOffset != _rhs._bucketOffset; +} + +// ---------------------------------------------------------------------------- +// Function difference() +// ---------------------------------------------------------------------------- + +template +inline typename Difference > >::Type +difference(Iter > const & lhs, + Iter > const & rhs) +{ + // TODO(holtgrew): Implementation could be more efficient. + // We only need to solve the case lhs < rhs. + if (lhs > rhs) + return -difference(rhs, lhs); + if (lhs == rhs) + return 0; + SEQAN_ASSERT(lhs < rhs); // Makes code below simpler. + + typedef Iter > TIter; + typedef typename Difference::Type TDifference; + TDifference d = 0; + for (TIter it = lhs; it != rhs; ++it) + ++d; + + return -d; +} + +// ---------------------------------------------------------------------------- +// Function operator-() [difference] +// ---------------------------------------------------------------------------- + +template +inline typename Difference > >::Type +operator-(Iter > const & lhs, + Iter > const & rhs) +{ + return difference(lhs, rhs); +} + +// ---------------------------------------------------------------------------- +// Function operator-() [copy movement] +// ---------------------------------------------------------------------------- + +template +inline Iter > +operator-(Iter > const & lhs, TDifference d) +{ + Iter > result = lhs; + result -= d; + return result; +} + +// ---------------------------------------------------------------------------- +// Function operator+() [copy movement] +// ---------------------------------------------------------------------------- + +template +inline Iter > +operator+(Iter > const & lhs, TDifference d) +{ + Iter > result = lhs; + result += d; + return result; +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ITERATOR_ARRAY_H_ diff --git a/seqan/align/gaps_iterator_base.h b/seqan/align/gaps_iterator_base.h new file mode 100644 index 0000000..097943d --- /dev/null +++ b/seqan/align/gaps_iterator_base.h @@ -0,0 +1,525 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// Author: Manuel Holtgrewe +// ========================================================================== + +// TODO(holtgrew): Switch to Host interface. + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ITERATOR_BASE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ITERATOR_BASE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// Internally used tag for creating iterators at the begin of containers. +struct Begin__; +typedef Tag Begin_; + +// Internally used tag for creating iterators at the end of containers. +struct End__; +typedef Tag End_; + +// Internally used tag for creating iterators inside of containers. +struct Position__; +typedef Tag Position_; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @class GapsIterator + * @implements RandomAccessIteratorConcept + * + * @brief Iterator class for @link Gaps @endlink. + * + * @signature template + * class Iter >; + * + * @tparam TGaps The @link Gaps @endlink object for the iterator. + * @tparam TSpec The specializing tag. + */ + +template +struct GapsIterator; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Position +// ---------------------------------------------------------------------------- + +template +struct Position > > : + Position +{}; + +template +struct Position > const> : + Position > > +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Difference +// ---------------------------------------------------------------------------- + +template +struct Difference > > : + Difference +{}; + +template +struct Difference > const> : + Difference > > +{}; + +// ---------------------------------------------------------------------------- +// Metafunction Source +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Should this be Host? or SourceIterator? + +template +struct Source > > +{ + typedef typename Source::Type TSource_; + typedef typename Iterator::Type Type; +}; + +template +struct Source > const> +{ + typedef typename Source::Type TSource_; + typedef typename Iterator::Type Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Value +// ---------------------------------------------------------------------------- + +template +struct Value > > +{ + typedef typename Source > >::Type TSource_; + typedef typename Value::Type TSourceValue_; + //typedef TSourceValue_ Type; + // TODO(holtgrew): We really want gapped values here but there are issues... + typedef typename GappedValueType::Type Type; +}; + +template +struct Value > const> : + Value > > {}; + +// ---------------------------------------------------------------------------- +// Metafunction GetValue +// ---------------------------------------------------------------------------- + +template +struct GetValue > > : + Value > > +{ +}; + +template +struct GetValue > const> : + Value > const> +{ +}; + +// ---------------------------------------------------------------------------- +// Metafunction Reference +// ---------------------------------------------------------------------------- + +template +struct Reference > > +{ + typedef Iter > TIterator_; + typedef Proxy > Type; +}; + +template +struct Reference > const> +{ + typedef Iter const > TIterator_; + typedef Proxy > Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function operator++ +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Could be general forward + +template +inline Iter > & +operator++(Iter > & it) +{ + goNext(it); + return it; +} + +template +inline Iter > +operator++(Iter > & it, int) +{ + Iter > ret = it; + goNext(it); + return ret; +} + +// ---------------------------------------------------------------------------- +// Function operator-- +// ---------------------------------------------------------------------------- + +template +inline Iter > & +operator--(Iter > & it) +{ + goPrevious(it); + return it; +} + +template +inline Iter > +operator--(Iter > & it, int) +{ + Iter > ret = it; + goPrevious(it); + return ret; +} + +// ---------------------------------------------------------------------------- +// Function insertGap() +// ---------------------------------------------------------------------------- + +/*! + * @fn GapsIterator#insertGap + * @brief Insert gap at the current position. + * + * @signature void insertGap(it); + * + * @param[in,out] it The iterator to insert gaps at. + */ + +// Forward to insertGaps() which has to be implemented by the specific gap +// iterator. + +template +inline void +insertGap(Iter > & it) +{ + insertGaps(it, 1); +} + +// ---------------------------------------------------------------------------- +// Function isCharacter() +// ---------------------------------------------------------------------------- + +/*! + * @fn GapsIterator#isCharacter + * @brief Query an iterator for being at a character + * + * @signature bool isCharacter(it); + * + * @param[in] it Iterator to query for pointing at a character. + * + * @return bool true if it is at a character and false otherwise. + */ + +template +bool isCharacter(Iter > const & it) +{ + return !isGap(it); +} + +// ---------------------------------------------------------------------------- +// Function countCharacters() +// ---------------------------------------------------------------------------- + +/*! + * @fn GapsIterator#countCharacters + * @brief Count characters at iterator. + * + * @signature TSize countCharacters(it[, dir]); + * + * @param[in] it Iterator for counting characters at. + * @param[in] dir A tag to specify the counting direction. One of @link GapDirectionTags @endlink. + * Defaults to @link GapDirectionTags#RightOfViewPos @endlink. + * + * @return TSize Number of characters. + * + * If the the direction tag is @link GapDirectionTags#RightOfViewPos @endlink the current view position will be + * included in the count, and excluded when @link GapDirectionTags#LeftOfViewPos @endlink is selected. + */ + +template +inline typename Size::Type +countCharacters(Iter > const & it) +{ + return countCharacters(it, RightOfViewPos()); +} + +// ---------------------------------------------------------------------------- +// Function isGap() +// ---------------------------------------------------------------------------- + +/*! + * @fn GapsIterator#isGap + * @brief Query an iterator for being at a gap + * + * @signature bool isGap(it); + * + * @param[in] it Iterator to query for pointing at a gap. + * + * @return bool true if it is at a gap and false otherwise. + */ + +// ---------------------------------------------------------------------------- +// Function countGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn GapsIterator#countGaps + * @brief Count gaps at iterator. + * + * @signature TSize countGaps(it[, dir]); + * + * @param[in] it Iterator for counting gaps at. + * @param[in] dir A tag to specify the counting direction. One of @link GapDirectionTags @endlink. + * Defaults to @link GapDirectionTags#RightOfViewPos @endlink. + * + * @return TSize Number of gaps. + * + * If the the direction tag is @link GapDirectionTags#RightOfViewPos @endlink the current view position will be + * included in the count, and excluded when @link GapDirectionTags#LeftOfViewPos @endlink is selected. + */ + +template +inline typename Size::Type +countGaps(Iter > const & it) +{ + return countGaps(it, RightOfViewPos()); +} + +// ---------------------------------------------------------------------------- +// Function insertGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn GapsIterator#insertGaps + * @brief Insert gaps at the current position. + * + * @signature void insertGaps(it, num); + * + * @param[in,out] it Remove gap at the given position (if any). + * @param[in] num Number of gaps to insert. + */ + +// ---------------------------------------------------------------------------- +// Function removeGap() +// ---------------------------------------------------------------------------- + +/*! + * @fn GapsIterator#removeGap + * @brief Insert gap at the current position. + * + * @signature TSize removeGap(it); + * + * @param[in,out] it Remove gap at the given position (if any). + * + * @return TSize Number of removed gaps. + */ + +// Forward to removeGaps() which has to be implemented by the specific gap +// iterator. + +template +inline typename Size::Type +removeGap(Iter > & it) +{ + return removeGaps(it, 1); +} + +// ---------------------------------------------------------------------------- +// Function removeGaps() +// ---------------------------------------------------------------------------- + +/*! + * @fn GapsIterator#removeGaps + * @brief Remove gaps from the current position. + * + * @signature TSize removeGaps(it, num); + * + * @param[in,out] it Remove gap at the given position (if any). + * @param[in] num Number of gaps to remove. + * + * @return TSize Number of removed gaps. + */ + +// ---------------------------------------------------------------------------- +// Function assignValue() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Const consistency problems. + +template +inline void +assignValue(Iter > & me, + TValue const & val) +{ + if (!isGap(me)) + { + assignValue(source(me), val); + } + // TODO(holtgrew): Else, inserting gaps is problematic... +} + +template +inline void +assignValue(Iter > const & me, + TValue const & val) +{ + if (!isGap(me)) + { + assignValue(source(me), val); + } +} + +// ---------------------------------------------------------------------------- +// Function container() +// ---------------------------------------------------------------------------- + +template +inline TGaps & +container(Iter > & me) +{ + return *me._container; +} + +template +inline TGaps & +container(Iter > const & me) +{ + return *me._container; +} + +// ---------------------------------------------------------------------------- +// Function source +// ---------------------------------------------------------------------------- + +// Returns host iterator. + +// TODO(holtgrew): Non-const version is superfluous. +template +inline typename Source > >::Type /*returns copy*/ +source(Iter > & it) +{ + return iter(container(it), toSourcePosition(container(it), position(it))); +} + +template +inline typename Source > const>::Type /*returns copy*/ +source(Iter > const & it) +{ + return iter(container(source(it)), toSourcePosition(container(it), position(it))); +} + +// TODO(holtgrew): setSource? setContainer? + +// ---------------------------------------------------------------------------- +// Function operator+= +// ---------------------------------------------------------------------------- + +template +inline Iter > & +operator+=(Iter > & it, TDiff diff) +{ + goFurther(it, diff); + return it; +} + +// ---------------------------------------------------------------------------- +// Function operator-= +// ---------------------------------------------------------------------------- + +template +inline Iter > & +operator-=(Iter > & it, TDiff diff) +{ + goFurther(it, -(int64_t)(diff)); + return it; +} + +// ---------------------------------------------------------------------------- +// Function goFurther +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Implementation could be faster. +template +inline void +goFurther(Iter > & it, + TDifference steps) +{ + typedef typename MakeSigned::Type TSignedDifference; + if (steps > TDifference(0)) + for (; steps; --steps) + goNext(it); + else + for (; -static_cast(steps); ++steps) + goPrevious(it); +} + +// ---------------------------------------------------------------------------- +// Function isClipped() +// ---------------------------------------------------------------------------- + +template +inline bool +isClipped(Iter > const &) +{ + return false; +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ALIGN_GAPS_ITERATOR_BASE_H_ diff --git a/seqan/align/global_alignment_banded.h b/seqan/align/global_alignment_banded.h new file mode 100644 index 0000000..eab33c6 --- /dev/null +++ b/seqan/align/global_alignment_banded.h @@ -0,0 +1,786 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Global alignment interface for the banded Needleman-Wunsch and Gotoh +// algorithms. +// +// We define the interface functions pretty explicitely (versus just TAlign, +// TFragments etc.) so the candidates the compiler gives when resolution to +// the globalFunction() fails is actually meaningful. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_BANDED_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_BANDED_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +template +class Score; +template +class Graph; +template +struct Alignment; +template +class Fragment; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [banded, Align] +// ---------------------------------------------------------------------------- + +template +TScoreValue globalAlignment(Align & align, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + int lowerDiag, + int upperDiag, + TAlgoTag const & /*algoTag*/) +{ + typedef Align TAlign; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + String trace; + + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, source(row(align, 0)), source(row(align, 1)), + scoringScheme, TAlignConfig2(lowerDiag, upperDiag), TGapModel()); + + _adaptTraceSegmentsTo(row(align, 0), row(align, 1), trace); + return res; +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignment(Align & align, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignment(align, scoringScheme, alignConfig, lowerDiag, upperDiag, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignment(Align & align, + Score const & scoringScheme, + AlignConfig const & alignConfig, + int lowerDiag, + int upperDiag) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignment(align, scoringScheme, alignConfig, lowerDiag, upperDiag, LinearGaps()); + else + return globalAlignment(align, scoringScheme, alignConfig, lowerDiag, upperDiag, AffineGaps()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignment(Align & align, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + AlignConfig<> alignConfig; + return globalAlignment(align, scoringScheme, alignConfig, lowerDiag, upperDiag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [banded, Gaps] +// ---------------------------------------------------------------------------- + +template +TScoreValue globalAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + int lowerDiag, + int upperDiag, + TAlgoTag const & /*algoTag*/) +{ + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + String trace; + + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, source(gapsH), source(gapsV), scoringScheme, + TAlignConfig2(lowerDiag, upperDiag), TGapModel()); + _adaptTraceSegmentsTo(gapsH, gapsV, trace); + return res; +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignment(gapsH, gapsV, scoringScheme, alignConfig, lowerDiag, upperDiag, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + AlignConfig const & alignConfig, + int lowerDiag, + int upperDiag) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignment(gapsH, gapsV, scoringScheme, alignConfig, lowerDiag, upperDiag, NeedlemanWunsch()); + else + return globalAlignment(gapsH, gapsV, scoringScheme, alignConfig, lowerDiag, upperDiag, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + AlignConfig<> alignConfig; + return globalAlignment(gapsH, gapsV, scoringScheme, alignConfig, lowerDiag, upperDiag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [banded, Graph >] +// ---------------------------------------------------------------------------- + +// Full interface. +template +TScoreValue globalAlignment(Graph > & alignmentGraph, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + int lowerDiag, + int upperDiag, + TAlgoTag const & /*algoTag*/) +{ + typedef Graph > TGraph; + typedef typename Position::Type TPosition; + typedef typename Size::Type TSize; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + String trace; + + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, value(stringSet(alignmentGraph), 0), + value(stringSet(alignmentGraph), 1), scoringScheme, + TAlignConfig2(lowerDiag, upperDiag), TGapModel()); + + _adaptTraceSegmentsTo(alignmentGraph, positionToId(stringSet(alignmentGraph), 0), + positionToId(stringSet(alignmentGraph), 1), trace); + return res; +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignment(Graph > & alignmentGraph, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignment(alignmentGraph, scoringScheme, alignConfig, lowerDiag, upperDiag, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignment(Graph > & alignmentGraph, + Score const & scoringScheme, + AlignConfig const & alignConfig, + int lowerDiag, + int upperDiag) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignment(alignmentGraph, scoringScheme, alignConfig, lowerDiag, upperDiag, NeedlemanWunsch()); + else + return globalAlignment(alignmentGraph, scoringScheme, alignConfig, lowerDiag, upperDiag, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignment(Graph > & alignmentGraph, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + AlignConfig<> alignConfig; + return globalAlignment(alignmentGraph, scoringScheme, alignConfig, lowerDiag, upperDiag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [banded, String >] +// ---------------------------------------------------------------------------- + +// Full interface. +template +TScoreValue globalAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + int lowerDiag, + int upperDiag, + TAlgoTag const & /*algoTag*/) +{ + typedef String, TStringSpec> TFragments; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + String trace; + + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, value(strings, 0), value(strings, 1), scoringScheme, + TAlignConfig2(lowerDiag, upperDiag), TGapModel()); + + _adaptTraceSegmentsTo(fragmentString, positionToId(strings, 0), positionToId(strings, 1), trace); + return res; +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignment(fragmentString, strings, scoringScheme, alignConfig, lowerDiag, upperDiag, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme, + AlignConfig const & alignConfig, + int lowerDiag, + int upperDiag) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignment(fragmentString, strings, scoringScheme, alignConfig, lowerDiag, upperDiag, NeedlemanWunsch()); + else + return globalAlignment(fragmentString, strings, scoringScheme, alignConfig, lowerDiag, upperDiag, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + AlignConfig<> alignConfig; + return globalAlignment(fragmentString, strings, scoringScheme, alignConfig, lowerDiag, upperDiag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() [banded, 2 Strings] +// ---------------------------------------------------------------------------- + +template +TScoreValue globalAlignmentScore(TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + int lowerDiag, + int upperDiag, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps, TracebackOff> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + DPScoutState_ dpScoutState; + String > traceSegments; // Dummy segments. + return _setUpAndRunAlignment(traceSegments, dpScoutState, seqH, seqV, scoringScheme, + TAlignConfig2(lowerDiag, upperDiag), TGapModel()); +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignmentScore(TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(seqH, seqV, scoringScheme, alignConfig, lowerDiag, upperDiag, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignmentScore(TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme, + AlignConfig const & alignConfig, + int lowerDiag, + int upperDiag) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignmentScore(seqH, seqV, scoringScheme, alignConfig, lowerDiag, upperDiag, NeedlemanWunsch()); + else + return globalAlignmentScore(seqH, seqV, scoringScheme, alignConfig, lowerDiag, upperDiag, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignmentScore(TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(seqH, seqV, scoringScheme, alignConfig, lowerDiag, upperDiag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() [banded, StringSet] +// ---------------------------------------------------------------------------- + +template +TScoreValue globalAlignmentScore(StringSet const & strings, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + int lowerDiag, + int upperDiag, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps, TracebackOff> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + SEQAN_ASSERT_EQ(length(strings), 2u); + + DPScoutState_ dpScoutState; + String > traceSegments; // Dummy segments. + return _setUpAndRunAlignment(traceSegments, dpScoutState, strings[0], strings[1], scoringScheme, + TAlignConfig2(lowerDiag, upperDiag), TGapModel()); +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignmentScore(StringSet const & strings, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TAlgoTag const & algoTag) +{ + SEQAN_ASSERT_EQ(length(strings), 2u); + + AlignConfig<> alignConfig; + return globalAlignmentScore(strings[0], strings[1], scoringScheme, alignConfig, lowerDiag, upperDiag, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignmentScore(StringSet const & strings, + Score const & scoringScheme, + AlignConfig const & alignConfig, + int lowerDiag, + int upperDiag) +{ + SEQAN_ASSERT_EQ(length(strings), 2u); + + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignmentScore(strings[0], strings[1], scoringScheme, alignConfig, lowerDiag, upperDiag, NeedlemanWunsch()); + else + return globalAlignmentScore(strings[0], strings[1], scoringScheme, alignConfig, lowerDiag, upperDiag, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignmentScore(StringSet const & strings, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + SEQAN_ASSERT_EQ(length(strings), 2u); + + AlignConfig<> alignConfig; + return globalAlignmentScore(strings[0], strings[1], scoringScheme, alignConfig, lowerDiag, upperDiag); +} + + +// ============================================================================ +// Many-vs-Many align interfaces. +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() [banded, SIMD version, 2x StringSet] +// ---------------------------------------------------------------------------- + +template +String globalAlignmentScore(StringSet const & stringsH, + StringSet const & stringsV, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + int lowerDiag, + int upperDiag, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps, TracebackOff> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + SEQAN_ASSERT_EQ(length(stringsH), length(stringsV)); + return _alignWrapper(stringsH, stringsV, scoringScheme, TAlignConfig2(lowerDiag, upperDiag), TGapModel()); +} + +// Interface without AlignConfig<>. +template +String globalAlignmentScore(StringSet const & stringsH, + StringSet const & stringsV, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(stringsH, stringsV, scoringScheme, alignConfig, lowerDiag, upperDiag, algoTag); +} + +// Interface without algorithm tag. +template +String globalAlignmentScore(StringSet const & stringsH, + StringSet const & stringsV, + Score const & scoringScheme, + AlignConfig const & alignConfig, + int lowerDiag, + int upperDiag) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignmentScore(stringsH, stringsV, scoringScheme, alignConfig, lowerDiag, upperDiag, NeedlemanWunsch()); + else + return globalAlignmentScore(stringsH, stringsV, scoringScheme, alignConfig, lowerDiag, upperDiag, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +String globalAlignmentScore(StringSet const & stringsH, + StringSet const & stringsV, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(stringsH, stringsV, scoringScheme, alignConfig, lowerDiag, upperDiag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() [banded, SIMD version, String vs StringSet] +// ---------------------------------------------------------------------------- + +template +String globalAlignmentScore(TStringH const & stringH, + StringSet const & stringsV, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + int lowerDiag, + int upperDiag, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps, TracebackOff> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + return _alignWrapper(stringH, stringsV, scoringScheme, TAlignConfig2(lowerDiag, upperDiag), TGapModel()); +} + +// Interface without AlignConfig<>. +template +String globalAlignmentScore(TString const & stringH, + StringSet const & stringsV, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(stringH, stringsV, scoringScheme, alignConfig, lowerDiag, upperDiag, algoTag); +} + +// Interface without algorithm tag. +template +String globalAlignmentScore(TString const & stringH, + StringSet const & stringsV, + Score const & scoringScheme, + AlignConfig const & alignConfig, + int lowerDiag, + int upperDiag) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignmentScore(stringH, stringsV, scoringScheme, alignConfig, lowerDiag, upperDiag, NeedlemanWunsch()); + else + return globalAlignmentScore(stringH, stringsV, scoringScheme, alignConfig, lowerDiag, upperDiag, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +String globalAlignmentScore(TString const & stringH, + StringSet const & stringsV, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(stringH, stringsV, scoringScheme, alignConfig, lowerDiag, upperDiag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [banded, SIMD version, GapsH, GapsV] +// ---------------------------------------------------------------------------- + +template +inline auto +globalAlignment(StringSet & gapSeqSetH, + StringSet & gapSeqSetV, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + int const lowerDiag, + int const upperDiag, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + return _alignWrapper(gapSeqSetH, gapSeqSetV, scoringScheme, TAlignConfig2(lowerDiag, upperDiag), TGapModel()); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [banded, SIMD version, StringSet] +// ---------------------------------------------------------------------------- + +template +String globalAlignment(StringSet > & alignSet, + Score const & scoringScheme, + AlignConfig const & alignConfig, + int const lowerDiag, + int const upperDiag, + TAlgoTag const & algoTag) +{ + typedef Align TAlign; + typedef typename Row::Type TGapSequence; + + StringSet > gapSetH; + StringSet > gapSetV; + reserve(gapSetH, length(alignSet)); + reserve(gapSetV, length(alignSet)); + + for (auto & align : alignSet) + { + appendValue(gapSetH, row(align, 0)); + appendValue(gapSetV, row(align, 1)); + } + + return globalAlignment(gapSetH, gapSetV, scoringScheme, alignConfig, lowerDiag, upperDiag, algoTag); +} + +// Interface without AlignConfig<>. +template +String globalAlignment(StringSet > & align, + Score const & scoringScheme, + int lowerDiag, int upperDiag, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignment(align, scoringScheme, alignConfig, lowerDiag, upperDiag, algoTag); +} + +// Interface without algorithm tag. +template +String globalAlignment(StringSet > & align, + Score const & scoringScheme, + AlignConfig const & alignConfig, + int lowerDiag, int upperDiag) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignment(align, scoringScheme, alignConfig, lowerDiag, upperDiag, NeedlemanWunsch()); + else + return globalAlignment(align, scoringScheme, alignConfig, lowerDiag, upperDiag, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +String globalAlignment(StringSet > & align, + Score const & scoringScheme, + int lowerDiag, int upperDiag) +{ + AlignConfig<> alignConfig; + return globalAlignment(align, scoringScheme, alignConfig, lowerDiag, upperDiag); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_BANDED_H_ diff --git a/seqan/align/global_alignment_hirschberg_impl.h b/seqan/align/global_alignment_hirschberg_impl.h new file mode 100644 index 0000000..0497f7d --- /dev/null +++ b/seqan/align/global_alignment_hirschberg_impl.h @@ -0,0 +1,694 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== + +#include + +// TODO(holtgrew): Get rid of this? +//#define SEQAN_HIRSCHBERG_DEBUG_CUT + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_HIRSCHBERG_IMPL_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_HIRSCHBERG_IMPL_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +struct Hirschberg_; +typedef Tag Hirschberg; + +// ---------------------------------------------------------------------------- +// Helper Class HirschbergSet_ +// ---------------------------------------------------------------------------- + +// State for the implementation of Hirschberg's algorithm. + +class HirschbergSet_ +{ +public: + unsigned x1; + unsigned x2; + unsigned y1; + unsigned y2; + int score; +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _begin1() +// ---------------------------------------------------------------------------- + +inline unsigned & +_begin1(HirschbergSet_ & me) { + return me.x1; +} + + +inline unsigned const & +_begin1(HirschbergSet_ const & me) { + return me.x1; +} + +// ---------------------------------------------------------------------------- +// Function _setBegin1() +// ---------------------------------------------------------------------------- + +inline void +_setBegin1(HirschbergSet_ & me, unsigned const & new_begin) { + me.x1 = new_begin; +} + +// ---------------------------------------------------------------------------- +// Function _end1() +// ---------------------------------------------------------------------------- + +inline unsigned & +_end1(HirschbergSet_ & me) { + return me.x2; +} + +inline unsigned const & +_end1(HirschbergSet_ const & me) { + return me.x2; +} + +// ---------------------------------------------------------------------------- +// Function _setEnd1() +// ---------------------------------------------------------------------------- + +inline void +_setEnd1(HirschbergSet_ & me, unsigned const & new_end) { + me.x2 = new_end; +} + +// ---------------------------------------------------------------------------- +// Function _begin2() +// ---------------------------------------------------------------------------- + +inline unsigned & +_begin2(HirschbergSet_ & me) { + return me.y1; +} + +inline unsigned const & +_begin2(HirschbergSet_ const & me) { + return me.y1; +} + +// ---------------------------------------------------------------------------- +// Function _setBegin2() +// ---------------------------------------------------------------------------- + +inline void +_setBegin2(HirschbergSet_ & me, unsigned const & new_begin) { + me.y1 = new_begin; +} + +// ---------------------------------------------------------------------------- +// Function _end2() +// ---------------------------------------------------------------------------- + +inline unsigned & +_end2(HirschbergSet_ & me) { + return me.y2; +} + +inline unsigned const & +_end2(HirschbergSet_ const & me) { + return me.y2; +} + +// ---------------------------------------------------------------------------- +// Function _setEnd2() +// ---------------------------------------------------------------------------- + +inline void +_setEnd2(HirschbergSet_ & me, unsigned const & new_end) { + me.y2 = new_end; +} + +// ---------------------------------------------------------------------------- +// Function _score() +// ---------------------------------------------------------------------------- + +inline int & +_score(HirschbergSet_ & me) { + return me.score; +} + +// ---------------------------------------------------------------------------- +// Function _score() +// ---------------------------------------------------------------------------- + +inline int const & +_score(HirschbergSet_ const & me) +{ + return me.score; +} + +// ---------------------------------------------------------------------------- +// Function _setScore() +// ---------------------------------------------------------------------------- + +inline void +_setScore(HirschbergSet_ & me,int new_score) { + me.score = new_score; +} + +// ---------------------------------------------------------------------------- +// Function _setBegin2() +// ---------------------------------------------------------------------------- + +// ////////////////////////////////////////////////////////////////////////////////////////////// +// Debug Methods +// functions are only used for debugging or verbose output, therefore they +// are only active in SEQAN_DEBUG +// ////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef SEQAN_DEBUG + +inline +void +print(HirschbergSet_ const & me) +{ + std::cout << me.x1 << " " << me.x2 << "\t" << me.y1 << " " << me.y2 << std::endl; +} +#endif + +// ---------------------------------------------------------------------------- +// Function operator==() +// ---------------------------------------------------------------------------- + +inline bool +operator==(HirschbergSet_ const & lhs, + HirschbergSet_ const & rhs) +{ + return ((_begin1(lhs) == _begin1(rhs)) && (_end1(lhs) == _end1(rhs)) && + (_begin2(lhs) == _begin2(rhs)) && (_end2(lhs) == _end2(rhs))); +} + +// ---------------------------------------------------------------------------- +// Function _writeDebugMatrix() +// ---------------------------------------------------------------------------- + +#ifdef SEQAN_HIRSCHBERG_DEBUG_CUT + template + void _writeDebugMatrix(TSource s1,TSource s2) + { + int l1 = length(s1); + int l2 = length(s2); + + int i,j,sg,sd; + + String > fMatrix,rMatrix,tMatrix; + + resize(fMatrix,l1 + 1); + resize(rMatrix,l1 + 1); + resize(tMatrix,l1 + 1); + + for(i = 0;i <= l1;++i) + { + resize(fMatrix[i],l2 + 1); + resize(rMatrix[i],l2 + 1); + resize(tMatrix[i],l2 + 1); + } + + for(i = 0;i <= l1;++i) + fMatrix[i][0] = i * (-1); + + for(i = l1;i >= 0;--i) + rMatrix[i][l2] = (l1 - i) * (-1); + + // calculate forward matrix + for(j = 1;j <= l2;++j) + { + fMatrix[0][j] = j*(-1); + for(i = 1;i <= l1;++i) + { + sg = -1 + ((fMatrix[i-1][j] > fMatrix[i][j-1]) ? fMatrix[i-1][j] : fMatrix[i][j-1]); + sd = fMatrix[i-1][j-1] + ((s1[i - 1] == s2[j-1]) ? 0 : -1 ); + + fMatrix[i][j] = ((sg > sd) ? sg : sd); + } + } + + // calculate reverse matrix + for(j = l2 - 1;j >= 0;--j) + { + rMatrix[l1][j] = (l2 - j)*(-1); + for(i = l1 - 1;i >= 0;--i) + { + sg = -1 + ((rMatrix[i+1][j] > rMatrix[i][j+1]) ? rMatrix[i+1][j] : rMatrix[i][j+1]); + sd = rMatrix[i+1][j+1] + ((s1[i] == s2[j]) ? 0 : -1 ); + + rMatrix[i][j] = ((sg > sd) ? sg : sd); + } + } + + // print fMatrix + std::cout << ";-;"; + for(i = 0;i < l1;++i) + std::cout << s1[i] << ";"; + + std::cout << std::endl << "-;"; + for(j = 0;j <= l2;++j) + { + if(j != 0) std::cout << s2[j-1] << ";"; + for(i = 0;i <= l1;++i) + { + std::cout << fMatrix[i][j] << ";"; + } + std::cout << std::endl; + } + // print rMatrix + std::cout << ";"; + for(i = 0;i < l1;++i) + std::cout << s1[i] << ";"; + std::cout << "-;" << std::endl; + + for(j = 0;j <= l2;++j) + { + if(j != l2) std::cout << s2[j] << ";"; + else std::cout << "-;"; + for(i = 0;i <= l1;++i) + { + std::cout << rMatrix[i][j] << ";"; + } + std::cout << std::endl; + } + + // fill and print target matrix + std::cout << ";-;"; + for(i = 0;i < l1;++i) + std::cout << s1[i] << ";"; + + std::cout << std::endl << "-;"; + for(j = 0;j <= l2;++j) + { + if(j != 0) std::cout << s2[j-1] << ";"; + for(i = 0;i <= l1;++i) + { + tMatrix[i][j] = fMatrix[i][j] + rMatrix[i][j]; + std::cout << tMatrix[i][j] << ";"; + } + std::cout << std::endl; + } + } + +#endif + +// debug flag .. define to see where Hirschberg cuts the sequences +//#define SEQAN_HIRSCHBERG_DEBUG_CUT + +// ---------------------------------------------------------------------------- +// Function globalAlignment() +// ---------------------------------------------------------------------------- + +template +TScoreValue +_globalAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & score_, + Hirschberg const & /*algorithmTag*/) +{ + TSequenceH const & s1 = source(gapsH); + TSequenceV const & s2 = source(gapsV); + + TScoreValue total_score = 0; + + typedef typename Value::Type TValueV; + + typedef typename Size::Type TStringSize; + + typedef typename Iterator::Type TSequenceHIter; + typedef typename Iterator::Type TSequenceVIter; + + typedef typename Iterator >::Type TGapsHIter; + typedef typename Iterator >::Type TGapsVIter; + + TGapsHIter target_0 = begin(gapsH); + TGapsVIter target_1 = begin(gapsV); + + typedef typename Iterator >::Type TMatrixIterator; + + TValueV v; + + TStringSize len1 = length(s1); + TStringSize len2 = length(s2); + + // string to store the score values for the currently active cell + String c_score; + resize(c_score,len2 + 1); + // string to strore the backpointers + String pointer; + resize(pointer,len2 + 1); + + // scoring-scheme specific score values + TScoreValue score_match = scoreMatch(score_); + TScoreValue score_mismatch = scoreMismatch(score_); + TScoreValue score_gap = scoreGapExtend(score_); + + TScoreValue border,s,sg,sd,sg1,sg2; + int dp; + + std::stack to_process; + HirschbergSet_ target; + + unsigned i,j; + + HirschbergSet_ hs_complete{0, static_cast(len1), 0, static_cast(len2), 0}; + to_process.push(hs_complete); + + while(!to_process.empty()) + { + target = to_process.top(); + to_process.pop(); + + if(_begin2(target) == _end2(target)) + { + for(i = 0;i < (_end1(target) - _begin1(target));++i) + { + insertGap(target_1); + ++target_0; + ++target_1; + } + } + if(_begin1(target) == _end1(target)) + { + for(i = 0;i < (_end2(target) - _begin2(target));++i) + { + insertGap(target_0); + ++target_0; + ++target_1; + } + } + else if(_begin1(target) + 1 == _end1(target) || _begin2(target) + 1 == _end2(target)) + { + /* ALIGN */ +#ifdef SEQAN_HIRSCHBERG_DEBUG_CUT + std::cout << "align s1 " << _begin1(target) << " to " << _end1(target) << " and s2 " << _begin2(target) << " to " << _end2(target) << std::endl; + std::cout << "align " << infix(s1,_begin1(target),_end1(target)) << " and " << infix(s2,_begin2(target),_end2(target)) << std::endl << std::endl; +#endif + + TStringSize len_1 = _end1(target) - _begin1(target); + TStringSize len_2 = _end2(target) - _begin2(target); + + Matrix matrix_; + + setDimension(matrix_, 2); + setLength(matrix_, 0, len_1 + 1); + setLength(matrix_, 1, len_2 + 1); + resize(matrix_); + + /* init matrix */ + TSequenceHIter x_begin = iter(s1, _begin1(target), Standard()) - 1; + TSequenceHIter x_end = iter(s1, _end1(target), Standard()) - 1; + TSequenceVIter y_begin = iter(s2, _begin2(target), Standard()) - 1; + TSequenceVIter y_end = iter(s2, _end2(target), Standard()) - 1; + + TSequenceHIter x = x_end; + TSequenceVIter y; + + TMatrixIterator col_ = end(matrix_) - 1; + TMatrixIterator finger1; + TMatrixIterator finger2; + + + TScoreValue h = 0; + TScoreValue border_ = score_gap; + TScoreValue v = border_; + + + //------------------------------------------------------------------------- + // init + + finger1 = col_; + *finger1 = 0; + for (x = x_end; x != x_begin; --x) + { + goPrevious(finger1, 0); + *finger1 = border_; + border_ += score_gap; + } + + //------------------------------------------------------------------------- + //fill matrix + border_ = 0; + for (y = y_end; y != y_begin; --y) + { + TValueV cy = *y; + h = border_; + border_ += score_gap; + v = border_; + + finger2 = col_; + goPrevious(col_, 1); + finger1 = col_; + + *finger1 = v; + + for (x = x_end; x != x_begin; --x) + { + goPrevious(finger1, 0); + goPrevious(finger2, 0); + if (*x == cy) + { + v = h + score_match; + h = *finger2; + } + else + { + TScoreValue s1 = h + score_mismatch; + h = *finger2; + TScoreValue s2 = score_gap + ((h > v) ? h : v); + v = (s1 > s2) ? s1 : s2; + } + *finger1 = v; + } + } + total_score += value(matrix_, 0,0); +#ifdef SEQAN_HIRSCHBERG_DEBUG_CUT + std::cout << "alignment score is " << total_score << std::endl << std::endl; +#endif + + /* TRACE BACK */ + finger1 = begin(matrix_); + x = iter(s1,_begin1(target)); + y = iter(s2,_begin2(target)); + x_end = iter(s1,_end1(target)); + y_end = iter(s2,_end2(target)); + + while ((x != x_end) && (y != y_end)) + { + bool gv; + bool gh; + + if (*x == *y) + { + gv = gh = true; + } + else + { + TMatrixIterator it_ = finger1; + + goNext(it_, 0); + TScoreValue v = *it_; + + goNext(it_, 1); + TScoreValue d = *it_; + + it_ = finger1; + goNext(it_, 1); + TScoreValue h = *it_; + + gv = (v >= h) | (d >= h); + gh = (h >= v) | (d >= v); + } + + if (gv) + { + ++x; + goNext(finger1, 0); + } + else + { + insertGap(target_0); + } + + if (gh) + { + ++y; + goNext(finger1, 1); + } + else + { + insertGap(target_1); + } + + ++target_0; + ++target_1; + } + + // if x or y did not reached there end position, fill the rest with gaps + while(x != x_end) + { + insertGap(target_1); + ++target_0; + ++target_1; + ++x; + } + + while(y != y_end) + { + insertGap(target_0); + ++target_0; + ++target_1; + ++y; + } + /* END ALIGN */ + } + else + { + /* + Calculate cut using the algorithm as proposed in the lecture of Clemens Gröpl + using a backpointer to remember the position where the optimal alignment passes + the mid column + */ + unsigned mid = static_cast(floor( static_cast((_begin1(target) + _end1(target))/2) )); + +#ifdef SEQAN_HIRSCHBERG_DEBUG_CUT + std::cout << "calculate cut for s1 " << _begin1(target) << " to " << _end1(target) << " and s2 " << _begin2(target) << " to " << _end2(target) << std::endl; + std::cout << "calculate cut for " << infix(s1,_begin1(target),_end1(target)) << " and " << infix(s2,_begin2(target),_end2(target)) << std::endl; + std::cout << "cut is in row " << mid << " symbol is " << getValue(s1,mid-1) << std::endl << std::endl; + + + _writeDebugMatrix(infix(s1,_begin1(target),_end1(target)),infix(s2,_begin2(target),_end2(target))); +#endif + + border = 0; + for(i = _begin2(target);i <= _end2(target);++i) + { + c_score[i] = border; + border += score_gap; + pointer[i] = i; + } + + // iterate over s1 until the mid column is reached + border = score_gap; + for(i = _begin1(target) + 1;i <= mid;++i) + { + s = c_score[_begin2(target)]; + c_score[_begin2(target)] = border; + border += score_gap; + v = getValue(s1,i-1); + for(j = _begin2(target) + 1;j <= _end2(target);++j) + { + sg = score_gap + ((c_score[j] > c_score[j - 1]) ? c_score[j] : c_score[j - 1]); + sd = s + ((v == getValue(s2,j-1)) ? score_match : score_mismatch); + + s = c_score[j]; + c_score[j] = (sg > sd) ? sg : sd; + } + } + + // from here, rememeber the cell of mid-column, where optimal alignment passed + for(i = mid + 1;i <= _end1(target);++i) + { + s = c_score[_begin2(target)]; + c_score[_begin2(target)] = border; + border += score_gap; + v = getValue(s1,i-1); + + dp = _begin2(target); + + for(j = _begin2(target) + 1;j <= _end2(target);++j) + { + sg1 = score_gap + c_score[j]; + sg2 = score_gap + c_score[j - 1]; + + sd = s + ((v == getValue(s2,j-1)) ? score_match : score_mismatch); + + s = c_score[j]; + sg = pointer[j]; + if(sd >= _max(sg1,sg2)) + { + c_score[j] = sd; + pointer[j] = dp; + } + else + { + if(sg2 > sg1) + { + c_score[j] = sg2; + pointer[j] = pointer[j-1]; + } + else + { + // gap introduced from left + // no update for the pointer + c_score[j] = sg1; + } + } + dp = sg; + } + } + +#ifdef SEQAN_HIRSCHBERG_DEBUG_CUT + std::cout << "hirschberg calculates cut in column " << mid << " and row " << pointer[_end2(target)] << std::endl; + std::cout << "requested position in c_score and pointer is " << _end2(target) << std::endl; + std::cout << "alignment score is " << c_score[_end2(target)] << std::endl << std::endl; +#endif + to_process.push(HirschbergSet_{mid, _end1(target), pointer[_end2(target)], _end2(target), 0}); + to_process.push(HirschbergSet_{_begin1(target), mid, _begin2(target), pointer[_end2(target)], 0}); + } + /* END CUT */ + } + return total_score; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_HIRSCHBERG_IMPL_H_ diff --git a/seqan/align/global_alignment_myers_hirschberg_impl.h b/seqan/align/global_alignment_myers_hirschberg_impl.h new file mode 100644 index 0000000..24e67ec --- /dev/null +++ b/seqan/align/global_alignment_myers_hirschberg_impl.h @@ -0,0 +1,762 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_MYERS_HIRSCHBERG_IMPL_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_MYERS_HIRSCHBERG_IMPL_H_ + +#include + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _writeDebugMatrix() +// ---------------------------------------------------------------------------- + +#ifdef MYERS_HIRSCHBERG_VERBOSE + template + void _writeDebugMatrix(TSource s1,TSource s2) + { +//IOREV _notio_ not relevant for iorev + int l1 = length(s1); + int l2 = length(s2); + + int i,j,sg,sd; + + String > fMatrix,rMatrix,tMatrix; + + resize(fMatrix,l1 + 1); + resize(rMatrix,l1 + 1); + resize(tMatrix,l1 + 1); + + for(i = 0;i <= l1;++i) + { + resize(fMatrix[i],l2 + 1); + resize(rMatrix[i],l2 + 1); + resize(tMatrix[i],l2 + 1); + } + + for(i = 0;i <= l1;++i) + fMatrix[i][0] = i * (-1); + + for(i = l1;i >= 0;--i) + rMatrix[i][l2] = (l1 - i) * (-1); + + // calculate forward matrix + for(j = 1;j <= l2;++j) + { + fMatrix[0][j] = j*(-1); + for(i = 1;i <= l1;++i) + { + sg = -1 + ((fMatrix[i-1][j] > fMatrix[i][j-1]) ? fMatrix[i-1][j] : fMatrix[i][j-1]); + sd = fMatrix[i-1][j-1] + ((s1[i - 1] == s2[j-1]) ? 0 : -1 ); + + fMatrix[i][j] = ((sg > sd) ? sg : sd); + } + } + + // calculate reverse matrix + for(j = l2 - 1;j >= 0;--j) + { + rMatrix[l1][j] = (l2 - j)*(-1); + for(i = l1 - 1;i >= 0;--i) + { + sg = -1 + ((rMatrix[i+1][j] > rMatrix[i][j+1]) ? rMatrix[i+1][j] : rMatrix[i][j+1]); + sd = rMatrix[i+1][j+1] + ((s1[i] == s2[j]) ? 0 : -1 ); + + rMatrix[i][j] = ((sg > sd) ? sg : sd); + } + } + + // print fMatrix + std::cout << ";-;"; + for(i = 0;i < l1;++i) + std::cout << s1[i] << ";"; + + std::cout << std::endl << "-;"; + for(j = 0;j <= l2;++j) + { + if(j != 0) std::cout << s2[j-1] << ";"; + for(i = 0;i <= l1;++i) + { + std::cout << fMatrix[i][j] << ";"; + } + std::cout << std::endl; + } + // print rMatrix + std::cout << ";"; + for(i = 0;i < l1;++i) + std::cout << s1[i] << ";"; + std::cout << "-;" << std::endl; + + for(j = 0;j <= l2;++j) + { + if(j != l2) std::cout << s2[j] << ";"; + else std::cout << "-;"; + for(i = 0;i <= l1;++i) + { + std::cout << rMatrix[i][j] << ";"; + } + std::cout << std::endl; + } + + // fill and print target matrix + std::cout << ";-;"; + for(i = 0;i < l1;++i) + std::cout << s1[i] << ";"; + + std::cout << std::endl << "-;"; + for(j = 0;j <= l2;++j) + { + if(j != 0) std::cout << s2[j-1] << ";"; + for(i = 0;i <= l1;++i) + { + tMatrix[i][j] = fMatrix[i][j] + rMatrix[i][j]; + std::cout << tMatrix[i][j] << ";"; + } + std::cout << std::endl; + } + } +#endif + +// ---------------------------------------------------------------------------- +// Function _printBinary() +// ---------------------------------------------------------------------------- + +// Debug integer types in binary format. +template +inline void +_printBinary(TStream & stream, T const n) +{ + std::bitset::VALUE> bits(n); + stream << bits; + stream << '\n'; +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() +// ---------------------------------------------------------------------------- + +// When using different alphabets, we will internally use the pattern alphabet +// for the comparison. This means that the text character is converted to the +// pattern alphabet. Here, the "pattern" is the shorter source sequence. + +template +int +_globalAlignment(Gaps & gapsH, + Gaps & gapsV, + MyersHirschberg const & algorithmTag) +{ + // Switch horizontal and vertical gap roles, gapsV should be the shorter one + // to fit into less words. + if (length(source(gapsH)) < length(source(gapsV))) + return _globalAlignment(gapsV, gapsH, algorithmTag); + + clearGaps(gapsH); + clearGaps(gapsV); + clearClipping(gapsH); + clearClipping(gapsV); + + typedef int TScoreValue; + + // use size of unsigned int as blocksize for bit-vectors + const unsigned int BLOCK_SIZE = BitsPerValue::VALUE; + + // saves the score value that will be returned + TScoreValue score,total_score = 0; + + typedef typename Value::Type TPatternAlphabet; + typedef typename Size::Type TStringSize; + + typedef typename Iterator::Type TSequenceHIterator; + typedef typename Iterator::Type TSequenceVIterator; + typedef Gaps TGapsH; + typedef Gaps TGapsV; + typedef typename Iterator::Type TGapsHIterator; + typedef typename Iterator::Type TGapsVIterator; + + typedef typename Iterator, Rooted>::Type TMatrixIterator; + + TGapsHIterator target_0 = begin(gapsH); + TGapsVIterator target_1 = begin(gapsV); + + TSequenceH const & x = source(gapsH); + TSequenceV const & y = source(gapsV); + + TStringSize len_x = length(x); + TStringSize len_y = length(y); + + // string to store the score values for the currently active cell + String c_score; + resize(c_score, len_x + 1, 0); + + // scoring-scheme specific score values + TScoreValue score_match = 0; + TScoreValue score_mismatch = -1; + TScoreValue score_gap = -1; + + // additional vars + unsigned i; + + // stack with parts of matrix that have to be processed + std::stack to_process; + HirschbergSet_ target; + + // myers specific vars and preprocessing + unsigned int patternAlphabetSize = ValueSize::VALUE; + unsigned int blockCount = (len_y + BLOCK_SIZE - 1) / BLOCK_SIZE; // maximal count of blocks + + String VP; + String VN; + String forwardBitMask; + String reverseBitMask; + + resize(VP, blockCount, maxValue()); + resize(VN, blockCount, 0); + + // first bitMask will be constructed from the shorter sequence + resize(forwardBitMask, patternAlphabetSize * blockCount, 0); + resize(reverseBitMask, patternAlphabetSize * blockCount, 0); + + // encoding the letters as bit-vectors + for (unsigned int j = 0; j < len_y; j++){ + forwardBitMask[blockCount * ordValue(getValue(y,j)) + j/BLOCK_SIZE] = forwardBitMask[blockCount * ordValue(getValue(y,j)) + j/BLOCK_SIZE] | 1 << (j%BLOCK_SIZE); + reverseBitMask[blockCount * ordValue(getValue(y,len_y - j - 1)) + j/BLOCK_SIZE] = reverseBitMask[blockCount * ordValue(getValue(y,len_y - j - 1)) + j/BLOCK_SIZE] | 1 << (j%BLOCK_SIZE); + } + + HirschbergSet_ hs_complete{0, static_cast(len_x), 0, static_cast(len_y), 1}; + to_process.push(hs_complete); + + while(!to_process.empty()) + { + target = to_process.top(); + to_process.pop(); + /* if score is zero, the whole part of the sequence can be simply skipped */ + if(_score(target) == 0) + { + /* coukd work faster */ + for(i = 0;i < (_end1(target) - _begin1(target));++i) + { + ++target_0; + ++target_1; + } + +#ifdef MYERS_HIRSCHBERG_VERBOSE + printf("skipped %i to %i in first sequence\n",_begin1(target),_end1(target)); +#endif + } + else if(_begin1(target) == _end1(target)) + { + +#ifdef MYERS_HIRSCHBERG_VERBOSE + std::cout << "align y " << _begin2(target) << " to " << _end2(target) << std::endl; + std::cout << "align " << infix(y,_begin2(target),_end2(target)) << std::endl << std::endl; +#endif + for(i = 0;i < (_end2(target) - _begin2(target));++i) + { + insertGap(target_0); + ++target_0; + ++target_1; + } + } + else if(_begin2(target) + 1 == _end2(target)) + { + /* ALIGN */ +#ifdef MYERS_HIRSCHBERG_VERBOSE + std::cout << "align x " << _begin1(target) << " to " << _end1(target) << " and y " << _begin2(target) << " to " << _end2(target) << std::endl; + std::cout << "align " << infix(x,_begin1(target),_end1(target)) << " and " << infix(y,_begin2(target),_end2(target)) << std::endl << std::endl; +#endif + + TStringSize len_1 = _end1(target) - _begin1(target); + TStringSize len_2 = _end2(target) - _begin2(target); + + Matrix matrix_; + + setDimension(matrix_, 2); + setLength(matrix_, 0, len_1 + 1); + setLength(matrix_, 1, len_2 + 1); + resize(matrix_); + + /* init matrix */ + TSequenceHIterator xs_begin = iter(x,_begin1(target)) - 1; + TSequenceHIterator xs_end = iter(x,_end1(target)) - 1; + TSequenceVIterator ys_begin = iter(y,_begin2(target)) - 1; + TSequenceVIterator ys_end = iter(y,_end2(target)) - 1; + + TSequenceHIterator xs = xs_end; + TSequenceVIterator ys; + + TMatrixIterator col_ = end(matrix_) - 1; + TMatrixIterator finger1; + TMatrixIterator finger2; + + + TScoreValue h = 0; + TScoreValue border_ = score_gap; + TScoreValue v = border_; + + + //------------------------------------------------------------------------- + // init + + finger1 = col_; + *finger1 = 0; + for (xs = xs_end; xs != xs_begin; --xs) + { + goPrevious(finger1, 0); + *finger1 = border_; + border_ += score_gap; + } + + //------------------------------------------------------------------------- + //fill matrix + + border_ = 0; + for (ys = ys_end; ys != ys_begin; --ys) + { + TPatternAlphabet cy = *ys; + h = border_; + border_ += score_gap; + v = border_; + + finger2 = col_; + goPrevious(col_, 1); + finger1 = col_; + + *finger1 = v; + + for (xs = xs_end; xs != xs_begin; --xs) + { + goPrevious(finger1, 0); + goPrevious(finger2, 0); + if (*xs == cy) + { + v = h + score_match; + h = *finger2; + } + else + { + TScoreValue s1 = h + score_mismatch; + h = *finger2; + TScoreValue s2 = score_gap + ((h > v) ? h : v); + v = (s1 > s2) ? s1 : s2; + } + *finger1 = v; + } + } + + // if computed the whole matrix last value of v = alignment score + if(target == hs_complete) total_score = v; + + /* TRACE BACK */ + finger1 = begin(matrix_); + xs = iter(x,_begin1(target)); + ys = iter(y,_begin2(target)); + xs_end = iter(x,_end1(target)); + ys_end = iter(y,_end2(target)); + + while ((xs != xs_end) && (ys != ys_end)) + { + bool gv; + bool gh; + + if (*xs == *ys) + { + gv = gh = true; + } + else + { + TMatrixIterator it_ = finger1; + + goNext(it_, 0); + TScoreValue v = *it_; + + goNext(it_, 1); + TScoreValue d = *it_; + + it_ = finger1; + goNext(it_, 1); + TScoreValue h = *it_; + + gv = (v >= h) | (d >= h); + gh = (h >= v) | (d >= v); + } + + if (gv) + { + ++xs; + goNext(finger1, 0); + } + else + { + insertGap(target_0); + } + + if (gh) + { + ++ys; + goNext(finger1, 1); + } + else + { + insertGap(target_1); + } + + ++target_0; + ++target_1; + } + + // if x or y did not reached there end position, fill the rest with gaps + while(xs != xs_end) + { + insertGap(target_1); + ++target_0; + ++target_1; + ++xs; + } + + while(ys != ys_end) + { + insertGap(target_0); + ++target_0; + ++target_1; + ++ys; + } + /* END ALIGN */ + + +#ifdef MYERS_HIRSCHBERG_VERBOSE + std::cout << std::endl << align_ << std::endl << std::endl; +#endif + + } + else + { + /* + --------------------------------------------------------------- + Calculate cut position using extended Myers-Bitvector-Algorithm + --------------------------------------------------------------- + */ + + /* declare variables */ + unsigned int X, D0, HN, HP; + + /* compute cut position */ + unsigned mid = static_cast(floor( static_cast((_begin2(target) + _end2(target))/2) )); + + /* debug infos */ +#ifdef MYERS_HIRSCHBERG_VERBOSE + std::cout << "calculate cut for x " << _begin1(target) << " to " << _end1(target) << " and y " << _begin2(target) << " to " << _end2(target) << std::endl; + std::cout << "calculate cut for " << infix(x,_begin1(target),_end1(target)) << " and " << infix(y,_begin2(target),_end2(target)) << std::endl; + std::cout << "cut is in row " << mid << " symbol is " << getValue(x,mid-1) << std::endl << std::endl; + + std::cout << std::endl; + _writeDebugMatrix(infix(x,_begin1(target),_end1(target)),infix(y,_begin2(target),_end2(target))); + std::cout << std::endl; +#endif + /* compute blocks and score masks */ + unsigned fStartBlock = _begin2(target) / BLOCK_SIZE; + unsigned fEndBlock = (mid - 1) / BLOCK_SIZE; + unsigned fSpannedBlocks = (fEndBlock - fStartBlock) + 1; + + unsigned int fScoreMask = 1 << ((mid - 1) % BLOCK_SIZE); + + unsigned int fOffSet = _begin2(target) % BLOCK_SIZE; + unsigned int fSilencer = ~0; + fSilencer <<= fOffSet; + + /* reset v-bitvectors */ + std::fill(begin(VP, Standard()) + fStartBlock, begin(VP, Standard()) + fEndBlock + 1, maxValue()); + std::fill(begin(VN, Standard()) + fStartBlock, begin(VN, Standard()) + fEndBlock + 1, 0); + + /* determine start-position and start-score */ + auto pos = _begin1(target); + score = (mid - _begin2(target)) * score_gap; + c_score[pos] = score; + + /* compute with myers - forward - begin */ + if(fSpannedBlocks == 1) + { + while (pos < _end1(target)) { + X = (fSilencer & forwardBitMask[(blockCount * ordValue(static_cast(getValue(x,pos)))) + fStartBlock]) | VN[fStartBlock]; + + D0 = ((VP[fStartBlock] + (X & VP[fStartBlock])) ^ VP[fStartBlock]) | X; + HN = VP[fStartBlock] & D0; + HP = VN[fStartBlock] | ~(VP[fStartBlock] | D0); + + X = (HP << 1) | (1 << fOffSet); + VN[fStartBlock] = X & D0; + VP[fStartBlock] = (HN << 1) | ~(X | D0); + + if (HP & fScoreMask) + score--; + else if (HN & fScoreMask) + score++; + + c_score[pos + 1] = score; + + ++pos; + } + } /* end - short patten */ + else + { + unsigned shift, currentBlock; + unsigned int temp, carryD0, carryHP, carryHN; + + while (pos < _end1(target)) + { + carryD0 = carryHP = carryHN = 0; + shift = blockCount * ordValue(static_cast(getValue(x,pos))); + + // computing first the top most block + X = (fSilencer & forwardBitMask[shift + fStartBlock]) | VN[fStartBlock]; + + temp = VP[fStartBlock] + (X & VP[fStartBlock]); + carryD0 = temp < VP[fStartBlock]; + + D0 = (temp ^ VP[fStartBlock]) | X; + HN = VP[fStartBlock] & D0; + HP = VN[fStartBlock] | ~(VP[fStartBlock] | D0); + + X = (HP << 1) | (1 << fOffSet); + carryHP = HP >> (BLOCK_SIZE - 1); + + VN[fStartBlock] = X & D0; + + temp = (HN << 1); + carryHN = HN >> (BLOCK_SIZE - 1); + + VP[fStartBlock] = temp | ~(X | D0); + + // compute the remaining blocks + for (currentBlock = fStartBlock + 1; currentBlock <= fEndBlock; currentBlock++) { + X = forwardBitMask[shift + currentBlock] | VN[currentBlock]; + + temp = VP[currentBlock] + (X & VP[currentBlock]) + carryD0; + + carryD0 = ((carryD0) ? temp <= VP[currentBlock] : temp < VP[currentBlock]); + + D0 = (temp ^ VP[currentBlock]) | X; + HN = VP[currentBlock] & D0; + HP = VN[currentBlock] | ~(VP[currentBlock] | D0); + + X = (HP << 1) | carryHP; + carryHP = HP >> (BLOCK_SIZE-1); + + VN[currentBlock] = X & D0; + + temp = (HN << 1) | carryHN; + carryHN = HN >> (BLOCK_SIZE - 1); + + VP[currentBlock] = temp | ~(X | D0); + } + + /* update score */ + if (HP & fScoreMask) + score--; + else if (HN & fScoreMask) + score++; + + c_score[pos + 1] = score; + + ++pos; + } + + } /* end - long patten */ + /* compute with myers - forward - end */ + + /* compute blocks and score masks */ + unsigned rStartBlock = (len_y - _end2(target)) / BLOCK_SIZE; + unsigned rEndBlock = (len_y - mid - 1) / BLOCK_SIZE; + unsigned rSpannedBlocks = (rEndBlock - rStartBlock) + 1; + + unsigned int rScoreMask = 1 << ((len_y - mid - 1) % BLOCK_SIZE); + unsigned int rOffSet = (len_y - _end2(target)) % BLOCK_SIZE; + unsigned int rSilencer = ~0; + rSilencer <<= rOffSet; + + /* reset v-bitvectors */ + std::fill(begin(VP, Standard()) + rStartBlock, begin(VP, Standard()) + rEndBlock + 1, maxValue()); + std::fill(begin(VN, Standard()) + rStartBlock, begin(VN, Standard()) + rEndBlock + 1, 0); + + /* determine start-position and start-score */ + pos = _end1(target); + score = (_end2(target) - mid) * score_gap; + + /* set start score */ + c_score[_end1(target)] += score; + + /* determine optimal cut position -- score extension */ + TScoreValue max = c_score[_end1(target)]; + TScoreValue rmax = score; + unsigned int pos_max = _end1(target); + + /* compute with myers - reverse - begin */ + if(rSpannedBlocks == 1) + { + while (pos-- > _begin1(target)) { + X = (rSilencer & reverseBitMask[(blockCount * ordValue(static_cast(getValue(x,pos)))) + rStartBlock]) | VN[rStartBlock]; + + D0 = ((VP[rStartBlock] + (X & VP[rStartBlock])) ^ VP[rStartBlock]) | X; + HN = VP[rStartBlock] & D0; + HP = VN[rStartBlock] | ~(VP[rStartBlock] | D0); + + X = (HP << 1) | (1 << rOffSet); + VN[rStartBlock] = X & D0; + VP[rStartBlock] = (HN << 1) | ~(X | D0); + + if (HP & rScoreMask) + --score; + else if (HN & rScoreMask) + ++score; + + c_score[pos] += score; + + /* check for optimality -- score extension */ + if(c_score[pos]> max) + { + pos_max = pos; + max = c_score[pos]; + rmax = score; + } + } + } /* end - short pattern */ + else + { + unsigned shift, currentBlock; + unsigned int temp, carryD0, carryHP, carryHN; + + while (pos-- > _begin1(target)) + { + carryD0 = carryHP = carryHN = 0; + shift = blockCount * ordValue(static_cast(getValue(x,pos))); + + // compute first the top most block + X = (rSilencer & reverseBitMask[shift + rStartBlock]) | VN[rStartBlock]; + + temp = VP[rStartBlock] + (X & VP[rStartBlock]); + carryD0 = temp < VP[rStartBlock]; + + D0 = (temp ^ VP[rStartBlock]) | X; + HN = VP[rStartBlock] & D0; + HP = VN[rStartBlock] | ~(VP[rStartBlock] | D0); + + X = (HP << 1) | (1 << rOffSet); + carryHP = HP >> (BLOCK_SIZE - 1); + + VN[rStartBlock] = X & D0; + + temp = (HN << 1); + carryHN = HN >> (BLOCK_SIZE - 1); + + VP[rStartBlock] = temp | ~(X | D0); + + // compute the remaining blocks + for (currentBlock = rStartBlock + 1; currentBlock <= rEndBlock; currentBlock++) { + X = reverseBitMask[shift + currentBlock] | VN[currentBlock]; + + temp = VP[currentBlock] + (X & VP[currentBlock]) + carryD0; + + carryD0 = ((carryD0) ? temp <= VP[currentBlock] : temp < VP[currentBlock]); + + D0 = (temp ^ VP[currentBlock]) | X; + HN = VP[currentBlock] & D0; + HP = VN[currentBlock] | ~(VP[currentBlock] | D0); + + X = (HP << 1) | carryHP; + carryHP = HP >> (BLOCK_SIZE-1); + + VN[currentBlock] = X & D0; + + temp = (HN << 1) | carryHN; + carryHN = HN >> (BLOCK_SIZE - 1); + + VP[currentBlock] = temp | ~(X | D0); + } + + if (HP & rScoreMask) + --score; + else if (HN & rScoreMask) + ++score; + + c_score[pos] += score; + + /* check for optimality -- score extension*/ + if(c_score[pos] > max) + { + pos_max = pos; + max = c_score[pos]; + rmax = score; + } + } + + } /* end - long pattern */ + /* compute with myers - reverse - end */ + + // if computed the whole matrix max = alignment score + if(target == hs_complete) + total_score = max; + +#ifdef MYERS_HIRSCHBERG_VERBOSE + printf("Optimal cut is at %i and %i with forward score %i and reverse score %i\n\n",mid,pos_max,(max - rmax),rmax); +#endif + /* push the two computed parts of the dp-matrix on process stack */ + to_process.push(HirschbergSet_{pos_max, _end1(target), mid, _end2(target), rmax}); + to_process.push(HirschbergSet_{_begin1(target), pos_max, _begin2(target), mid, max - rmax}); + + } + /* END CUT */ + } + + return total_score; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_MYERS_HIRSCHBERG_IMPL_H_ diff --git a/seqan/align/global_alignment_myers_impl.h b/seqan/align/global_alignment_myers_impl.h new file mode 100644 index 0000000..8082f3b --- /dev/null +++ b/seqan/align/global_alignment_myers_impl.h @@ -0,0 +1,201 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== + +// TODO(holtgrew): Should be called _globalAlignmentScore()! + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_MYERS_IMPL_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_MYERS_IMPL_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// When using different alphabets, we will internally use the pattern alphabet +// for the comparison. This means that the text character is converted to the +// pattern alphabet. Here, the "pattern" is the shorter source sequence. + +template +int +_globalAlignmentScore(String const & seqH, + String const & seqV, + MyersBitVector const & algorithmTag) +{ + // Switch horizontal and vertical gap roles, gapsV should be the shorter one + // to fit into less words. + if (length(seqH) < length(seqV)) + return _globalAlignmentScore(seqV, seqH, algorithmTag); + + // Use size of unsigned int as blocksize for bit-vectors. + const unsigned int BLOCK_SIZE = BitsPerValue::VALUE; + + typedef String const TSequenceH; + typedef String const TSequenceV; + + typedef typename Value::Type TPatternAlphabet; + typedef typename Size::Type TSourceSize; + + TSequenceH const & x = seqH; + TSequenceV const & y = seqV; + + TSourceSize len_x = length(x); + unsigned int pos = 0; + + // init variables + unsigned int len_y = length(y); + int score = (-1)*len_y; + unsigned int patternAlphabetSize = ValueSize::VALUE; + unsigned int blockCount = (len_y + BLOCK_SIZE - 1) / BLOCK_SIZE; + + unsigned int scoreMask = 1 << ((len_y % BLOCK_SIZE) - 1); // the mask with a bit set at the position of the last active cell + + String VP; + resize(VP, blockCount, maxValue()); + String VN; + resize(VN, blockCount, 0); + String bitMask; + resize(bitMask, patternAlphabetSize * blockCount, 0); + + // encoding the letters as bit-vectors + for (unsigned int j = 0; j < len_y; j++) + bitMask[blockCount * ordValue(getValue(y,j)) + j/BLOCK_SIZE] = bitMask[blockCount * ordValue(getValue(y,j)) + j/BLOCK_SIZE] | 1 << (j%BLOCK_SIZE); + + // compute score + unsigned int X, D0, HN, HP; + if(blockCount == 1) + { + while (pos < len_x) { + X = bitMask[ordValue(static_cast(getValue(x,pos)))] | VN[0]; + + D0 = ((VP[0] + (X & VP[0])) ^ VP[0]) | X; + HN = VP[0] & D0; + HP = VN[0] | ~(VP[0] | D0); + + // customized to compute edit distance + X = (HP << 1) | 1; + VN[0] = X & D0; + VP[0] = (HN << 1) | ~(X | D0); + + if (HP & scoreMask) + score--; + else if (HN & scoreMask) + score++; + + ++pos; + } + } // end compute score - short pattern + else + { + unsigned int temp, shift, currentBlock; + unsigned int carryD0, carryHP, carryHN; + + while (pos < len_x) + { + // set vars + carryD0 = carryHP = carryHN = 0; + shift = blockCount * ordValue(static_cast(getValue(x,pos))); + + // computing first the top most block + X = bitMask[shift] | VN[0]; + + temp = VP[0] + (X & VP[0]); + carryD0 = temp < VP[0]; + + D0 = (temp ^ VP[0]) | X; + HN = VP[0] & D0; + HP = VN[0] | ~(VP[0] | D0); + + // customized to compute edit distance + X = (HP << 1) | 1; + carryHP = HP >> (BLOCK_SIZE - 1); + + VN[0] = X & D0; + + temp = (HN << 1); + carryHN = HN >> (BLOCK_SIZE - 1); + + VP[0] = temp | ~(X | D0); + + // computing the necessary blocks, carries between blocks following one another are stored + for (currentBlock = 1; currentBlock < blockCount; currentBlock++) { + X = bitMask[shift + currentBlock] | VN[currentBlock]; + + temp = VP[currentBlock] + (X & VP[currentBlock]) + carryD0; + + carryD0 = ((carryD0) ? temp <= VP[currentBlock] : temp < VP[currentBlock]); + + D0 = (temp ^ VP[currentBlock]) | X; + HN = VP[currentBlock] & D0; + HP = VN[currentBlock] | ~(VP[currentBlock] | D0); + + X = (HP << 1) | carryHP; + carryHP = HP >> (BLOCK_SIZE-1); + + VN[currentBlock] = X & D0; + + temp = (HN << 1) | carryHN; + carryHN = HN >> (BLOCK_SIZE - 1); + + VP[currentBlock] = temp | ~(X | D0); + } + + // update score with the HP and HN values of the last block the last block + if (HP & scoreMask) + score--; + else if (HN & scoreMask) + score++; + ++pos; + } + + } // end compute score - long pattern + + return score; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_MYERS_IMPL_H_ diff --git a/seqan/align/global_alignment_specialized.h b/seqan/align/global_alignment_specialized.h new file mode 100644 index 0000000..1fa2a4d --- /dev/null +++ b/seqan/align/global_alignment_specialized.h @@ -0,0 +1,201 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Test for globalAlignmentScore() implementations that use Hirschberg and +// MyersBitVector, MyersHirschberg. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_SPECIALIZED_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_SPECIALIZED_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [Hirschberg] +// ---------------------------------------------------------------------------- + +template +TScoreValue globalAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + Hirschberg const & /*algorithmTag*/) +{ + SEQAN_ASSERT_EQ(scoreGapOpen(scoringScheme), scoreGapExtend(scoringScheme)); + return _globalAlignment(gapsH, gapsV, scoringScheme, Hirschberg()); +} + +template +TScoreValue globalAlignment(Align & align, + Score const & scoringScheme, + Hirschberg const & /*algorithmTag*/) +{ + SEQAN_ASSERT_EQ(length(rows(align)), 2u); + + return globalAlignment(row(align, 0), row(align, 1), scoringScheme, Hirschberg()); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [Myers-Hirschberg] +// ---------------------------------------------------------------------------- + +template +int globalAlignment(Align & align, + MyersHirschberg const & algorithmTag) +{ + SEQAN_ASSERT_EQ(length(rows(align)), 2u); + return _globalAlignment(row(align, 0), row(align, 1), algorithmTag); +} + +template +int globalAlignment(Gaps & gapsH, + Gaps & gapsV, + MyersHirschberg const & algorithmTag) +{ + return _globalAlignment(gapsH, gapsV, algorithmTag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [MyersBitVector] +// ---------------------------------------------------------------------------- + +template +int globalAlignment(Align & align, + MyersBitVector const & algorithmTag) +{ + SEQAN_ASSERT_EQ(length(rows(align)), 2u); + return _globalAlignment(row(align, 0), row(align, 1), algorithmTag); +} + +template +int globalAlignment(Gaps & gapsH, + Gaps & gapsV, + MyersBitVector const & algorithmTag) +{ + return _globalAlignment(gapsH, gapsV, algorithmTag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() [Hirschberg] +// ---------------------------------------------------------------------------- + +template +TScoreValue globalAlignmentScore(String const & seqH, + String const & seqV, + Score const & scoringScheme, + Hirschberg const & algorithmTag) +{ + Gaps const, ArrayGaps> gapsH(seqH); + Gaps const, ArrayGaps> gapsV(seqV); + return globalAlignment(gapsH, gapsV, scoringScheme, algorithmTag); +} + +template +TScoreValue globalAlignmentScore(StringSet const & strings, + Score const & scoringScheme, + Hirschberg const & algorithmTag) +{ + SEQAN_ASSERT_EQ(length(strings), 2u); + return globalAlignmentScore(strings[0], strings[1], scoringScheme, algorithmTag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() [Myers-Hirschberg] +// ---------------------------------------------------------------------------- + +template +int globalAlignmentScore(String const & seqH, + String const & seqV, + MyersHirschberg const & algorithmTag) +{ + Gaps const, ArrayGaps> gapsH(seqH); + Gaps const, ArrayGaps> gapsV(seqV); + return _globalAlignment(gapsH, gapsV, algorithmTag); +} + +template +int globalAlignmentScore(StringSet const & strings, + MyersHirschberg const & algorithmTag) +{ + SEQAN_ASSERT_EQ(length(strings), 2u); + return globalAlignmentScore(strings[0], strings[1], algorithmTag); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() [MyersBitVector] +// ---------------------------------------------------------------------------- + +template +int globalAlignmentScore(String const & seqH, + String const & seqV, + MyersBitVector const & algorithmTag) +{ + return _globalAlignmentScore(seqH, seqV, algorithmTag); +} + +template +int globalAlignmentScore(StringSet const & strings, + MyersBitVector const & algorithmTag) +{ + SEQAN_ASSERT_EQ(length(strings), 2u); + return _globalAlignmentScore(strings[0], strings[1], algorithmTag); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_SPECIALIZED_H_ diff --git a/seqan/align/global_alignment_unbanded.h b/seqan/align/global_alignment_unbanded.h new file mode 100644 index 0000000..a58c539 --- /dev/null +++ b/seqan/align/global_alignment_unbanded.h @@ -0,0 +1,841 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Global alignment interface for the unbanded Needleman-Wunsch and Gotoh +// algorithms. +// +// We define the interface functions pretty explicitly (versus just TAlign, +// TFragments etc.) so the candidates the compiler gives when resolution to +// the globalFunction() fails is actually meaningful. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_UNBANDED_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_UNBANDED_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +template +class Score; +template +class Graph; +template +struct Alignment; +template +class Fragment; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function globalAlignment() +// ---------------------------------------------------------------------------- + +/*! + * @fn globalAlignment + * @headerfile + * @brief Computes the best global pairwise alignment. + * + * @signature TScoreVal globalAlignment(align, scoringScheme, [alignConfig,] [lowerDiag, upperDiag,] [algorithmTag]); + * @signature TScoreVal globalAlignment(gapsH, gapsV, scoringScheme, [alignConfig,] [lowerDiag, upperDiag,] [algorithmTag]); + * @signature TScoreVal globalAlignment(frags, strings, scoringScheme, [alignConfig,] [lowerDiag, upperDiag,] [algorithmTag]); + * @signature TScoreVal globalAlignment(alignGraph, scoringScheme, [alignConfig,] [lowerDiag, upperDiag,] [algorithmTag]); + * + * @param[in,out] align The @link Align @endlink object to use for storing the pairwise alignment. + * @param[in,out] gapsH The @link Gaps @endlink object for the first row (horizontal in the DP matrix). + * @param[in,out] gapsV The @link Gaps @endlink object for the second row (vertical in the DP matrix). + * @param[in,out] frags String of @link Fragment @endlink objects to store alignment in. + * @param[in] strings StringSet of length two with the strings to align. + * @param[in,out] alignGraph Alignment Graph for the resulting alignment. Must be initialized with two strings. + * @param[in] scoringScheme The @link Score scoring scheme @endlink to use for the alignment. Note that + * the user is responsible for ensuring that the scoring scheme is compatible with algorithmTag. + * @param[in] alignConfig @link AlignConfig @endlink instance to use for the alignment configuration. + * @param[in] lowerDiag Optional lower diagonal (int). + * @param[in] upperDiag Optional upper diagonal (int). + * @param[in] algorithmTag Tag to select the alignment algorithm (see @link AlignmentAlgorithmTags @endlink). + * + * @return TScoreVal Score value of the resulting alignment (Metafunction: @link Score#Value @endlink of + * the type of scoringScheme). + * + * There exist multiple overloads for this function with four configuration dimensions. + * + * First, you can select whether begin and end gaps are free in either sequence using alignConfig. + * + * Second, you can select the type of the target storing the alignment. This can be either an @link Align @endlink + * object, two @link Gaps @endlink objects, a @link AlignmentGraph @endlink, or a string of @link Fragment @endlink + * objects. @link Align @endlink objects provide an interface to tabular alignments with the restriction of all rows + * having the same type. Using two @link Gaps @endlink objects has the advantage that you an align sequences with + * different types, for example @link DnaString @endlink and @link Dna5String @endlink. @link AlignmentGraph Alignment + * Graphs @endlink provide a graph-based representation of segment-based colinear alignments. Using @link Fragment + * @endlink strings is useful for collecting many pairwise alignments, for example in the construction of @link + * AlignmentGraph Alignment Graphs @endlink for multiple-sequence alignments (MSA). + * + * Third, you can optionally give a band for the alignment using lowerDiag and upperDiag. The center + * diagonal has index 0, the ith diagonal below has index -i, the ith above has + * index i. + * + * Fourth, you can select the algorithm to use with algorithmTag. This can be one of @link + * AlignmentAlgorithmTags#NeedlemanWunsch @endlink and @link AlignmentAlgorithmTags#Gotoh @endlink. The + * Needleman-Wunsch algorithm supports scoring schemes with linear gap costs only while Gotoh's algorithm also allows + * affine gap costs. + * + * The available alignment algorithms all have some restrictions. Gotoh's algorithm can handle arbitrary substitution + * and affine gap scores. Needleman-Wunsch is limited to linear gap scores. The implementation of Hirschberg's + * algorithm is further limited that it does not support alignConfig objects or banding. The implementation of + * the Myers-Hirschberg algorithm further limits this to only support edit distance (as scores, matches are scored with + * 0, mismatches are scored with -1). + * + * The examples below show some common use cases. + * + * @section Examples + * + * Global alignment of two sequences using an @link Align @endlink object and + * the Needleman-Wunsch algorithm. + * + * @include demos/dox/align/global_alignment_unbanded.cpp + * + * The output is as follows: + * + * @include demos/dox/align/global_alignment_unbanded.cpp.stdout + * + * Global banded alignment of two sequences using two @link Gaps @endlink objects and the Gotoh algorithm. + * + * @include demos/dox/align/global_alignment_banded.cpp + * + * The output is as follows: + * + * @include demos/dox/align/global_alignment_banded.cpp.stdout + * + * https://seqan.readthedocs.io/en/develop/Tutorial/Algorithms/Alignment/PairwiseSequenceAlignment.html + * + * @section References + * + *
    + *
  • Needleman SB, Wunsch CD: A general method applicable to the search for similarities in the amino acid sequence + * of two proteins. J Mol Biol 1970, 48(3): 443-53.
  • + *
  • Gotoh O: An improved algorithm for matching biological sequences. J Mol Biol 1982, 162(3):705-8
  • + *
+ * + * @see localAlignment + * @see globalAlignmentScore + * @see AlignmentAlgorithmTags + */ + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [unbanded, Align] +// ---------------------------------------------------------------------------- + +template +TScoreValue globalAlignment(Align & align, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + TAlgoTag const & /*algoTag*/) +{ + typedef Align TAlign; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + String trace; + TScoreValue res; + DPScoutState_ dpScoutState; + res = _setUpAndRunAlignment(trace, dpScoutState, source(row(align, 0)), source(row(align, 1)), scoringScheme, + TAlignConfig2(), TGapModel()); + + _adaptTraceSegmentsTo(row(align, 0), row(align, 1), trace); + return res; +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignment(Align & align, + Score const & scoringScheme, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignment(align, scoringScheme, alignConfig, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignment(Align & align, + Score const & scoringScheme, + AlignConfig const & alignConfig) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignment(align, scoringScheme, alignConfig, NeedlemanWunsch()); + else + return globalAlignment(align, scoringScheme, alignConfig, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignment(Align & align, + Score const & scoringScheme) +{ + AlignConfig<> alignConfig; + return globalAlignment(align, scoringScheme, alignConfig); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [unbanded, Gaps] +// ---------------------------------------------------------------------------- + +template +TScoreValue globalAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + TAlgoTag const & /*algoTag*/) +{ + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + String traceSegments; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(traceSegments, dpScoutState, source(gapsH), source(gapsV), scoringScheme, + TAlignConfig2(), TGapModel()); + _adaptTraceSegmentsTo(gapsH, gapsV, traceSegments); + return res; +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignment(gapsH, gapsV, scoringScheme, alignConfig, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + AlignConfig const & alignConfig) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignment(gapsH, gapsV, scoringScheme, alignConfig, NeedlemanWunsch()); + else + return globalAlignment(gapsH, gapsV, scoringScheme, alignConfig, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme) +{ + AlignConfig<> alignConfig; + return globalAlignment(gapsH, gapsV, scoringScheme, alignConfig); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [unbanded, Graph >] +// ---------------------------------------------------------------------------- + +// Full interface. +template +TScoreValue globalAlignment(Graph > & alignmentGraph, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + TAlgoTag const & /*algoTag*/) +{ + typedef Graph > TGraph; + typedef typename Position::Type TPosition; + typedef typename Size::Type TSize; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + String traceSegments; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(traceSegments, dpScoutState, value(stringSet(alignmentGraph), 0), + value(stringSet(alignmentGraph), 1), scoringScheme, TAlignConfig2(), + TGapModel()); + + _adaptTraceSegmentsTo(alignmentGraph, positionToId(stringSet(alignmentGraph), 0), + positionToId(stringSet(alignmentGraph), 1), traceSegments); + return res; +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignment(Graph > & alignmentGraph, + Score const & scoringScheme, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignment(alignmentGraph, scoringScheme, alignConfig, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignment(Graph > & alignmentGraph, + Score const & scoringScheme, + AlignConfig const & alignConfig) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignment(alignmentGraph, scoringScheme, alignConfig, NeedlemanWunsch()); + else + return globalAlignment(alignmentGraph, scoringScheme, alignConfig, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignment(Graph > & alignmentGraph, + Score const & scoringScheme) +{ + AlignConfig<> alignConfig; + return globalAlignment(alignmentGraph, scoringScheme, alignConfig); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [unbanded, String >] +// ---------------------------------------------------------------------------- + +// Full interface. +template +TScoreValue globalAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + TAlgoTag const & /*algoTag*/) +{ + typedef String, TStringSpec> TFragments; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + String traceSegments; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(traceSegments, dpScoutState, value(strings, 0), value(strings, 1), + scoringScheme, TAlignConfig2(), TGapModel()); + + _adaptTraceSegmentsTo(fragmentString, positionToId(strings, 0), positionToId(strings, 1), traceSegments); + return res; +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignment(fragmentString, strings, scoringScheme, alignConfig, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme, + AlignConfig const & alignConfig) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignment(fragmentString, strings, scoringScheme, alignConfig, NeedlemanWunsch()); + else + return globalAlignment(fragmentString, strings, scoringScheme, alignConfig, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme) +{ + AlignConfig<> alignConfig; + return globalAlignment(fragmentString, strings, scoringScheme, alignConfig); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() +// ---------------------------------------------------------------------------- + +/*! + * @fn globalAlignmentScore + * @headerfile + * @brief Computes the best global pairwise alignment score. + * + * @signature TScoreVal globalAlignmentScore(seqH, seqV, scoringScheme[, alignConfig][, lowerDiag, upperDiag][, algorithmTag]); + * @signature TScoreVal globalAlignmentScore(strings, scoringScheme[, alignConfig][, lowerDiag, upperDiag][, algorithmTag]); + * @signature TScoreVal globalAlignmentScore(seqH, seqV, {MyersBitVector | MyersHirschberg}); + * @signature TScoreVal globalAlignmentScore(strings, {MyersBitVector | MyersHirschberg}); + * + * @param[in] seqH Horizontal gapped sequence in alignment matrix. Types: String + * @param[in] seqV Vertical gapped sequence in alignment matrix. Types: String + * @param[in] strings A @link StringSet @endlink containing two sequences. Type: StringSet. + * @param[in] alignConfig The @link AlignConfig @endlink to use for the alignment. Type: AlignConfig + * @param[in] scoringScheme The scoring scheme to use for the alignment. Note that the user is responsible for ensuring + * that the scoring scheme is compatible with algorithmTag. Type: @link Score @endlink. + * @param[in] lowerDiag Optional lower diagonal. Types: int + * @param[in] upperDiag Optional upper diagonal. Types: int + * @param[in] algorithmTag The Tag for picking the alignment algorithm. Types: @link PairwiseLocalAlignmentAlgorithms + * @endlink. + * + * @return TScoreVal Score value of the resulting alignment (Metafunction: @link Score#Value @endlink of + * the type of scoringScheme). + * + * This function does not perform the (linear time) traceback step after the (mostly quadratic time) dynamic programming + * step. Note that Myers' bit-vector algorithm does not compute an alignment (only in the Myers-Hirschberg variant) but + * scores can be computed using globalAlignmentScore. + * + * The same limitations to algorithms as in @link globalAlignment @endlink apply. Furthermore, the + * MyersBitVector and MyersHirschberg variants can only be used without any other parameter. + * + * @see https://seqan.readthedocs.io/en/develop/Tutorial/Algorithms/Alignment/PairwiseSequenceAlignment.html + * @see globalAlignment + */ + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() [unbanded, 2 Strings] +// ---------------------------------------------------------------------------- + +template +TScoreValue globalAlignmentScore(TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps, TracebackOff> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + DPScoutState_ dpScoutState; + String > traceSegments; // Dummy segments. + return _setUpAndRunAlignment(traceSegments, dpScoutState, seqH, seqV, scoringScheme, TAlignConfig2(), TGapModel()); +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignmentScore(TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(seqH, seqV, scoringScheme, alignConfig, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignmentScore(TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme, + AlignConfig const & alignConfig) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignmentScore(seqH, seqV, scoringScheme, alignConfig, NeedlemanWunsch()); + else + return globalAlignmentScore(seqH, seqV, scoringScheme, alignConfig, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignmentScore(TSequenceH const & seqH, + TSequenceV const & seqV, + Score const & scoringScheme) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(seqH, seqV, scoringScheme, alignConfig); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() [unbanded, StringSet] +// ---------------------------------------------------------------------------- + +template +TScoreValue globalAlignmentScore(StringSet const & strings, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps, TracebackOff> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + SEQAN_ASSERT_EQ(length(strings), 2u); + + DPScoutState_ dpScoutState; + String > traceSegments; // Dummy segments. + return _setUpAndRunAlignment(traceSegments, dpScoutState, strings[0], strings[1], scoringScheme, TAlignConfig2(), + TGapModel()); +} + +// Interface without AlignConfig<>. +template +TScoreValue globalAlignmentScore(StringSet const & strings, + Score const & scoringScheme, + TAlgoTag const & algoTag) +{ + SEQAN_ASSERT_EQ(length(strings), 2u); + + AlignConfig<> alignConfig; + return globalAlignmentScore(strings[0], strings[1], scoringScheme, alignConfig, algoTag); +} + +// Interface without algorithm tag. +template +TScoreValue globalAlignmentScore(StringSet const & strings, + Score const & scoringScheme, + AlignConfig const & alignConfig) +{ + SEQAN_ASSERT_EQ(length(strings), 2u); + + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignmentScore(strings[0], strings[1], scoringScheme, alignConfig, NeedlemanWunsch()); + else + return globalAlignmentScore(strings[0], strings[1], scoringScheme, alignConfig, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +TScoreValue globalAlignmentScore(StringSet const & strings, + Score const & scoringScheme) +{ + SEQAN_ASSERT_EQ(length(strings), 2u); + + AlignConfig<> alignConfig; + return globalAlignmentScore(strings[0], strings[1], scoringScheme, alignConfig); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignmentScore() [unbanded, SIMD version, 2x StringSet] +// ---------------------------------------------------------------------------- + +template +String globalAlignmentScore(StringSet const & stringsH, + StringSet const & stringsV, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + TAlgoTag const & /*algoTag*/) +{ + SEQAN_ASSERT_EQ(length(stringsH), length(stringsV)); + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps, TracebackOff> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + return _alignWrapper(stringsH, stringsV, scoringScheme, TAlignConfig2(), TGapModel()); +} + +// Interface without AlignConfig<>. +template +String globalAlignmentScore(StringSet const & stringsH, + StringSet const & stringsV, + Score const & scoringScheme, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(stringsH, stringsV, scoringScheme, alignConfig, algoTag); +} + +// Interface without algorithm tag. +template +String globalAlignmentScore(StringSet const & stringsH, + StringSet const & stringsV, + Score const & scoringScheme, + AlignConfig const & alignConfig) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignmentScore(stringsH, stringsV, scoringScheme, alignConfig, NeedlemanWunsch()); + else + return globalAlignmentScore(stringsH, stringsV, scoringScheme, alignConfig, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +String globalAlignmentScore(StringSet const & stringsH, + StringSet const & stringsV, + Score const & scoringScheme) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(stringsH, stringsV, scoringScheme, alignConfig); +} + +// -------------------------------------------------------------------------------- +// Function globalAlignmentScore() [unbanded, SIMD version, String vs StringSet] +// -------------------------------------------------------------------------------- +template +String globalAlignmentScore(TString1 const & stringH, + StringSet const & stringsV, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps, TracebackOff> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + return _alignWrapper(stringH, stringsV, scoringScheme, TAlignConfig2(), TGapModel()); +} + +// Interface without AlignConfig<>. +template +String globalAlignmentScore(TString1 const & stringH, + StringSet const & stringsV, + Score const & scoringScheme, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(stringH, stringsV, scoringScheme, alignConfig, algoTag); +} + +// Interface without algorithm tag. +template +String globalAlignmentScore(TString1 const & stringH, + StringSet const & stringsV, + Score const & scoringScheme, + AlignConfig const & alignConfig) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignmentScore(stringH, stringsV, scoringScheme, alignConfig, NeedlemanWunsch()); + else + return globalAlignmentScore(stringH, stringsV, scoringScheme, alignConfig, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +String globalAlignmentScore(TString1 const & stringH, + StringSet const & stringsV, + Score const & scoringScheme) +{ + AlignConfig<> alignConfig; + return globalAlignmentScore(stringH, stringsV, scoringScheme, alignConfig); +} + +// ============================================================================ +// Many-vs-Many align interfaces. +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [unbanded, SIMD version, GapsH, GapsV] +// ---------------------------------------------------------------------------- + +template +inline auto +globalAlignment(StringSet, TSetSpecH> & gapSeqSetH, + StringSet, TSetSpecV> & gapSeqSetV, + Score const & scoringScheme, + AlignConfig const & /*alignConfig*/, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig TAlignConfig; + typedef typename SubstituteAlignConfig_::Type TFreeEndGaps; + typedef AlignConfig2, TFreeEndGaps> TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + return _alignWrapper(gapSeqSetH, gapSeqSetV, scoringScheme, TAlignConfig2(), TGapModel()); +} + +// ---------------------------------------------------------------------------- +// Function globalAlignment() [unbanded, SIMD version, StringSet] +// ---------------------------------------------------------------------------- + +template +String globalAlignment(StringSet > & alignSet, + Score const & scoringScheme, + AlignConfig const & alignConfig, + TAlgoTag const & algoTag) +{ + typedef Align TAlign; + typedef typename Row::Type TGapSequence; + + StringSet > gapSetH; + StringSet > gapSetV; + reserve(gapSetH, length(alignSet)); + reserve(gapSetV, length(alignSet)); + + for (auto & align : alignSet) + { + appendValue(gapSetH, row(align, 0)); + appendValue(gapSetV, row(align, 1)); + } + + return globalAlignment(gapSetH, gapSetV, scoringScheme, alignConfig, algoTag); +} + +// Interface without AlignConfig<>. +template +String globalAlignment(StringSet > & align, + Score const & scoringScheme, + TAlgoTag const & algoTag) +{ + AlignConfig<> alignConfig; + return globalAlignment(align, scoringScheme, alignConfig, algoTag); +} + +// Interface without algorithm tag. +template +String globalAlignment(StringSet > & align, + Score const & scoringScheme, + AlignConfig const & alignConfig) +{ + if (scoreGapOpen(scoringScheme) == scoreGapExtend(scoringScheme)) + return globalAlignment(align, scoringScheme, alignConfig, NeedlemanWunsch()); + else + return globalAlignment(align, scoringScheme, alignConfig, Gotoh()); +} + +// Interface without AlignConfig<> and algorithm tag. +template +String globalAlignment(StringSet > & align, + Score const & scoringScheme) +{ + AlignConfig<> alignConfig; + return globalAlignment(align, scoringScheme, alignConfig); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_UNBANDED_H_ diff --git a/seqan/align/local_alignment_banded.h b/seqan/align/local_alignment_banded.h new file mode 100644 index 0000000..8edcfd5 --- /dev/null +++ b/seqan/align/local_alignment_banded.h @@ -0,0 +1,298 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Interface functions for banded local alignment. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_BANDED_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_BANDED_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function localAlignment() [banded, Align] +// ---------------------------------------------------------------------------- + +template +TScoreValue localAlignment(Align & align, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TTag const & tag) +{ + typedef Align TAlign; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig2, FreeEndGaps_<> > TAlignConfig2; + + SEQAN_ASSERT_EQ(length(rows(align)), 2u); + + String trace; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, source(row(align, 0)), source(row(align, 1)), + scoringScheme, TAlignConfig2(lowerDiag, upperDiag), tag); + + _adaptTraceSegmentsTo(row(align, 0), row(align, 1), trace); + return res; +} + +template +TScoreValue localAlignment(Align & align, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + SEQAN_ASSERT(length(rows(align)) == 2u); + if (_usesAffineGaps(scoringScheme, source(row(align, 0)), source(row(align, 1)))) + return localAlignment(align, scoringScheme, lowerDiag, upperDiag, AffineGaps()); + else + return localAlignment(align, scoringScheme, lowerDiag, upperDiag, LinearGaps()); +} + +// ---------------------------------------------------------------------------- +// Function localAlignment() [banded, Gaps] +// ---------------------------------------------------------------------------- + +template +TScoreValue localAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TTag const & tag) +{ + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig2, FreeEndGaps_<> > TAlignConfig2; + + String trace; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, source(gapsH), source(gapsV), scoringScheme, + TAlignConfig2(lowerDiag, upperDiag), tag); + _adaptTraceSegmentsTo(gapsH, gapsV, trace); + return res; +} + +template +TScoreValue localAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + if (_usesAffineGaps(scoringScheme, source(gapsH), source(gapsV))) + return localAlignment(gapsH, gapsV, scoringScheme, lowerDiag, upperDiag, AffineGaps()); + else + return localAlignment(gapsH, gapsV, scoringScheme, lowerDiag, upperDiag, LinearGaps()); +} + +// ---------------------------------------------------------------------------- +// Function localAlignment() [banded, Graph >] +// ---------------------------------------------------------------------------- + +template +TScoreValue localAlignment(Graph > & alignmentGraph, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TTag const & tag) +{ + typedef Graph > TGraph; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig2, FreeEndGaps_<> > TAlignConfig2; + + String trace; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, value(stringSet(alignmentGraph), 0), + value(stringSet(alignmentGraph), 1), scoringScheme, + TAlignConfig2(lowerDiag, upperDiag), tag); + + _adaptTraceSegmentsTo(alignmentGraph, positionToId(stringSet(alignmentGraph), 0), + positionToId(stringSet(alignmentGraph), 1), trace); + return res; +} + +template +TScoreValue localAlignment(Graph > & alignmentGraph, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + SEQAN_ASSERT(length(stringSet(alignmentGraph)) == 2u); + + if (_usesAffineGaps(scoringScheme, stringSet(alignmentGraph)[0], stringSet(alignmentGraph)[1])) + return localAlignment(alignmentGraph, scoringScheme, lowerDiag, upperDiag, AffineGaps()); + else + return localAlignment(alignmentGraph, scoringScheme, lowerDiag, upperDiag, LinearGaps()); +} + +// ---------------------------------------------------------------------------- +// Function localAlignment() [banded, String >] +// ---------------------------------------------------------------------------- + +// Full interface. +template +TScoreValue localAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme, + int lowerDiag, + int upperDiag, + TTag const & tag) +{ + typedef String, TStringSpec> TFragments; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig2, FreeEndGaps_<> > TAlignConfig2; + + String trace; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, value(strings, 0), value(strings, 1), scoringScheme, + TAlignConfig2(lowerDiag, upperDiag), tag); + _adaptTraceSegmentsTo(fragmentString, positionToId(strings, 0), positionToId(strings, 1), trace); + return res; +} + +template +TScoreValue localAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme, + int lowerDiag, + int upperDiag) +{ + SEQAN_ASSERT(length(strings) == 2u); + + if (_usesAffineGaps(scoringScheme, strings[0], strings[1])) + return localAlignment(fragmentString, strings, scoringScheme, lowerDiag, upperDiag, AffineGaps()); + else + return localAlignment(fragmentString, strings, scoringScheme, lowerDiag, upperDiag, LinearGaps()); +} + +// ============================================================================ +// Many-vs-Many align interfaces. +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function localAlignment() [banded, SIMD version, GapsH, GapsV] +// ---------------------------------------------------------------------------- + +template +inline auto +localAlignment(StringSet & gapSeqSetH, + StringSet & gapSeqSetV, + Score const & scoringScheme, + int const lowerDiag, + int const upperDiag, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig2, FreeEndGaps_<> > TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + return _alignWrapper(gapSeqSetH, gapSeqSetV, scoringScheme, TAlignConfig2(lowerDiag, upperDiag), TGapModel()); +} + +// ---------------------------------------------------------------------------- +// Function localAlignment() [banded, SIMD version, StringSet] +// ---------------------------------------------------------------------------- + +template +inline String +localAlignment(StringSet, TSetSpec> & alignSet, + Score const & scoringScheme, + int const lowerDiag, + int const upperDiag, + TAlgoTag const & algoTag) +{ + typedef Align TAlign; + typedef typename Row::Type TGapSequence; + + StringSet > gapSetH; + StringSet > gapSetV; + reserve(gapSetH, length(alignSet)); + reserve(gapSetV, length(alignSet)); + + for (auto & align : alignSet) + { + appendValue(gapSetH, row(align, 0)); + appendValue(gapSetV, row(align, 1)); + } + + return localAlignment(gapSetH, gapSetV, scoringScheme, lowerDiag, upperDiag, algoTag); +} + +template +String localAlignment(StringSet > & align, + Score const & scoringScheme, + int lowerDiag, int upperDiag) +{ + if (_usesAffineGaps(scoringScheme, source(row(align[0], 0)), source(row(align[0], 1)))) + return localAlignment(align, scoringScheme, lowerDiag, upperDiag, AffineGaps()); + else + return localAlignment(align, scoringScheme, lowerDiag, upperDiag, LinearGaps()); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_BANDED_H_ diff --git a/seqan/align/local_alignment_banded_waterman_eggert_impl.h b/seqan/align/local_alignment_banded_waterman_eggert_impl.h new file mode 100644 index 0000000..3f42d50 --- /dev/null +++ b/seqan/align/local_alignment_banded_waterman_eggert_impl.h @@ -0,0 +1,601 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// Author: Anne-Katrin Emde +// Author: Tobias Rausch +// Author: Birte Kehr +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_BANDED_WATERMAN_EGGERT_IMPL_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_BANDED_WATERMAN_EGGERT_IMPL_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// Legacy. +struct BandedWatermanEggert_; +typedef Tag BandedWatermanEggert; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _alignBandedSmithWaterman() +// ---------------------------------------------------------------------------- + +template +inline TScoreValue +_alignBandedSmithWaterman(LocalAlignmentFinder& finder, + TSequenceH const & seqH, + TSequenceV const & seqV, + TScore const& sc, + TScoreValue const cutoff, + TDiagonal const diagL, + TDiagonal const diagU) { + typedef typename Size::Type TSize; + typedef LocalAlignmentFinder TFinder; + + // Initialization + TSequenceH const& str1 = seqH; + TSequenceV const& str2 = seqV; + TSize len1 = length(str1); + TSize len2 = length(str2); + + TSize lo_row = (diagU <= 0) ? static_cast(-diagU) : 0; + TSize hi_row = len2;// + 1; + if (len1 - diagL < hi_row) hi_row = static_cast(len1 - diagL); + + TSize height = hi_row - lo_row + 1; + TSize diagonalWidth = (TSize) (diagU - diagL + 1); + + TSize actualCol, actualRow; + TScoreValue verti_val, hori_val; + + // Initialize iterators + typename TFinder::TMatrixIterator matIt = begin(finder.matrix); // Iterator in current row + goNext(matIt, 1); + typename TFinder::TMatrixIterator matIt2 = begin(finder.matrix); // Iterator in previous row (for diagonal and vertical value) + + for (TSize row = 1; row < height; ++row) { + actualRow = row + lo_row; + hori_val = 0; + + for (TSize col = 0; col < diagonalWidth; ++col, ++matIt) { + // handle begin and end triangle of band + if ((int)col + diagL + (int)actualRow < 0) {++matIt2; continue;} + actualCol = static_cast(col + diagL + actualRow); + if (actualCol > len1) {++matIt2; continue;} + + if (actualCol != 0) { + // Get the new maximum for diagonal + *matIt = *matIt2 + + score(const_cast(sc), sequenceEntryForScore(sc, str1, (int) actualCol - 1), + sequenceEntryForScore(sc, str2, (int) actualRow - 1)); + + ++matIt2; + + // Get the new maximum for vertical + if (col < diagonalWidth - 1) { + verti_val = *matIt2 + + scoreGapExtendVertical(sc, sequenceEntryForScore(sc, str1, (int) actualCol - 1), + sequenceEntryForScore(sc, str2, (int) actualRow - 1)); + if (verti_val > *matIt) { + *matIt = verti_val; + } + } + + // Get the new maximum for horizontal + if (col > 0) { + hori_val = hori_val + + scoreGapExtendHorizontal(sc, sequenceEntryForScore(sc, str1, (int) actualCol - 1), + sequenceEntryForScore(sc, str2, (int) actualRow - 1)); + if (hori_val > *matIt) { + *matIt = hori_val; + } + } + + // Check if new maximum is greater than 0 + if (0 > *matIt) { + *matIt = 0; + } + + // Record the new best score + if (*matIt >= cutoff) { + push(finder.pQ, ScoreAndID(*matIt, position(matIt))); + } + } else { + // First column (*matIt = 0) + ++matIt2; + } + hori_val = *matIt; + } + } + // // Debug code + // std::cerr << std::endl; + //for(TSize i= 0; i 0) std::cerr << " " << str2[i-1] << std::endl; + // else std::cerr << std::endl; + //} + // if(length(finder.pQ) > 0) std::cerr << "Max score: " << top(finder.pQ).value_ << std::endl; + + if(!empty(finder.pQ)) { + finder.bestEndPos = top(finder.pQ).id_; + return top(finder.pQ).value_; + } else { + return 0; + } +} + +// ---------------------------------------------------------------------------- +// Helper Function _alignBandedSmithWatermanDeclump() +// ---------------------------------------------------------------------------- + +template +inline void +_setForbiddenCell(String& forbidden, + TSize len1, + TSize len2, + TSize numRows) +{ + forbidden[(len1 - 1)*numRows + (len2 - 1)] = true; +} + + +template +inline void +_setForbiddenCell(Nothing&, + TSize, + TSize, + TSize) +{ +} + +// ---------------------------------------------------------------------------- +// Function _alignBandedSmithWatermanDeclump() +// ---------------------------------------------------------------------------- + +template +inline void +_alignBandedSmithWatermanDeclump(LocalAlignmentFinder& finder, + TSequenceH const & seqH, + TSequenceV const & seqV, + TScore const& sc, + TScoreValue const cutoff, + TDiagonal const diagL, + TDiagonal const diagU) +{ + typedef typename Size::Type TSize; + typedef LocalAlignmentFinder TFinder; + typedef unsigned char TTraceValue; + + // Traceback values + TTraceValue Diagonal = 0; TTraceValue Horizontal = 1; TTraceValue Vertical = 2; + + TSequenceH const& str1 = seqH; + TSequenceV const& str2 = seqV; + TSize len1 = length(str1); + + TSize diagonalWidth = (TSize) (diagU - diagL + 1); + TSize lo_row = (diagU <= 0) ? static_cast(-diagU) : 0; + TSize hi_row = length(seqV);// + 1; + if (len1 - diagL < hi_row) hi_row = static_cast(len1 - diagL); + TSize height = hi_row - lo_row + 1; + + TSize actualRow, actualCol; + //TSize row, col; + + // Initialize iterators + typename TFinder::TMatrixIterator matIt = iter(finder.matrix, finder.bestBeginPos); + typename TFinder::TMatrixIterator matIt2; + + // Initialize column boundaries + TSize minCol = diagonalWidth, newMinCol = diagonalWidth; + TSize maxCol = 0, newMaxCol = 0; + TSize row = coordinate(matIt, 1); + TSize col = coordinate(matIt, 0); + TSize traceCol = col; + + matIt -= col; + + // Initialize position in trace + TSize tracePos = length(finder.trace.sizes); + while (tracePos > 0 && finder.trace.tvs[tracePos-1] != Diagonal) --tracePos; + if (tracePos == 0) return; + TSize traceSize = finder.trace.sizes[tracePos-1]; + TTraceValue traceValue = finder.trace.tvs[tracePos-1]; + + // iterate over rows + while((row < height) && ((maxCol > minCol) || (tracePos > 0))) { + actualRow = row + lo_row; + + // make sure that all matrix entries of trace are re-calculated and set to forbidden + while (traceSize == 0 && tracePos > 1) { + // determine next trace direction + --tracePos; + traceValue = finder.trace.tvs[tracePos-1]; + if (traceValue == Horizontal) { + traceCol += finder.trace.sizes[tracePos-1]; + } else { + traceSize = finder.trace.sizes[tracePos-1]; + } + } + if (tracePos > 0) { + // follow the trace in the current row + if (traceValue == Diagonal) { + --traceSize; + _setForbiddenCell(finder.forbidden, row+1, traceCol+1, diagonalWidth); + minCol = _min(minCol, traceCol); + maxCol = _max(maxCol, traceCol+1); + } else if (traceValue == Vertical) { + if (traceCol > 0) --traceCol; + --traceSize; + } + + if (traceCol >= maxCol) { + maxCol = traceCol + 1; + } + } + + // iterate over columns that have to be re-calculated + if (maxCol > minCol) { + col = minCol; + matIt += col; + matIt2 = matIt - diagonalWidth; + while (col < maxCol) { + actualCol = static_cast(col + diagL + actualRow); + if (actualCol > len1) break; + + TScoreValue newVal = 0; + + // diagonal + if (!value(finder.forbidden, position(matIt))) { + newVal = _max(newVal, *matIt2 + score(sc, sequenceEntryForScore(sc, str1, (int)actualCol-1), + sequenceEntryForScore(sc, str2, (int)actualRow-1))); + } + ++matIt2; + + // horizontal + if (col > 0) { + newVal = _max(newVal, *(matIt-1) + + scoreGapExtendHorizontal(sc, sequenceEntryForScore(sc, str1, (int) actualCol-1), + sequenceEntryForScore(sc, str2, (int)actualRow-1))); + } + + // vertical + if (col+1 < maxCol) { + newVal = _max(newVal, *matIt2 + + scoreGapExtendVertical(sc, sequenceEntryForScore(sc, str1, (int)actualCol-1), + sequenceEntryForScore(sc, str2, (int)actualRow-1))); + } + + if (newVal != *matIt) { + // matrix entry changed + *matIt = newVal; + maxCol = _min(_max(maxCol, col+2), diagonalWidth); + newMaxCol = _max(newMaxCol, col+1); + newMinCol = ((col != 0) ? _min(newMinCol, col-1) : 0); + + // Record the new best score + if (newVal >= cutoff) { + push(finder.pQ, ScoreAndID(newVal, position(matIt))); + } + } else { + // matrix entry did not change + if (col == minCol) { + ++minCol; + } + } + ++col; + ++matIt; + } + matIt += diagonalWidth - col; + } else { + matIt += diagonalWidth; + } + + minCol = _max((TSize)0, newMinCol); + maxCol = _min(diagonalWidth, newMaxCol); + newMinCol = diagonalWidth; + newMaxCol = 0; + + ++row; + } + // // Debug code + // std::cerr << std::endl; + // for (TSize i = 0; i < height; ++i) { + // for(TSize j = 0; j < diagonalWidth; ++j) { + // std::cerr << value(finder.matrix, j, i) << ','; + // } + //if (i > 0) std::cerr << " " << str2[i-1] << " "; + //else std::cerr << " "; + // for (TSize j= 0; j 0) std::cerr << " " << str2[i-1] << std::endl; + //else std::cerr << std::endl; + // } +} + +// ---------------------------------------------------------------------------- +// Function _alignBandedSmithWatermanTrace() +// ---------------------------------------------------------------------------- + +template +inline Pair > +_alignBandedSmithWatermanTrace(LocalAlignmentFinder & finder, + TSequenceH const & seqH, + TSequenceV const & seqV, + TId id1, + TId id2, + TScore& sc, + TDiagonal diagL, + TDiagonal diagU) +{ + typedef LocalAlignmentFinder TFinder; + typedef typename Size::Type TSize; + typedef unsigned char TTraceValue; + + clear(finder.trace.sizes); + clear(finder.trace.tvs); + + // Traceback values + TTraceValue Diagonal = 0; TTraceValue Horizontal = 1; TTraceValue Vertical = 2; TTraceValue Stop = 3; + + // Initialization + TSequenceH const& str1 = seqH; + TSequenceV const& str2 = seqV; + TSize len1 = length(str1); + TSize len2 = length(str2); + + TSize lo_row = (diagU <= 0) ? static_cast(-diagU) : 0; + //TSize diagonalWidth = static_cast(diagU - diagL + 1); + + // Start the trace from the cell with the max value + typename TFinder::TMatrixIterator matIt = iter(finder.matrix, finder.bestEndPos); + typename TFinder::TMatrixIterator matIt2 = iter(finder.matrix, finder.bestEndPos); + goPrevious(matIt2, 1); + + TSize row = coordinate(matIt, 1); + TSize col = coordinate(matIt, 0); + TSize endRow = row + lo_row; + TSize endCol = static_cast(col + diagL + endRow); + + TSize actualRow = row + lo_row; + TSize actualCol = static_cast(col + diagL + actualRow); + if ((actualCol == 0) || (actualRow == 0)) + return Pair >(); + + if (actualCol < len1) _alignTracePrint(finder.trace, seqH, seqV, id1, actualCol, id2, actualRow, len1 - actualCol, Horizontal); + if (actualRow < len2) _alignTracePrint(finder.trace, seqH, seqV, id1, actualCol, id2, actualRow, len2 - actualRow, Vertical); + + TTraceValue traceValue = Stop; + TTraceValue nextTraceValue = Horizontal; + TSize segLen = 0; + + while (nextTraceValue != Stop) { + traceValue = nextTraceValue; + if (*matIt == 0) { + nextTraceValue = Stop; + } + else if (*matIt == *matIt2 + + score(const_cast(sc), sequenceEntryForScore(sc, str1, (int)actualCol-1), + sequenceEntryForScore(sc, str2, (int)actualRow-1))) + { + nextTraceValue = Diagonal; + --actualRow; --actualCol; + --row; + goPrevious(matIt, 1); + goPrevious(matIt2, 1); + } else if (*matIt == *(matIt2+1) + + scoreGapExtendVertical(sc, sequenceEntryForScore(sc, str1, (int)actualCol-1), + sequenceEntryForScore(sc, str2, (int)actualRow-1))) + { + nextTraceValue = Vertical; + --actualRow; + --row; ++col; + goPrevious(matIt, 1); goNext(matIt, 0); + goPrevious(matIt2, 1); goNext(matIt2, 0); + } else { + SEQAN_ASSERT_EQ(*matIt, *(matIt-1) + + scoreGapExtendHorizontal(sc, sequenceEntryForScore(sc, str1, (int) actualCol-1), + sequenceEntryForScore(sc, str2, (int) actualRow-1))); + nextTraceValue = Horizontal; + --actualCol; + --col; + goPrevious(matIt, 0); + goPrevious(matIt2, 0); + } + if (traceValue == nextTraceValue) { + ++segLen; + } else { + _alignTracePrint(finder.trace, seqH, seqV, id1, actualCol, id2, actualRow, segLen, traceValue); + segLen = 1; + } + } + + // Handle the remaining sequence + if (actualCol != 0) _alignTracePrint(finder.trace, seqH, seqV, (TId) id1, (TSize) 0, (TId) 0, (TSize) 0, (TSize) actualCol, Horizontal); + if (actualRow != 0) _alignTracePrint(finder.trace, seqH, seqV, (TId) 0, (TSize) 0, (TId) id2, (TSize) 0, (TSize) actualRow, Vertical); + + goNext(matIt, 1); // assumes that each trace ends with a diagonal + finder.bestBeginPos = position(matIt); + + return Pair >(Pair(actualCol, endCol), Pair(actualRow, endRow)); +} + +// ---------------------------------------------------------------------------- +// Function _initLocalAlignmentFinder() +// ---------------------------------------------------------------------------- + +template +void +_initLocalAlignmentFinder(TSequenceH const & seqH, + TSequenceV const & seqV, + LocalAlignmentFinder & finder, + BandedWatermanEggert const &, + TDiagonal const lowerDiag, + TDiagonal const upperDiag) { + typedef LocalAlignmentFinder TFinder; + typedef typename TFinder::TMatrix TMatrix; + typedef typename Size::Type TSize; + + TSize lo_row = (upperDiag <= 0) ? static_cast(-upperDiag) : 0; + TSize hi_row = length(seqV) + 1; + TSize len0 = length(seqH); + if (len0 - lowerDiag < hi_row) hi_row = static_cast(len0 - lowerDiag); + TSize height = hi_row - lo_row + 1; + SEQAN_ASSERT_GEQ(upperDiag, lowerDiag); + TSize diagonalWidth = (TSize) (upperDiag - lowerDiag + 1); + + setDimension(finder.matrix, 2); + setLength(finder.matrix, 0, diagonalWidth); + setLength(finder.matrix, 1, height); + resize(finder.matrix, 0); + + resize(finder.forbidden, height * diagonalWidth, false); + + finder.bestEndPos = minValue(); + finder.bestBeginPos = minValue(); +} + +// ---------------------------------------------------------------------------- +// Function _localAlignment() +// ---------------------------------------------------------------------------- + +template +inline TScoreValue +_localAlignment(LocalAlignmentFinder & finder, + Gaps & gapsH, + Gaps & gapsV, + Score const& sc, + TScoreValue cutoff, + TDiagonal diag1, + TDiagonal diag2, + BandedWatermanEggert const /*algorithmTag*/) +{ + clearGaps(gapsH); + clearClipping(gapsH); + clearGaps(gapsV); + clearClipping(gapsV); + + _initLocalAlignmentFinder(source(gapsH), source(gapsV), finder, BandedWatermanEggert(), diag1, diag2); + finder.needReinit = false; + + // Fill the matrix + TScoreValue maxScore = _alignBandedSmithWaterman(finder, source(gapsH), source(gapsV), sc, cutoff, diag1, diag2); + if (maxScore < cutoff) return 0; + + // Follow the matrix back from max entry and create a trace path + Pair > alignmentPositions = _alignBandedSmithWatermanTrace(finder, source(gapsH), source(gapsV), 0u, 0u, sc, diag1, diag2); + + // Fill the gaps following the trace path. + _pumpTraceToGaps(gapsH, gapsV, finder.trace); + + // The following (using rightOfGaps = false) only works if the gap open cost is negative. In this case, we can + // assume that there are no leading or trailing gaps in either sequence. + // + // We need this assumption because the we get source positions through alignmentPositions and conversion from + // souce to view coordinates gives us the end of a gap if we are at the beginning. + // + // TODO(holtgrew): This should be done in a more robust way. It would probably be better if alignmentPositions gave us the lengths of the local alignments! + setClippedEndPosition(gapsH, toViewPosition(gapsH, alignmentPositions.i1.i2, false)); + setClippedEndPosition(gapsV, toViewPosition(gapsV, alignmentPositions.i2.i2, false)); + setClippedBeginPosition(gapsH, toViewPosition(gapsH, alignmentPositions.i1.i1)); + setClippedBeginPosition(gapsV, toViewPosition(gapsV, alignmentPositions.i2.i1)); + + pop(finder.pQ); + + return maxScore; +} + +// ---------------------------------------------------------------------------- +// Function _localAlignmentNext() +// ---------------------------------------------------------------------------- + +template +inline TScoreValue +_localAlignmentNext(LocalAlignmentFinder & finder, + Gaps & gapsH, + Gaps & gapsV, + TScore const& sc, + TScoreValue cutoff, + TDiagonal diag1, + TDiagonal diag2, + BandedWatermanEggert const & /*algorithmTag*/) { + // Declump the matrix and find new maximum score + _alignBandedSmithWatermanDeclump(finder, source(gapsH), source(gapsV), sc, cutoff, diag1, diag2); + typename LocalAlignmentFinder::TMatrixPosition nextBestEnd; + nextBestEnd = _getNextBestEndPosition(finder, cutoff); + if(nextBestEnd==0) + return 0; + TScoreValue maxScore = getValue(finder.matrix, nextBestEnd); + if(maxScore == 0) return 0; + + // Follow the trace matrix and create a trace path + Pair > alignmentPositions = _alignBandedSmithWatermanTrace(finder, source(gapsH), source(gapsV), 0u, 0u, sc, diag1, diag2); + + // Fill the gaps following the trace path. + _pumpTraceToGaps(gapsH, gapsV, finder.trace); + + // The following (using rightOfGaps = false) only works if the gap open cost is negative. In this case, we can + // assume that there are no leading or trailing gaps in either sequence. + // + // We need this assumption because the we get source positions through alignmentPositions and conversion from + // souce to view coordinates gives us the end of a gap if we are at the beginning. + // + // TODO(holtgrew): This should be done in a more robust way. It would probably be better if alignmentPositions gave us the lengths of the local alignments! + setClippedEndPosition(gapsH, toViewPosition(gapsH, alignmentPositions.i1.i2, false)); + setClippedEndPosition(gapsV, toViewPosition(gapsV, alignmentPositions.i2.i2, false)); + setClippedBeginPosition(gapsH, toViewPosition(gapsH, alignmentPositions.i1.i1)); + setClippedBeginPosition(gapsV, toViewPosition(gapsV, alignmentPositions.i2.i1)); + + return maxScore; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_BANDED_WATERMAN_EGGERT_IMPL_H_ diff --git a/seqan/align/local_alignment_enumeration.h b/seqan/align/local_alignment_enumeration.h new file mode 100644 index 0000000..0dd6946 --- /dev/null +++ b/seqan/align/local_alignment_enumeration.h @@ -0,0 +1,220 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_ENUMERATION_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_ENUMERATION_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class LocalAlignmentEnumerator +// ---------------------------------------------------------------------------- + +template +class LocalAlignmentEnumerator; + +/*! + * @class LocalAlignmentEnumerator + * @headerfile + * @brief Enumeration of local alignments. + * + * @signature template + * class LocalAlignmentEnumerator; + * + * @tparam TScore The type of the @link Score @endlink to use for the local alignment. + * @tparam TSpec The tag to use for specializing the enumerator. + * + * This is an abstract class that will only be instantiated through its subclasses. + * See the documentation of the specializations for examples. + * + * @section References + * + *
    + *
  • Waterman MS, Eggert M: A new algorithm for best subsequence alignments with application to tRNA-rRNA + * comparisons. J Mol Biol 1987, 197(4):723-728.
  • + *
+ */ + +/*! + * @class UnbandedLocalAlignmentEnumerator + * @extends LocalAlignmentEnumerator + * @headerfile + * @brief Unbanded enumeration of local alignments using the Waterman-Eggert algorithm. + * + * @signature template + * class LocalAlignmentEnumerator; + * + * @tparam TScore The @link Score @endlink type. + * + * @section Examples + * + * Enumerate all alignments into a @link Align @endlink object. + * + * @code{.cpp} + * SimpleScore scoringScheme(2, -1, -1, -2); + * LocalAlignmentEnumerator enumerator(scoringScheme, 5); + * + * Dna5String seqH = "CGAGAGAGACCGAGA"; + * Dna5String seqV = "TTCTGAGATCCGTTTTT"; + * + * Align align; + * resize(rows(align), 2);@s + * assignSource(row(align), 0, seqH); + * assignSource(row(align), 1, seqV); + * + * int i = 0; + * while (nextLocalAlignment(align, enumerator)) + * { + * std::cout << i << "-th alignment:\n"; + * std::cout << align << "\n\n"; + * std::cout << "score == " << getScore(enumerator) << "\n"; + * } + * @endcode + */ + +/*! + * @fn UnbandedLocalAlignmentEnumerator::LocalAlignmentEnumerator + * @brief Constructor. + * + * @signature LocalAlignmentEnumerator::LocalAlignmentEnumerator(scheme[, cutoff]); + * + * @param[in] scheme The @link Score @endlink object to use for the alignment score. + * @param[in] cutoff Alignments with scores < cutoff will be discarded (int, default 0). + */ + +/*! + * @class BandedLocalAlignmentEnumerator + * @extends LocalAlignmentEnumerator + * @headerfile + * @brief Banded enumeration of local alignments using the Waterman-Eggert algorithm. + * + * @signature template + * class LocalAlignmentEnumerator; + * + * @tparam TScore The @link Score @endlink type. + * + * @section Examples + * + * Enumerate all alignments in the band between -3 and 0 into an @link Align @endlink object. + * + * @code{.cpp} + * SimpleScore scoringScheme(2, -1, -1, -2); + * LocalAlignmentEnumerator enumerator(scoringScheme, -3, 0, 5); + * + * Dna5String seqH = "CGAGAGAGACCGAGA"; + * Dna5String seqV = "TTCTGAGATCCGTTTTT"; + * + * Align align; + * resize(rows(align), 2); + * assignSource(row(align), 0, seqH); + * assignSource(row(align), 1, seqV); + * + * int i = 0; + * while (nextLocalAlignment(align, enumerator)) + * { + * std::cout << i << "-th alignment:\n"; + * std::cout << align << "\n\n"; + * std::cout << "score == " << getScore(enumerator) << "\n"; + * } + * @endcode + */ + +/*! + * @fn BandedLocalAlignmentEnumerator::LocalAlignmentEnumerator + * @brief Constructor. + * + * @signature LocalAlignmentEnumerator::LocalAlignmentEnumerator(scheme, upperDiag, lowerDiag[, cutoff]); + * + * @param[in] scheme The @link Score @endlink object to use for the alignment score. + * @param[in] upperDiag An int with the upper diagonal. + * @param[in] lowerDiag An int with the lower diagonal. + * @param[in] cutoff Alignments with scores < cutoff will be discarded (int, default 0). + */ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function getScore() +// ---------------------------------------------------------------------------- + +/*! + * @fn LocalAlignmentEnumerator#getScore + * @headerfile + * @brief Get current alignment score. + * + * @signature TScoreVal getScore(enumerator); + * + * @param[in] enumerator The LocalAlignmentEnumerator to query. + * + * @return TScoreVal The current alignment score (@link Score#Value @endlink of TScore). + */ + +// ---------------------------------------------------------------------------- +// Function nextLocalAlignment() +// ---------------------------------------------------------------------------- + +/*! + * @fn LocalAlignmentEnumerator#nextLocalAlignment + * @headerfile + * @brief Compute next suboptimal local alignment. + * + * @signature bool nextLocalAlignment(align, enumerator); + * @signature bool nextLocalAlignment(gapsH, gapsV, enumerator); + * + * @param[in] align @link Align @endlink object to use for the alignment representation. + * @param[in] gapsH @link Gaps @endlink object to use for the first/horizontal sequence in the alignment matrix. + * @param[in] gapsV @link Gaps @endlink object to use for the second/vertical sequence in the alignment matrix. + * @param[in] enumerator The LocalAlignmentEnumerator to advance. + * + * @return bool true if another suboptimal alignment above the given threshold was found and false + * otherwise. + */ + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_ENUMERATION_H_ diff --git a/seqan/align/local_alignment_enumeration_banded.h b/seqan/align/local_alignment_enumeration_banded.h new file mode 100644 index 0000000..4172d79 --- /dev/null +++ b/seqan/align/local_alignment_enumeration_banded.h @@ -0,0 +1,126 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_ENUMERATION_BANDED_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_ENUMERATION_BANDED_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Specialization Banded LocalAlignmentEnumerator +// ---------------------------------------------------------------------------- + +struct Banded_; +typedef Tag Banded; + +template +class LocalAlignmentEnumerator +{ +public: + typedef typename Value::Type TScoreValue_; + + TScore _score; + int _lowerDiag; + int _upperDiag; + TScoreValue_ _cutoff; + LocalAlignmentFinder _finder; + + LocalAlignmentEnumerator(TScore const & score, int lowerDiag, int upperDiag) : + _score(score), _lowerDiag(lowerDiag), _upperDiag(upperDiag), _cutoff(0) + {} + + LocalAlignmentEnumerator(TScore const & score, int lowerDiag, int upperDiag, int cutoff) : + _score(score), _lowerDiag(lowerDiag), _upperDiag(upperDiag), _cutoff(cutoff) + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function getScore() +// ---------------------------------------------------------------------------- + +template +inline TScoreValue +getScore(LocalAlignmentEnumerator, Banded> const & enumerator) +{ + return getScore(enumerator._finder); +} + +// ---------------------------------------------------------------------------- +// Function nextLocalAlignment() +// ---------------------------------------------------------------------------- + +template +inline bool +nextLocalAlignment(Gaps & gapsH, + Gaps & gapsV, + LocalAlignmentEnumerator, Banded> & enumerator) +{ + if (enumerator._finder.needReinit) + return _localAlignment(enumerator._finder, gapsH, gapsV, enumerator._score, enumerator._cutoff, + enumerator._lowerDiag, enumerator._upperDiag, BandedWatermanEggert()); + else + return _localAlignmentNext(enumerator._finder, gapsH, gapsV, enumerator._score, + enumerator._cutoff, enumerator._lowerDiag, enumerator._upperDiag, + BandedWatermanEggert()); +} + +template +inline bool +nextLocalAlignment(Align & align, + LocalAlignmentEnumerator, Banded> & enumerator) +{ + SEQAN_ASSERT_EQ(length(rows(align)), 2u); + + return nextLocalAlignment(row(align, 0), row(align, 1), enumerator); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_ENUMERATION_BANDED_H_ diff --git a/seqan/align/local_alignment_enumeration_unbanded.h b/seqan/align/local_alignment_enumeration_unbanded.h new file mode 100644 index 0000000..a5efcb8 --- /dev/null +++ b/seqan/align/local_alignment_enumeration_unbanded.h @@ -0,0 +1,122 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_ENUMERATION_UNBANDED_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_ENUMERATION_UNBANDED_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Specialization Unbanded LocalAlignmentEnumerator +// ---------------------------------------------------------------------------- + +struct Unbanded_; +typedef Tag Unbanded; + +template +class LocalAlignmentEnumerator +{ +public: + typedef typename Value::Type TScoreValue_; + + TScore _scoringScheme; + TScoreValue_ _cutoff; + LocalAlignmentFinder _finder; + + LocalAlignmentEnumerator(TScore const & score) : + _scoringScheme(score), _cutoff(0) + {} + + LocalAlignmentEnumerator(TScore const & score, int cutoff) : + _scoringScheme(score), _cutoff(cutoff) + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function getScore() +// ---------------------------------------------------------------------------- + +template +inline TScoreValue +getScore(LocalAlignmentEnumerator, Unbanded> const & enumerator) +{ + // TODO(holtgrew): Const correctness! + return getScore(const_cast &>(enumerator._finder)); +} + +// ---------------------------------------------------------------------------- +// Function nextLocalAlignment() +// ---------------------------------------------------------------------------- + +template +inline bool +nextLocalAlignment(Gaps & gapsH, + Gaps & gapsV, + LocalAlignmentEnumerator, Unbanded> & enumerator) +{ + if (enumerator._finder.needReinit) + return _smithWaterman(gapsH, gapsV, enumerator._finder, enumerator._scoringScheme, enumerator._cutoff); + else + return _smithWatermanGetNext(gapsH, gapsV, enumerator._finder, enumerator._scoringScheme, enumerator._cutoff); +} + +template +inline bool +nextLocalAlignment(Align & align, + LocalAlignmentEnumerator, Unbanded> & enumerator) +{ + SEQAN_ASSERT_EQ(length(rows(align)), 2u); + + return nextLocalAlignment(row(align, 0), row(align, 1), enumerator); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_ENUMERATION_UNBANDED_H_ diff --git a/seqan/align/local_alignment_unbanded.h b/seqan/align/local_alignment_unbanded.h new file mode 100644 index 0000000..a6a920f --- /dev/null +++ b/seqan/align/local_alignment_unbanded.h @@ -0,0 +1,381 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Interface functions for unbanded local alignment. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_UNBANDED_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_UNBANDED_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function localAlignment() +// ---------------------------------------------------------------------------- + +/*! + * @fn localAlignment + * @headerfile + * @brief Computes the best pairwise local alignment using the Smith-Waterman algorithm. + * + * @signature TScoreVal localAlignment(align, scoringScheme, [lowerDiag, upperDiag]); + * @signature TScoreVal localAlignment(gapsH, gapsV, scoringScheme, [lowerDiag, upperDiag]); + * @signature TScoreVal localAlignment(fragmentString, scoringScheme, [lowerDiag, upperDiag]); + * + * @param[in,out] gapsH Horizontal gapped sequence in alignment matrix. Types: @link Gaps @endlink + * @param[in,out] gapsV Vertical gapped sequence in alignment matrix. Types: @link Gaps @endlink + * @param[in,out] align An @link Align @endlink object that stores the alignment. The + * number of rows must be 2 and the sequences must have already + * been set. align[0] is the horizontal one in the + * alignment matrix alignment, align[1] is the vertical + * one. + * @param[in,out] fragmentString + * String of @link Fragment @endlink objects. The sequence + * with id 0 is the horizontal one, the sequence + * with id 1 is the vertical one. + * @param[in] scoringScheme + * The @link Score scoring scheme @endlink to use for the alignment. + * @param[in] lowerDiag Optional lower diagonal (int). + * @param[in] upperDiag Optional upper diagonal (int). + * + * @return TScoreVal Score value of the resulting alignment (Metafunction @link Score#Value @endlink of the type of + * scoringScheme). + * + * The Waterman-Eggert algorithm (local alignment with declumping) is available through the @link + * LocalAlignmentEnumerator @endlink class. + * + * When using @link Gaps @endlink and @link Align @endlink objects, only parts (i.e. one infix) of each sequence will be + * aligned. This will be presented to the user by setting the clipping begin and end position of the gaps (the rows in + * the case of @link Align @endlink objects). When using @link Fragment @endlink strings, these parts of the sequences + * will not appear in any fragment. + * + * There exist multiple overloads for this function with two configuration dimensions. + * + * First, you can select the type of the target storing the alignment. This can be either an @link Align @endlink + * object, two @link Gaps @endlink objects, or a string of @link Fragment @endlink objects. @link Align @endlink objects + * provide an interface to tabular alignments with the restriction of all rows having the same type. Using two @link + * Gaps @endlink objects has the advantage that you an align sequences with different types, for example @link DnaString + * @endlink and @link Dna5String @endlink. Using @link Fragment @endlink strings is useful for collecting many pairwise + * alignments, for example in the construction of @link AlignmentGraph Alignment Graphs @endlink for multiple- sequence + * alignments (MSA). + * + * Second, you can optionally give a band for the alignment using lowerDiag and upperDiag. The center + * diagonal has index 0, the ith diagonal below has index -i, the ith above has + * index i. + * + * The examples below show some common use cases. + * + * @section Examples + * + * Local alignment of two sequences using an @link Align @endlink object. + * + * @code{.cpp} + * Dna5String seqH = "CGATT"; + * Dna5String seqV = "CGAAATT"; + * + * Align align; + * resize(rows(align), 2); + * assignSource(row(align, 0), seqH); + * assignSource(row(align, 0), seqV); + * Score scoringScheme(2, -1, -2); + * + * int result = localAlignment(align, scoringScheme); + * @endcode + * + * Local banded alignment of two sequences using two @link Gaps @endlink objects. + * + * @code{.cpp} + * Dna5String seqH = "CGATT"; + * Gaps gapsH(seqH); + * DnaString seqV = "CGAAATT"; + * Gaps > gapsV(seqV); + * + * Score scoringScheme(5, -3, -1, -5); + * + * int result = localAlignment(gapsH, gapsV, scoringScheme, -2, 2); + * @endcode + * + * https://seqan.readthedocs.io/en/develop/Tutorial/Algorithms/Alignment/PairwiseSequenceAlignment.html + * + * @section References + * + *
    + *
  • Smith TF, Waterman, MS: Identification of Common Molecular Subsequences. J Mol Biol 1981, 147(1):195-7.
  • + *
+ * + * @see globalAlignment + * @see LocalAlignmentEnumerator + * @see PairwiseLocalAlignmentAlgorithms + */ + +// ---------------------------------------------------------------------------- +// Function localAlignment() [unbanded, Align] +// ---------------------------------------------------------------------------- + +template +TScoreValue localAlignment(Align & align, + Score const & scoringScheme, + TTag const & tag) +{ + SEQAN_ASSERT_EQ(length(rows(align)), 2u); + typedef Align TAlign; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig2, FreeEndGaps_<> > TAlignConfig2; + + String trace; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, source(row(align, 0)), source(row(align, 1)), + scoringScheme, TAlignConfig2(), tag); + + _adaptTraceSegmentsTo(row(align, 0), row(align, 1), trace); + return res; +} + + template + TScoreValue localAlignment(Align & align, + Score const & scoringScheme) + { + SEQAN_ASSERT(length(rows(align)) == 2u); + if (_usesAffineGaps(scoringScheme, source(row(align, 0)), source(row(align, 1)))) + return localAlignment(align, scoringScheme, AffineGaps()); + else + return localAlignment(align, scoringScheme, LinearGaps()); + } + +// ---------------------------------------------------------------------------- +// Function localAlignment() [unbanded, Gaps] +// ---------------------------------------------------------------------------- + + template + TScoreValue localAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme, + TTag const & tag) + { + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig2, FreeEndGaps_<> > TAlignConfig2; + + String trace; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, source(gapsH), source(gapsV), scoringScheme, + TAlignConfig2(), tag); + _adaptTraceSegmentsTo(gapsH, gapsV, trace); + return res; + } + + template +TScoreValue localAlignment(Gaps & gapsH, + Gaps & gapsV, + Score const & scoringScheme) +{ + if (_usesAffineGaps(scoringScheme, source(gapsH), source(gapsV))) + return localAlignment(gapsH, gapsV, scoringScheme, AffineGaps()); + else + return localAlignment(gapsH, gapsV, scoringScheme, LinearGaps()); +} + +// ---------------------------------------------------------------------------- +// Function localAlignment() [unbanded, Graph>] +// ---------------------------------------------------------------------------- + +// Full interface. + +template +TScoreValue localAlignment(Graph > & alignmentGraph, + Score const & scoringScheme, + TTag const & tag) +{ + typedef Graph > TGraph; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig2, FreeEndGaps_<> > TAlignConfig2; + + String trace; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, value(stringSet(alignmentGraph), 0), + value(stringSet(alignmentGraph), 1), scoringScheme, TAlignConfig2(), tag); + + _adaptTraceSegmentsTo(alignmentGraph, positionToId(stringSet(alignmentGraph), 0), + positionToId(stringSet(alignmentGraph), 1), trace); + return res; +} + +template +TScoreValue localAlignment(Graph > & alignmentGraph, + Score const & scoringScheme) +{ + SEQAN_ASSERT(length(stringSet(alignmentGraph)) == 2u); + + if (_usesAffineGaps(scoringScheme, stringSet(alignmentGraph)[0], stringSet(alignmentGraph)[1])) + return localAlignment(alignmentGraph, scoringScheme, AffineGaps()); + else + return localAlignment(alignmentGraph, scoringScheme, LinearGaps()); +} + +// ---------------------------------------------------------------------------- +// Function localAlignment() [unbanded, String >] +// ---------------------------------------------------------------------------- + +// Full interface. + +template +TScoreValue localAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme, + TTag const & tag) +{ + typedef String, TStringSpec> TFragments; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + typedef AlignConfig2, FreeEndGaps_<> > TAlignConfig2; + + String trace; + DPScoutState_ dpScoutState; + TScoreValue res = _setUpAndRunAlignment(trace, dpScoutState, value(strings, 0), value(strings, 1), scoringScheme, + TAlignConfig2(), tag); + + _adaptTraceSegmentsTo(fragmentString, positionToId(strings, 0), positionToId(strings, 1), trace); + return res; +} + +template +TScoreValue localAlignment(String, TStringSpec> & fragmentString, + StringSet const & strings, + Score const & scoringScheme) +{ + SEQAN_ASSERT(length(strings) == 2u); + + if (_usesAffineGaps(scoringScheme, strings[0], strings[1])) + return localAlignment(fragmentString, strings, scoringScheme, AffineGaps()); + else + return localAlignment(fragmentString, strings, scoringScheme, LinearGaps()); +} + +// ============================================================================ +// Many-vs-Many align interfaces. +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function localAlignment() [unbanded, SIMD version, GapsH, GapsV] +// ---------------------------------------------------------------------------- + +template +inline auto +localAlignment(StringSet & gapSeqSetH, + StringSet & gapSeqSetV, + Score const & scoringScheme, + TAlgoTag const & /*algoTag*/) +{ + typedef AlignConfig2, FreeEndGaps_<> > TAlignConfig2; + typedef typename SubstituteAlgoTag_::Type TGapModel; + + return _alignWrapper(gapSeqSetH, gapSeqSetV, scoringScheme, TAlignConfig2(), TGapModel()); +} + +// ---------------------------------------------------------------------------- +// Function localAlignment() [unbanded, SIMD version, StringSet] +// ---------------------------------------------------------------------------- + +template +inline String +localAlignment(StringSet > & alignSet, + Score const & scoringScheme, + TAlgoTag const & algoTag) +{ + typedef Align TAlign; + typedef typename Row::Type TGapSequence; + + StringSet > gapSetH; + StringSet > gapSetV; + reserve(gapSetH, length(alignSet)); + reserve(gapSetV, length(alignSet)); + + for (auto & align : alignSet) + { + appendValue(gapSetH, row(align, 0)); + appendValue(gapSetV, row(align, 1)); + } + + return localAlignment(gapSetH, gapSetV, scoringScheme, algoTag); +} + +template +String localAlignment(StringSet > & align, + Score const & scoringScheme) +{ + if (_usesAffineGaps(scoringScheme, source(row(align[0], 0)), source(row(align[0], 1)))) + return localAlignment(align, scoringScheme, AffineGaps()); + else + return localAlignment(align, scoringScheme, LinearGaps()); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_UNBANDED_H_ diff --git a/seqan/align/local_alignment_waterman_eggert_impl.h b/seqan/align/local_alignment_waterman_eggert_impl.h new file mode 100644 index 0000000..e78fc33 --- /dev/null +++ b/seqan/align/local_alignment_waterman_eggert_impl.h @@ -0,0 +1,751 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// Author: Anne-Katrin Emde +// ========================================================================== +// Implementation of the Waterman-Eggert algorithm, sometimes also called +// Smith-Waterman algorithm with declumping. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_WATERMAN_EGGERT_IMPL_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_WATERMAN_EGGERT_IMPL_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Helper Class ScoreAndID +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Why is Pair<> not enough? +// TODO(holtgrew): Rename to ScoreAndID_ (with trailing underscore) + +// Simple class that stores a value with an ID. +template +class ScoreAndID +{ +public: + TValue value_; + TID id_; + + ScoreAndID() : value_(MinValue::VALUE), id_(MaxValue::VALUE) + {} + + ScoreAndID(TValue score, TID id_pos) + { + value_ = score; + id_ = id_pos; + } + + inline bool operator>(ScoreAndID const & other) const + { + return value_ > other.value_; + } + + inline bool operator<(ScoreAndID const & other) const + { + return value_ < other.value_; + } +}; + +// ---------------------------------------------------------------------------- +// Class LocalAlignmentFinder +// ---------------------------------------------------------------------------- + +template +class LocalAlignmentFinder +{ +public: + typedef Matrix TMatrix; + typedef typename Position::Type TMatrixPosition; + typedef typename Size::Type TSize; + typedef ScoreAndID TPQEntry; + + typedef Iter TMatrixIterator; + typedef PriorityType TPriorityQ; + typedef String TBoolMatrix; + + //DP-matrix + TMatrix matrix; + //matrix that memorizes the cells from which not to go diagonal + TBoolMatrix forbidden; + //priority queue for quickly finding the maximum score in the DP-matrix + TPriorityQ pQ; + //position of maximum score (where traceback is started from) + TMatrixPosition bestEndPos; + //position where traceback ended and where declumping begins + TMatrixPosition bestBeginPos; + //traceback path that is set to forbidden while declumping + AlignTraceback trace; + + bool needReinit; //true: call "smithWaterman", false: call "smithWatermanGetNext" + + LocalAlignmentFinder() : bestEndPos(0), bestBeginPos(0), needReinit(true) + {} + + // TODO(holtgrew): Remove and replace all occurrences with default constructor. + template + LocalAlignmentFinder(TAlign const &) : bestEndPos(0), bestBeginPos(0), needReinit(true) + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _initLocalAlignmentFinder() +// ---------------------------------------------------------------------------- + +template +void +_initLocalAlignmentFinder(TSequenceH const & seqH, + TSequenceV const & seqV, + LocalAlignmentFinder & finder, + TTag) { + typedef LocalAlignmentFinder TFinder; + typedef typename TFinder::TMatrix TMatrix; + typedef typename Size::Type TSize; + + TSize len0 = length(seqH); + TSize len1 = length(seqV); + + setDimension(finder.matrix, 2); + setLength(finder.matrix, 0, len0 + 1); + setLength(finder.matrix, 1, len1 + 1); + resize(finder.matrix); + + resize(finder.forbidden, (len0 + 1) * (len1 + 1), false); + + finder.bestEndPos = maxValue(); + finder.bestBeginPos = maxValue(); +} + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +template +void clear(LocalAlignmentFinder & sw_finder) +{ + sw_finder.needReinit = true; +} + +// ---------------------------------------------------------------------------- +// Function getScore() +// ---------------------------------------------------------------------------- + +template +TScoreValue getScore(LocalAlignmentFinder const & sw) +{ + typedef LocalAlignmentFinder TFinder; + if(sw.bestEndPos != maxValue()) + return getValue(const_cast(sw.matrix), sw.bestEndPos); + return 0; +} + +// ---------------------------------------------------------------------------- +// Function _smithWatermanGetMatrix() +// ---------------------------------------------------------------------------- + +template +TScoreValue +_smithWatermanGetMatrix(LocalAlignmentFinder & sw, + TStringH const & strH, + TStringV const & strV, + Score const & score_, + TScoreValue cutoff) +{ + // typedefs + typedef Matrix TMatrix; + typedef typename Position::Type TMatrixPosition; + typedef Iter TMatrixIterator; + + typedef typename Iterator::Type TStringIteratorH; + //typedef typename Value::Type TValueH; + typedef typename Iterator::Type TStringIteratorV; + typedef typename Value::Type TValueV; + + //------------------------------------------------------------------------- + //define some variables + + +// TSize str1_length = length(strH); +// TSize str2_length = length(strV); + TStringIteratorH x_begin = begin(strH) - 1; + TStringIteratorH x_end = end(strH) - 1; + TStringIteratorV y_begin = begin(strV) - 1; + TStringIteratorV y_end = end(strV) - 1; + + TStringIteratorH x = x_end; + TStringIteratorV y; + + TScoreValue score_match = scoreMatch(score_); + TScoreValue score_mismatch = scoreMismatch(score_); + TScoreValue score_gap = scoreGapExtend(score_); + + TScoreValue h = 0; + TScoreValue v = 0; + + TMatrixIterator col_ = end(sw.matrix) - 1; + TMatrixIterator finger1; + TMatrixIterator finger2; + + //------------------------------------------------------------------------- + // init + + finger1 = col_; + *finger1 = 0; + //std::cout <<" "; + for (x = x_end; x != x_begin; --x) + { + goPrevious(finger1, 0); + *finger1 = 0; + } + + //------------------------------------------------------------------------- + //fill matrix + for (y = y_end; y != y_begin; --y) + { + TValueV cy = *y; + + h = 0; + v = 0; + + finger2 = col_; //points to last column + goPrevious(col_, 1); //points to this column + finger1 = col_; + + *finger1 = v; + + for (x = x_end; x != x_begin; --x) + { + goPrevious(finger1, 0); + goPrevious(finger2, 0); + + if (*x == cy) + { + v = h + score_match; + h = *finger2; + } + else + { + TScoreValue s1 = h + score_mismatch; + h = *finger2; + TScoreValue s2 = score_gap + ((h > v) ? h : v); + v = (s1 > s2) ? s1 : s2; + if (v < 0) v = 0; + + } + *finger1 = v; + if (v >= cutoff) + { + push(sw.pQ,ScoreAndID(v,position(finger1))); + } + } + } + + // check if any scores >= cutoff were found + if(!empty(sw.pQ)) + { + ScoreAndID best = top(sw.pQ); + v = getValue(sw.matrix,best.id_); + sw.bestEndPos = best.id_; + } + else + v=0; + + return v; +} + +// ---------------------------------------------------------------------------- +// Function _smithWatermanDeclump() +// ---------------------------------------------------------------------------- + +// declumping +template +void +_smithWatermanDeclump(LocalAlignmentFinder & sw , + Gaps & gapsH, + Gaps & gapsV, + Score const & score_) +{ +//------------------------------------------------------------------------- +//typedefs + //typedef typename LocalAlignmentFinder::TMatrixPosition TMatrixPosition; + typedef typename LocalAlignmentFinder::TMatrix TMatrix; + typedef Iter TMatrixIterator; + + typedef Gaps TGapsH; + typedef typename Iterator::Type TGapsHIter; + typedef typename Iterator::Type TSequenceHIter; + //typedef typename Value::Type TValueH; + + typedef Gaps TGapsV; + typedef typename Iterator::Type TGapsVIter; + typedef typename Iterator::Type TSequenceVIter; + typedef typename Value::Type TValueV; + +//------------------------------------------------------------------------- +//variables + // TRow row0 = row(align_,0); + // TRow row1 = row(align_,1); + + // beginPosition == # leading gaps + // endPosition == length of clipped region without trailing gaps + // clippedEndPosition == source position of clipping end. + + // TAlignIterator ali_it0_stop = iter(row0,beginPosition(row0)); + // TAlignIterator ali_it1_stop = iter(row1,beginPosition(row1)); + TGapsHIter ali_it0_stop = begin(gapsH); + TGapsVIter ali_it1_stop = begin(gapsV); + + // SEQAN_ASSERT( endPosition(row0)- beginPosition(row0) == endPosition(row1)- beginPosition(row1) ); + + // TAlignIterator ali_it0 = iter(row0,endPosition(row0)); + // TAlignIterator ali_it1 = iter(row1,endPosition(row1)); + TGapsHIter ali_it0 = end(gapsH); + TGapsVIter ali_it1 = end(gapsV); + + // TStringIterator x_begin = begin(source(row0))-1; + // TStringIterator y_begin = begin(source(row1))-1; + // TStringIterator x_end = iter(source(row0),clippedEndPosition(row0))-1; + // TStringIterator y_end = iter(source(row1),clippedEndPosition(row1))-1; + TSequenceHIter x_begin = begin(source(gapsH))-1; + TSequenceVIter y_begin = begin(source(gapsV))-1; + TSequenceHIter x_end = iter(source(gapsH), endPosition(gapsH) - 1); + TSequenceVIter y_end = iter(source(gapsV), endPosition(gapsV) - 1); + + // TStringIterator x = x_end; + // TStringIterator y = y_end; + // TStringIterator x_stop = x_end; + TSequenceHIter x = x_end; + TSequenceVIter y = y_end; + TSequenceHIter x_stop = x_end; + + + TScoreValue score_match = scoreMatch(score_); + TScoreValue score_mismatch = scoreMismatch(score_); + TScoreValue score_gap = scoreGapExtend(score_); + TScoreValue h,v; + + TMatrixIterator finger0 = iter(sw.matrix,sw.bestBeginPos); + TMatrixIterator end_col = finger0; + TMatrixIterator finger1 = finger0; + TMatrixIterator forbidden = finger0; + + bool different = true; + bool forbidden_reached = true; + bool end_reached = false; + bool skip_row = false; + + +/* int str0_length = length(source(row(align_,0)))+1; + int str1_length = length(source(row(align_,1)))+1; + for(int i = 0; i v) ? h : v); + v = (s1 > s2) ? s1 : s2; + if (v < 0) v = 0; + + } + + // value is the same as in the original matrix + if(*finger0==v) + { + //x_stop is as far as we have to go at least + if(x +typename Iterator, Standard >::Type +_smithWatermanTrace(Gaps & gapsH, + Gaps & gapsV, + typename LocalAlignmentFinder::TBoolMatrix & fb_matrix, + Iter< Matrix, PositionIterator > source_, + Score const & scoring_) { + //typedefs + typedef Iter, PositionIterator > TMatrixIterator; + typedef typename Position >::Type TPosition; + +// typedef Segment TTargetSourceSegment; + typedef typename Iterator::Type TSourceIteratorH; + typedef typename Iterator::Type TSourceIteratorV; + + typedef Gaps TGapsH; + typedef Gaps TGapsV; + typedef typename Iterator::Type TTargetIteratorH; + typedef typename Iterator::Type TTargetIteratorV; + + //------------------------------------------------------------------------- + //variables + TPosition pos_0 = coordinate(source_, 0); + TPosition pos_1 = coordinate(source_, 1); + + TSourceH strH = source(gapsH); + TSourceV strV = source(gapsV); + + TTargetIteratorH target_0 = iter(gapsH, pos_0); + TTargetIteratorV target_1 = iter(gapsV, pos_1); + + TSourceIteratorH it_0 = iter(strH, pos_0, Standard()); + TSourceIteratorH it_0_end = end(strH); + + TSourceIteratorV it_1 = iter(strV, pos_1, Standard()); + TSourceIteratorV it_1_end = end(strV); + + TScoreValue score_mismatch = scoreMismatch(scoring_); + TScoreValue score_gap = scoreGapExtend(scoring_); + + //------------------------------------------------------------------------- + //follow the trace until 0 is reached + while ((*source_!=0) && (it_0 != it_0_end) && (it_1 != it_1_end)) + { + bool gv; + bool gh; + bool forbidden = fb_matrix[position(source_)]; + + if (*it_0 == *it_1 && !forbidden) + { + gv = gh = true; + } + else + { + TMatrixIterator it_ = source_; + + goNext(it_, 0); + TScoreValue v = *it_ + score_gap; + + TScoreValue d; + if(forbidden) + d = 0; + else{ + goNext(it_, 1); + d = *it_ + score_mismatch; + } + + it_ = source_; + goNext(it_, 1); + TScoreValue h = *it_ + score_gap; + + gv = (v >= h) | (d >= h); + gh = (h > v) | (d >= v); + } + + if (gv) + { + ++it_0; + goNext(source_, 0); + } + else + { + insertGap(target_0); + } + + if (gh) + { + ++it_1; + goNext(source_, 1); + } + else + { + insertGap(target_1); + } + ++target_0; + ++target_1; + } + + // We have removed all gaps and clippings from gapsH and gapsV in the calling functions, so the following works. + // Note that we have to set the end position first. + // TODO(holtgrew): Use setBegin/EndPosition(). + setClippedEndPosition(gapsH, toViewPosition(gapsH, position(it_0, strH))); + setClippedEndPosition(gapsV, toViewPosition(gapsV, position(it_1, strV))); + setClippedBeginPosition(gapsH, toViewPosition(gapsH, pos_0)); + setClippedBeginPosition(gapsV, toViewPosition(gapsV, pos_1)); + + return source_; +} + +// ---------------------------------------------------------------------------- +// Function _getNextBestEndPosition() +// ---------------------------------------------------------------------------- + +// Adjust the priority queue of scores until the true maximum is found. +template +typename LocalAlignmentFinder::TMatrixPosition +_getNextBestEndPosition(LocalAlignmentFinder & sw , + TScoreValue cutoff) +{ + // get maximal score from priority queue + TScoreValue topScore = 0; + if (!empty(sw.pQ)) + topScore = getValue(sw.matrix, top(sw.pQ).id_); + + // check if matrix entry of topScore did not change while declumping + if (!empty(sw.pQ)) { + while (top(sw.pQ).value_ != topScore) { + if (topScore >= cutoff) { + ((sw.pQ).heap[0]).value_ = topScore; + adjustTop(sw.pQ); + } else { + pop(sw.pQ); + } + if (!empty(sw.pQ)) topScore = getValue(sw.matrix, top(sw.pQ).id_); + else break; + } + } + + // priority queue with top scores is empty + if(empty(sw.pQ)) {//||top(sw.pQ).value_::TMatrixPosition ret_pos = top(sw.pQ).id_; + sw.bestEndPos = ret_pos; + pop(sw.pQ); + + return ret_pos; +} + +// ---------------------------------------------------------------------------- +// Function _smithWaterman() +// ---------------------------------------------------------------------------- + +// Wrapper that computes the matrix and does the backtracking for the best alignment +template +TScoreValue +_smithWaterman(Gaps & gapsH, + Gaps & gapsV, + LocalAlignmentFinder & sw_finder, + Score const & score_, + TScoreValue cutoff) +{ + // TODO(holtgrew): This sourceSegment() stuff is confusing... Do we *really* need this? + // Clear gaps and clipping from result Gaps structures. + clearGaps(gapsH); + clearGaps(gapsV); + clearClipping(gapsH); + clearClipping(gapsV); + + _initLocalAlignmentFinder(sourceSegment(gapsH), sourceSegment(gapsV), sw_finder, WatermanEggert()); + + TScoreValue ret = _smithWatermanGetMatrix(sw_finder, sourceSegment(gapsH), sourceSegment(gapsV), score_,cutoff); + + if(ret==0) + return ret; + sw_finder.needReinit = false; + + typedef Iter::TMatrix,PositionIterator > TMatrixIterator; + TMatrixIterator best_begin; + + // TODO(holtgrew): What does the following comment mean? + // TODO: sw_finder statt kram + best_begin = _smithWatermanTrace(gapsH, gapsV, sw_finder.forbidden,iter(sw_finder.matrix,(top(sw_finder.pQ)).id_), score_); + + sw_finder.bestBeginPos = position(best_begin); + + pop(sw_finder.pQ); + + return ret; +} + +// ---------------------------------------------------------------------------- +// Function _smithWatermanGetNext() +// ---------------------------------------------------------------------------- + +// Wrapper that declumps the matrix and traces back the next best alignment +template +TScoreValue +_smithWatermanGetNext(Gaps & gapsH, + Gaps & gapsV, + LocalAlignmentFinder & sw_finder , + Score const & score_, + TScoreValue cutoff) +{ + _smithWatermanDeclump(sw_finder, gapsH, gapsV, score_); + + clearGaps(gapsH); + clearGaps(gapsV); + clearClipping(gapsH); + clearClipping(gapsV); + + typename LocalAlignmentFinder::TMatrixPosition next_best_end; + next_best_end = _getNextBestEndPosition(sw_finder,cutoff); + if(next_best_end==0) + return 0; + typename LocalAlignmentFinder::TMatrixIterator next_best_begin; + next_best_begin= _smithWatermanTrace(gapsH, gapsV, sw_finder.forbidden,iter(sw_finder.matrix,next_best_end), score_); + sw_finder.bestBeginPos = position(next_best_begin); + + return getValue(sw_finder.matrix,next_best_end); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_LOCAL_ALIGNMENT_WATERMAN_EGGERT_IMPL_H_ diff --git a/seqan/align/matrix_base.h b/seqan/align/matrix_base.h new file mode 100644 index 0000000..e5ca253 --- /dev/null +++ b/seqan/align/matrix_base.h @@ -0,0 +1,1103 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// Simple matrices; Used in many alignment algorithms. +// ========================================================================== + +#ifndef SEQAN_HEADER_MATRIX_BASE_H +#define SEQAN_HEADER_MATRIX_BASE_H + +namespace seqan +{ + +////////////////////////////////////////////////////////////////////////////// + +struct NDimensional; + + +template +class Matrix; + +////////////////////////////////////////////////////////////////////////////// +template struct SizeArr_; + +template +struct SizeArr_ > +{ + typedef Matrix TMatrix_; + typedef typename Size::Type TSize_; + typedef String Type; +}; + +////////////////////////////////////////////////////////////////////////////// + +template +struct Host > +{ + typedef typename StringSpecForValue_::Type TSpec_; + typedef String Type; +}; + +template +struct Host const> +{ + typedef typename StringSpecForValue_::Type TSpec_; + typedef String Type; +}; + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +// TODO(holtgrew): Add more comprehensive documentation! + +/*! + * @class Matrix + * @headerfile + * @brief A simple n-dimensional matrix type. + * + * @signature template + * class Matrix; + * + * @tparam TValue Type of matrix entries. + * @tparam DIMENSION Dimension of the matrix. Use 0 for n-dimensional, values > 0 for a matrix with + * DIMENSION dimensions. Defaults to 0. + */ + + +template +class Matrix +{ +//____________________________________________________________________________ + +public: + typedef typename Size::Type TSize; + typedef String TSizeArr; + typedef typename Host::Type THost; + + TSizeArr data_lengths; //Length of every dimension + TSizeArr data_factors; //used for positions of dimensions in host ("size of jumps" to get to next entry of specified dimension) + + Holder data_host; +//____________________________________________________________________________ + +public: + Matrix() + { + create(data_host); + } + Matrix(Matrix const & other_): + data_lengths(other_.data_lengths), + data_factors(other_.data_factors), + data_host(other_.data_host) + { + } + inline Matrix const & + operator = (Matrix const & other_) + { + data_lengths = other_.data_lengths; + data_factors = other_.data_factors; + data_host = other_.data_host; + + return *this; + } + ~Matrix() + { + } +//____________________________________________________________________________ + + +//____________________________________________________________________________ + + inline TValue & + operator () (TSize x1, TSize x2) + { + return value(*this, x1, x2); + } + inline TValue & + operator () (TSize x1, TSize x2, TSize x3) + { + return value(*this, x1, x2, x3); + } + inline TValue & + operator () (TSize x1, TSize x2, TSize x3, TSize x4) + { + return value(*this, x1, x2, x3, x4); + } + +//____________________________________________________________________________ +}; + + +template +class Matrix +{ +//____________________________________________________________________________ + +public: + typedef typename Size::Type TSize; + typedef String TSizeArr; + typedef typename Host::Type THost; + + TSizeArr data_lengths; + TSizeArr data_factors; + + Holder data_host; + + +//____________________________________________________________________________ + +public: + Matrix() + { + create(data_host); + + //setDimension to 2 + resize(data_lengths, 2, 0); + resize(data_factors, 2, 0); + data_factors[0] = 1; + } + Matrix(Matrix const & other_): + data_lengths(other_.data_lengths), + data_factors(other_.data_factors), + data_host(other_.data_host) + { + } + inline Matrix const & + operator = (Matrix const & other_) + { + data_lengths = other_.data_lengths; + data_factors = other_.data_factors; + data_host = other_.data_host; + + return *this; + } + + ~Matrix() + { + } +//____________________________________________________________________________ + + +//____________________________________________________________________________ + + inline TValue & + operator () (TSize x1, TSize x2) + { + return value(*this, x1, x2); + } + +//____________________________________________________________________________ +}; + +template +class Matrix +{ +//____________________________________________________________________________ + +public: + typedef typename Size::Type TSize; + typedef String TSizeArr; + typedef typename Host::Type THost; + + TSizeArr data_lengths; + TSizeArr data_factors; + + Holder data_host; + + +//____________________________________________________________________________ + +public: + Matrix() + { + create(data_host); + + //setDimension to 3 + resize(data_lengths, 3, 0); + resize(data_factors, 3); + data_factors[0] = 1; + } + Matrix(Matrix const & other_): + data_lengths(other_.data_lengths), + data_factors(other_.data_factors), + data_host(other_.data_host) + { + } + inline Matrix const & + operator = (Matrix const & other_) + { + data_lengths = other_.data_lengths; + data_factors = other_.data_factors; + data_host = other_.data_host; + + return *this; + } + + ~Matrix() + { + } +//____________________________________________________________________________ + + +//____________________________________________________________________________ + + inline TValue & + operator () (TSize x1, TSize x2, TSize x3) + { + return value(*this, x1, x2, x3); + } + +//____________________________________________________________________________ +}; + +template +inline typename SizeArr_ >::Type & +_dataLengths(Matrix & me) +{ + return me.data_lengths; +} + +template +inline typename SizeArr_ >::Type const & +_dataLengths(Matrix const & me) +{ + return me.data_lengths; +} + +template +inline typename SizeArr_ >::Type & +_dataFactors(Matrix & me) +{ + return me.data_factors; +} + +template +inline typename SizeArr_ >::Type const & +_dataFactors(Matrix const & me) +{ + return me.data_factors; +} + +//____________________________________________________________________________ + + +template +inline bool +dependent(Matrix & me) +{ + return dependent(me.data_host); +} + +//____________________________________________________________________________ + +template +inline Holder >::Type> & +_dataHost(Matrix & matrix) +{ + return matrix.data_host; +} + +template +inline Holder >::Type> const & +_dataHost(Matrix const & matrix) +{ + return matrix.data_host; +} + +//____________________________________________________________________________ + +template +inline void +assignHost(Matrix & me, THost const & value_) +{ + assignValue(me.data_host, value_); +} + +//____________________________________________________________________________ + +template +inline void +moveHost(Matrix & me, THost const & value_) +{ + moveValue(me.data_host, value_); +} +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +template +struct Value< Matrix > +{ + typedef TValue Type; +}; + +////////////////////////////////////////////////////////////////////////////// + +template +struct Iterator< Matrix, TIteratorSpec > +{ + typedef Iter, PositionIterator> Type; +}; + +template +struct Iterator< Matrix const, TIteratorSpec > +{ + typedef Iter const, PositionIterator> Type; +}; + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +template +inline typename Size const>::Type +dimension(Matrix const & me) +{ + return length(_dataLengths(me)); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +setDimension(Matrix & me, + unsigned int dim_) +{ + + SEQAN_ASSERT_GT(dim_, 0u); +//std::cout<<"\npress enter1\n"; +//std::cin.get(); + resize(_dataLengths(me), dim_, 0); + + resize(_dataFactors(me), dim_); + _dataFactors(me)[0] = 1; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline typename Size >::Type +length(Matrix const & me, + unsigned int dim_) +{ + return me.data_lengths[dim_]; +} + +template +inline typename Size >::Type +length(Matrix const & me) +{ + return length(host(me)); +} + +template +inline bool empty(Matrix const & me) +{ + return empty(host(me)); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +setLength(Matrix & me, + unsigned int dim_, + TLength length_) +{ + SEQAN_ASSERT_GT(length_, static_cast(0)); + SEQAN_ASSERT_LT(dim_, dimension(me)); + + typedef typename SizeArr_ >::TSize_ TSize_; + + _dataLengths(me)[dim_] = static_cast(length_); +} + +////////////////////////////////////////////////////////////////////////////// + +/*! + * @fn Matrix#resize + * @brief Resize the matrix and fill it with a given value or zeroes. + * + * @signature void resize(matrix[, val]); + * + * @param[in,out] matrix The Matrix to fill. + * @param[in] val The optional value to fill the matrix with. + */ + + +template +inline void +resize(Matrix & me) +{ + typedef Matrix TMatrix; + typedef typename Size::Type TSize; + + unsigned int dimension_ = dimension(me); + + SEQAN_ASSERT_GT(dimension_, 0u); + + TSize factor_ = _dataFactors(me)[0] * length(me, 0); + for (unsigned int i = 1; (factor_ > 0) && (i < dimension_); ++i) + { + _dataFactors(me)[i] = factor_; + factor_ *= length(me, i); + } + + if (factor_ > 0) + { + resize(host(me), factor_); + } +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline void +resize(Matrix & me, TFillValue myValue) //resize the matrix and fill with value +{ + typedef Matrix TMatrix; + typedef typename Size::Type TSize; + + unsigned int dimension_ = dimension(me); + + SEQAN_ASSERT_GT(dimension_, 0u); + + TSize factor_ = _dataFactors(me)[0] * length(me, 0); + for (unsigned int i = 1; (factor_ > 0) && (i < dimension_); ++i) + { + _dataFactors(me)[i] = factor_; + factor_ *= length(me, i); + } + + if (factor_ > 0) + resize(host(me), factor_, myValue); +} + + +////////////////////////////////////////////////////////////////////////////// + +template +inline typename Position >::Type +nextPosition(Matrix & me, + TPosition position_, + unsigned int dimension_) +{ + return position_ + _dataFactors(me)[dimension_]; +} + +template +inline typename Position >::Type +nextPosition(Matrix const & me, + TPosition position_, + unsigned int dimension_) +{ + return position_ + _dataFactors(me)[dimension_]; +} + +template +inline typename Position >::Type +previousPosition(Matrix & me, + TPosition position_, + unsigned int dimension_) +{ + return position_ - _dataFactors(me)[dimension_]; +} + +template +inline typename Position >::Type +previousPosition(Matrix const & me, + TPosition position_, + unsigned int dimension_) +{ + return position_ - _dataFactors(me)[dimension_]; +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline typename Size< Matrix >::Type +coordinate(Matrix const & me, + TPosition position_, + unsigned int dimension_) +{ + SEQAN_ASSERT_LT(dimension_, dimension(me)); + + if (dimension_ < dimension(me) - 1) + { + return (position_ / _dataFactors(me)[dimension_]) % _dataFactors(me)[dimension_ + 1]; + } + else + { + return position_ / _dataFactors(me)[dimension_]; + } +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline typename Iterator, Tag const>::Type +begin(Matrix & me, + Tag const) +{ + return typename Iterator, Tag const >::Type(me, 0); +} +template +inline typename Iterator const, Tag const>::Type +begin(Matrix const & me, + Tag const) +{ + return typename Iterator const, Tag const >::Type(me, 0); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline typename Iterator, Tag const >::Type +end(Matrix & me, + Tag const) +{ + return typename Iterator, Tag const >::Type(me, length(host(me))); +} +template +inline typename Iterator const, Tag const >::Type +end(Matrix const & me, + Tag const) +{ + return typename Iterator, Tag const >::Type(me, length(host(me))); +} + +////////////////////////////////////////////////////////////////////////////// + +template +inline typename Reference >::Type +value(Matrix & me, + TPosition position_) +{ + return value(host(me), position_); +} + +template +inline typename Reference const>::Type +value(Matrix const & me, + TPosition position_) +{ + return value(host(me), position_); +} + +//____________________________________________________________________________ + +//two dimensional value access +template +inline typename Reference >::Type +value(Matrix & me, + TOrdinate1 i1, + TOrdinate2 i2) +{ + return value(host(me), i1 + i2 * _dataFactors(me)[1]); +} + +template +inline typename Reference const>::Type +value(Matrix const & me, + TOrdinate1 i1, + TOrdinate2 i2) +{ + return value(host(me), i1 + i2 * _dataFactors(me)[1]); +} + +//____________________________________________________________________________ + +//3 dimensional value access + +template +inline typename Reference >::Type +value(Matrix & me, + TOrdinate1 i1, + TOrdinate2 i2, + TOrdinate3 i3) +{ + return value(host(me), i1 + i2 * _dataFactors(me)[1] + i3 * _dataFactors(me)[2]); +} + +//____________________________________________________________________________ + +//4 dimensional value access + +template +inline typename Reference >::Type +value(Matrix & me, + TOrdinate1 i1, + TOrdinate2 i2, + TOrdinate3 i3, + TOrdinate4 i4) +{ + return value(host(me), i1 + i2 * _dataFactors(me)[1] + i3 * _dataFactors(me)[2] + i4 * _dataFactors(me)[3]); +} + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +// Iterator: goNext +////////////////////////////////////////////////////////////////////////////// + +template +inline void +goNext(Iter, PositionIterator> & me, + unsigned int dimension_) +{ + setPosition(me, nextPosition(container(me), position(me), dimension_)); +} + +template +inline void +goNext(Iter const, PositionIterator> & me, + unsigned int dimension_) +{ + setPosition(me, nextPosition(container(me), position(me), dimension_)); +} + +template +inline void +goNext(Iter, PositionIterator> & me) +{ + goNext(me, 0); +} + +template +inline void +goNext(Iter const, PositionIterator> & me) +{ + goNext(me, 0); +} + +////////////////////////////////////////////////////////////////////////////// +// Iterator: goPrevious +////////////////////////////////////////////////////////////////////////////// + +template +inline void +goPrevious(Iter< Matrix, PositionIterator > & me, + unsigned int dimension_) +{ + setPosition(me, previousPosition(container(me), position(me), dimension_)); +} + +template +inline void +goPrevious(Iter< Matrix const, PositionIterator > & me, + unsigned int dimension_) +{ + setPosition(me, previousPosition(container(me), position(me), dimension_)); +} + +template +inline void +goPrevious(Iter< Matrix, PositionIterator > & me) +{ + goPrevious(me, 0); +} + +template +inline void +goPrevious(Iter< Matrix const, PositionIterator > & me) +{ + goPrevious(me, 0); +} + +////////////////////////////////////////////////////////////////////////////// +// goTo +////////////////////////////////////////////////////////////////////////////// + +template +inline void +goTo(Iter, PositionIterator> & me, TPosition0 pos0, TPosition1 pos1) +{ + setPosition(me, pos0 + pos1 * _dataFactors(container(me))[1]); +} + + +template +inline void +goTo(Iter const, PositionIterator> & me, TPosition0 pos0, TPosition1 pos1) +{ + setPosition(me, pos0 + pos1 * _dataFactors(container(me))[1]); +} + + +template +inline void +goTo(Iter, PositionIterator> & me, TPosition0 pos0, TPosition1 pos1, TPosition2 pos2) +{ + setPosition(me, pos0 + pos1 * _dataFactors(container(me))[1] + pos2 * _dataFactors(container(me))[2]); +} + + +template +inline void +goTo(Iter const, PositionIterator> & me, TPosition0 pos0, TPosition1 pos1, TPosition2 pos2) +{ + setPosition(me, pos0 + pos1 * _dataFactors(container(me))[1] + pos2 * _dataFactors(container(me))[2]); +} + +////////////////////////////////////////////////////////////////////////////// +// Iterator: coordinate + +template +inline typename Size< Matrix >::Type +coordinate(Iter, PositionIterator > & me, + unsigned int dimension_) +{ + return coordinate(container(me), position(me), dimension_); +} + +template +inline typename Size< Matrix >::Type +coordinate(Iter const, PositionIterator > & me, + unsigned int dimension_) +{ + return coordinate(container(me), position(me), dimension_); +} + +/*! + * @fn Matrix::operator+ + * @brief Sum operator for the Matrix type. + * + * @signature TMatrix Matrix::operator+(lhs, rhs); + * + * @param[in] lhs First summand. + * @param[in] rhs Second summand. + * + * @return TMatrix The resulting matrix of same type as lhs and rhs. + */ + +template +Matrix +operator + (Matrix const & matrix1,Matrix const & matrix2) +{ + //the two matrices must have same dimension + SEQAN_ASSERT(_dataLengths(matrix1) == _dataLengths(matrix2)); + + Matrix result; + //copy the first matrix + setDimension(result,length(_dataLengths(matrix1))); + _dataLengths(result) = _dataLengths(matrix1); + resize(result); + + //add the matrices + for(unsigned int i = 0;i< length(host(result));++i) + { + value(host(result), i)=value(host(matrix1), i)+value(host(matrix2), i); + } + //Return matrix sum + return result; +} + +template +Matrix +operator - (Matrix const & matrix1,Matrix const & matrix2) +{ + //the two matrices must have same dimension + SEQAN_ASSERT(_dataLengths(matrix1) == _dataLengths(matrix2)); + + Matrix result; + //resize the matrix + setDimension(result,length(_dataLengths(matrix1))); + _dataLengths(result) = _dataLengths(matrix1); + resize(result); + + //subtract the matrices + for(unsigned int i = 0;i< length(host(result));++i) + { + value(host(result), i)=value(host(matrix1), i)-value(host(matrix2), i); + } + //Return matrix difference + return result; +} + +template +Matrix +operator * (Matrix const & matrix1, Matrix const & matrix2) +{ + SEQAN_ASSERT_EQ(length(matrix1,1), length(matrix2,0)); + + unsigned int nrow1=length(matrix1,0); + unsigned int ncol2=length(matrix2,1); + Matrix result; + //resize the matrix + setLength(result, 0, nrow1); + setLength(result, 1, ncol2); + resize(result,(TValue) 0); + + //Matrix product + for(unsigned int row = 0; row < nrow1; row++) + { + for(unsigned int col = 0; col < ncol2; col++) + { + for(unsigned int colRes = 0; colRes < length(matrix1,1); colRes++) + { + value(result,row,col)+= value(host(matrix1), row + colRes * matrix1.data_factors[1])*value(host(matrix2), colRes + col * matrix2.data_factors[1]); + } + } + } + //return the matrix product + return result; +} + + +template +Matrix +operator * (TValue const & scalar, Matrix const & matrix) +{ + Matrix result; + result= matrix; + //scalar multiplication + for(unsigned int i = 0;i< length(host(result));++i) + { + value(host(result), i)*=scalar; + } + //return the matrix product + return result; +} + +template +Matrix +operator * (Matrix const & matrix, TValue const & scalar) +{ + Matrix result; + result= matrix; + //scalar multiplication + for(unsigned int i = 0;i< length(host(result));++i) + { + value(host(result), i)*=scalar; + } + //return the matrix product + return result; +} + + +template +bool +operator == (Matrix const & matrix1, Matrix const & matrix2) +{ + bool result; + result= (matrix1.data_lengths==matrix2.data_lengths)&&(matrix1.data_factors==matrix2.data_factors)&&(value(matrix1.data_host)==value(matrix2.data_host))&&(DIMENSION1==DIMENSION2); + return result; +} + +/* +template +Matrix +matricialSum(Matrix &matrix1,Matrix &matrix2) +{ + //the two matrices must have same dimension + if(length(matrix1,0) != length(matrix2,0)||length(matrix1,1) != length(matrix2,1)) + { + fprintf(stderr,"Error: The two matrices have different dimensions"); + } + + + unsigned int nrow=length(matrix1,0); + unsigned int ncol=length(matrix1,1); + + Matrix result; + //resize the matrix + setLength(result, 0, nrow); + setLength(result, 1, ncol); + resize(result); + + //add the matrices + for(unsigned int i = 0;i< nrow*ncol;++i) + { + value(host(result), i)=value(host(matrix1), i)+value(host(matrix2), i); + } + //Return matrix difference + return result; + +} +*/ +////////////////////////////////////////////////////////////////////////////// +// _matricialDifference +////////////////////////////////////////////////////////////////////////////// + +/* +template +inline Matrix +matricialDifference(Matrix & matrix1, Matrix & matrix2) +{ + //the two matrices must have same dimension + if(length(matrix1,0) != length(matrix2,0)||length(matrix1,1) != length(matrix2,1)) + { + fprintf(stderr,"Error: The two matrices have different dimensions"); + } + + unsigned int nrow=length(matrix1,0); + unsigned int ncol=length(matrix1,1); + + Matrix result; + //resize the matrix + //setDimension(result, 2); + setLength(result, 0, nrow); + setLength(result, 1, ncol); + resize(result); + + //Substract the matrices + for(unsigned int i1 = 0;i1< nrow;++i1) + { + for(unsigned int i2 = 0;i2 +inline Matrix +matricialProduct(Matrix &matrix1, + Matrix &matrix2) +{ + //SEQAN_ASSERT_LT(dimension_, dimension(me)); + if(length(matrix1,1) != length(matrix2,0)) + { + fprintf(stderr,"Error: Number of columns of matrix1 is unequal to number of rows of matrix2"); + } + + unsigned int nrow1=length(matrix1,0); + unsigned int ncol2=length(matrix2,1); + Matrix result; + //resize the matrix + setLength(result, 0, nrow1); + setLength(result, 1, ncol2); + resize(result,(TValue) 0); + + //Matrix product + for(unsigned int row = 0; row < nrow1; row++) + { + for(unsigned int col = 0; col < ncol2; col++) + { + for(unsigned int colRes = 0; colRes < length(matrix1,1); colRes++) + { + value(result,row,col)+=value(matrix1, row,colRes)*value(matrix2,colRes,col); + } + } + } + //return the matrix product + return result; +} +*/ + +/*! + * @fn Matrix#transpose + * @brief Tranpose a 2D Matrix. + * + * @signature TMatrix transpose(matrix); + * + * @param[in] matrix The matrix to tranpose. + * @return TMatrix The resulting tranposed matrix. + */ + +template +Matrix +transpose(Matrix const & matrix) +{ + + unsigned int nrow=length(matrix,0); + unsigned int ncol=length(matrix,1); + + Matrix result; + //resize the matrix + setLength(result, 0, ncol); + setLength(result, 1, nrow); + resize(result); + + + for(unsigned int i1 = 0;i1< nrow;++i1) + { + for(unsigned int i2 = 0;i2 +std::ostream& operator<<(std::ostream &out, const Matrix &matrix) +{ + for(unsigned int i1 = 0;i1< matrix.data_lengths[0];++i1) + { + for(unsigned int i2 = 0;i2<(matrix.data_lengths[1]-1);++i2) + { + out< +// void read(FILE *file, Matrix & matrix) +// { +// //unsigned int column_size=3; +// unsigned int column_size=pow(4,5); +// //read the transition matrix +// setLength(matrix, 0, column_size); +// setLength(matrix, 1, column_size); +// resize(matrix,0.0); +// for(unsigned int row=0; row +// ========================================================================== +// Extras for the align module +// ========================================================================== + +#ifndef SEQAN_ALIGN_EXTEND_H +#define SEQAN_ALIGN_EXTEND_H + +#include +#include +#include + +#include +#include +#include + +#endif diff --git a/seqan/align_extend/align_extend.h b/seqan/align_extend/align_extend.h new file mode 100644 index 0000000..f5459fb --- /dev/null +++ b/seqan/align_extend/align_extend.h @@ -0,0 +1,647 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Hannes Hauswedell +// ========================================================================== +// This file contains routines to extend an existing Align object +// ========================================================================== + +#ifndef INCLUDE_ALIGN_ALIGN_EXTEND_H +#define INCLUDE_ALIGN_ALIGN_EXTEND_H + +namespace seqan { + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class AliExtContext_ +// ---------------------------------------------------------------------------- + +// Context with memory holding objects for alignment extension +// This can be reused to prevent repeated memory allocations +template +struct AliExtContext_ +{ + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + + TGaps0 leftRow0, centerRow0, rightRow0; + TGaps1 leftRow1, centerRow1, rightRow1; + + TDPContext dpContext; + + String > traceSegment; +}; + +template +inline void +clear(AliExtContext_ & prov) +{ + // gaps don't need to be cleared, because they are always + // re-assigned before use; dpContext, too! + + // trace segment always needs to be cleared + clear(prov.traceSegment); + // dpContext doesn't need to be cleared +} + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _reverseTrace() +// ---------------------------------------------------------------------------- + +// Reverse a trace string and adapt internal position. +template +void _reversePartialTrace(String, TSpec> & trace, + TPos2 const lengthH, + TPos2 const lengthV) +{ + typedef String, TSpec> TTrace; + typedef typename Iterator::Type TTraceIter; + + if (empty(trace)) + return; + + for (TTraceIter it = begin(trace, Rooted()); !atEnd(it); goNext(it)) + { + it->_horizontalBeginPos = lengthH - _getEndHorizontal(*it); + it->_verticalBeginPos = lengthV - _getEndVertical(*it); + } + reverse(trace); +} + +// ---------------------------------------------------------------------------- +// Function _setUpAndRunAlignImpl() +// ---------------------------------------------------------------------------- + +template +inline TScoreValue +_setUpAndRunAlignImpl(TAliExtContext_ & alignContext, + TString0 const & str0, + TString1 const & str1, + Score const & scoreScheme, + int const /*lowerDiag*/, + int const /*upperDiag*/, + TScoreValue const /*xDrop*/, + TTracebackConfig const & /*gapOrientation*/, + False const & /*TBoolBanded*/, + False const & /*TBoolXDrop*/) +{ + typedef FreeEndGaps_ TFreeEndGaps; + typedef AlignConfig2, DPBandConfig, TFreeEndGaps, + TracebackOn > > TAlignConfig; + + DPScoutState_ scoutState; + return _setUpAndRunAlignment(alignContext.dpContext, alignContext.traceSegment, scoutState, str0, str1, scoreScheme, + TAlignConfig()); +} + +template +inline TScoreValue +_setUpAndRunAlignImpl(TAliExtContext_ & alignContext, + TString0 const & str0, + TString1 const & str1, + Score const & scoreScheme, + int const lowerDiag, + int const upperDiag, + TScoreValue const /*xDrop*/, + TTracebackConfig const & /*gapOrientation*/, + True const & /*TBoolBanded*/, + False const & /*TBoolXDrop*/) +{ + typedef FreeEndGaps_ TFreeEndGaps; + typedef AlignConfig2, DPBandConfig, TFreeEndGaps, + TracebackOn > > TAlignConfig; + + DPScoutState_ scoutState; + return _setUpAndRunAlignment(alignContext.dpContext, alignContext.traceSegment, scoutState, str0, str1, scoreScheme, + TAlignConfig(lowerDiag, upperDiag)); +} + +template +inline TScoreValue +_setUpAndRunAlignImpl(TAliExtContext_ & alignContext, + TString0 const & str0, + TString1 const & str1, + Score const & scoreScheme, + int const /*lowerDiag*/, + int const /*upperDiag*/, + TScoreValue const xDrop, + TTracebackConfig const & /*gapOrientation*/, + False const & /*TBoolBanded*/, + True const & /*TBoolXDrop*/) +{ + typedef FreeEndGaps_ TFreeEndGaps; + typedef AlignConfig2 >, DPBandConfig, TFreeEndGaps, + TracebackOn > > TAlignConfig; + + DPScoutState_ > > scoutState(xDrop); + return _setUpAndRunAlignment(alignContext.dpContext, alignContext.traceSegment, scoutState, str0, str1, scoreScheme, + TAlignConfig()); +} + +template +inline TScoreValue +_setUpAndRunAlignImpl(TAliExtContext_ & alignContext, + TString0 const & str0, + TString1 const & str1, + Score const & scoreScheme, + int const lowerDiag, + int const upperDiag, + TScoreValue const xDrop, + TTracebackConfig const & /*gapOrientation*/, + True const & /*TBoolBanded*/, + True const & /*TBoolXDrop*/) +{ + typedef FreeEndGaps_ TFreeEndGaps; + typedef AlignConfig2 >, DPBandConfig, TFreeEndGaps, + TracebackOn > > TAlignConfig; + + DPScoutState_ > > scoutState(xDrop); + return _setUpAndRunAlignment(alignContext.dpContext, alignContext.traceSegment, scoutState, str0, str1, scoreScheme, + TAlignConfig(lowerDiag, upperDiag)); +} + +// ---------------------------------------------------------------------------- +// Function _extendAlignmentImpl() +// ---------------------------------------------------------------------------- + +template +inline TScoreValue +_extendAlignmentImpl(Gaps & row0, + Gaps & row1, + TScoreValue const & origScore, + TString0 const & hSeq, + TString1 const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + int const lowerDiag, + int const upperDiag, + TScoreValue const & xDrop, + Score const & scoreScheme, + TBoolBanded const & /**/, + TBoolXDrop const & /**/, + TAliExtContext_ & alignContext) +{ + typedef typename Infix::Type TInf0; + typedef typename Infix::Type TInf1; + + TPos const hBeginPos = positions[0]; + TPos const vBeginPos = positions[1]; + TPos const hEndPos = positions[2]; + TPos const vEndPos = positions[3]; + + SEQAN_ASSERT_EQ(infix(source(row0), beginPosition(row0), endPosition(row0)), + infix(hSeq, hBeginPos, hEndPos)); + SEQAN_ASSERT_EQ(infix(source(row1), beginPosition(row1), endPosition(row1)), + infix(vSeq, vBeginPos, vEndPos)); + + bool extendLeft = ((direction & EXTEND_LEFT) && (hBeginPos > 0u) && (vBeginPos > 0u)); + bool extendRight = ((direction & EXTEND_RIGHT) && (hEndPos < length(hSeq)) && (vEndPos < length(vSeq))); + + clear(alignContext); + alignContext.centerRow0 = row0; + alignContext.centerRow1 = row1; + + TScoreValue leftScore = 0; + TScoreValue centerScore = origScore; + TScoreValue rightScore = 0; + + TPos newAlignLen = length(row0); + + // centerScore was set to "compute yourself" by interface function without score parameter + if (centerScore == minValue()) + { + centerScore = 0; + + for (TPos i = 0; i < length(row0); ++i) + { + if ( ( isGap(row0, i)) || ( isGap(row1, i)) ) + { + if (( i==0 ) || + (isGap(row0, i-1) != isGap(row0, i)) || + (isGap(row1, i-1) != isGap(row1, i)) ) + { + centerScore += scoreGapOpen(scoreScheme); + } + else + { + centerScore += scoreGapExtend(scoreScheme); + } + } + else + { + centerScore += score(scoreScheme, row0[i], row1[i]); + } + } + } + + // "reset" original alignment to full length on sequences and no gaps + assignSource(row0, infix(hSeq, 0, length(hSeq))); + assignSource(row1, infix(vSeq, 0, length(vSeq))); + + // left + if (extendLeft) + { + TInf0 inf0 = infix(hSeq, 0, hBeginPos); + TInf1 inf1 = infix(vSeq, 0, vBeginPos); + + // reverse input + ModifiedString const r_inf0(inf0); + ModifiedString const r_inf1(inf1); + + leftScore = _setUpAndRunAlignImpl(alignContext, r_inf0, r_inf1, scoreScheme, lowerDiag, upperDiag, xDrop, + TracebackConfig_(), TBoolBanded(), TBoolXDrop()); + // un-reverve + _reversePartialTrace(alignContext.traceSegment, length(inf0), length(inf1)); + + setSource(alignContext.leftRow0, inf0); + setSource(alignContext.leftRow1, inf1); + + _adaptTraceSegmentsTo(alignContext.leftRow0, alignContext.leftRow1, alignContext.traceSegment); + + if (length(alignContext.leftRow0) > 0) + { + integrateGaps(row0, alignContext.leftRow0); + integrateGaps(row1, alignContext.leftRow1); + setClippedBeginPosition(row0, clippedBeginPosition(alignContext.leftRow0)); + setClippedBeginPosition(row1, clippedBeginPosition(alignContext.leftRow1)); + + newAlignLen += length(alignContext.leftRow0); + } + else + { + extendLeft = false; + } + } + + // center + if (extendLeft) + { + integrateGaps(row0, alignContext.centerRow0, length(alignContext.leftRow0)); + integrateGaps(row1, alignContext.centerRow1, length(alignContext.leftRow1)); + } + else + { + integrateGaps(row0, alignContext.centerRow0, hBeginPos); + integrateGaps(row1, alignContext.centerRow1, vBeginPos); + TPos leadGaps0 = countGaps(begin(alignContext.centerRow0)); + TPos leadGaps1 = countGaps(begin(alignContext.centerRow1)); + + TPos sourceBeginPos0 = toSourcePosition(alignContext.centerRow0, leadGaps0) + hBeginPos - + beginPosition(alignContext.centerRow0); + TPos sourceBeginPos1 = toSourcePosition(alignContext.centerRow1, leadGaps1) + vBeginPos - + beginPosition(alignContext.centerRow1); + + setClippedBeginPosition(row0, toViewPosition(row0, sourceBeginPos0) - leadGaps0); + setClippedBeginPosition(row1, toViewPosition(row1, sourceBeginPos1) - leadGaps1); + } + + // right + if (extendRight) + { + TInf0 inf0 = infix(hSeq, hEndPos, length(hSeq)); + TInf1 inf1 = infix(vSeq, vEndPos, length(vSeq)); + + clear(alignContext.traceSegment); + rightScore = _setUpAndRunAlignImpl(alignContext, inf0, inf1, scoreScheme, lowerDiag, upperDiag, xDrop, + TracebackConfig_(), TBoolBanded(), TBoolXDrop()); + + setSource(alignContext.rightRow0, inf0); + setSource(alignContext.rightRow1, inf1); + _adaptTraceSegmentsTo(alignContext.rightRow0, alignContext.rightRow1, alignContext.traceSegment); + + if (length(alignContext.rightRow0) > 0) + { + integrateGaps(row0, alignContext.rightRow0); + integrateGaps(row1, alignContext.rightRow1); + + newAlignLen += length(alignContext.rightRow0); + } + } + + setClippedEndPosition(row0, clippedBeginPosition(row0) + newAlignLen); + setClippedEndPosition(row1, clippedBeginPosition(row1) + newAlignLen); + + return leftScore + centerScore + rightScore; +} + +// get rows from align object +template +inline TScoreValue +_extendAlignmentImpl(Align & align, + TScoreValue const & origScore, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + int const lowerDiag, + int const upperDiag, + TScoreValue const & xDrop, + Score const & scoreScheme, + TBoolBanded const & /**/, + TBoolXDrop const & /**/, + TAliExtContext_ & alignContext) +{ + SEQAN_ASSERT_EQ_MSG(length(rows(align)), 2u, "Only works with pairwise alignments."); + SEQAN_ASSERT_EQ_MSG(length(row(align, 0)), length(row(align, 1)), "Invalid alignment!"); + + return _extendAlignmentImpl(row(align, 0), row(align, 1), origScore, hSeq, vSeq, positions, direction, lowerDiag, + upperDiag, xDrop, scoreScheme, TBoolBanded(), TBoolXDrop(), alignContext); +} + +// create AlignContext +template +inline TScoreValue +_extendAlignmentImpl(Align & align, + TScoreValue const & origScore, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + int const lowerDiag, + int const upperDiag, + TScoreValue const & xDrop, + Score const & scoreScheme, + TBoolBanded const & /**/, + TBoolXDrop const & /**/) +{ + if (scoreGapOpen(scoreScheme) == scoreGapExtend(scoreScheme)) + { + typedef DPContext TDPContext; + typedef AliExtContext_, + Gaps, + TDPContext> TAliExtContext_; + TAliExtContext_ alignContext; + return _extendAlignmentImpl(align, origScore, hSeq, vSeq, positions, direction, lowerDiag, upperDiag, xDrop, + scoreScheme, TBoolBanded(), TBoolXDrop(), alignContext); + } + else + { + typedef DPContext TDPContext; + typedef AliExtContext_, + Gaps, + TDPContext> TAliExtContext_; + TAliExtContext_ alignContext; + return _extendAlignmentImpl(align, origScore, hSeq, vSeq, positions, direction, lowerDiag, upperDiag, xDrop, + scoreScheme, TBoolBanded(), TBoolXDrop(), alignContext); + } +} + +// ---------------------------------------------------------------------------- +// Function extendAlignment() +// ---------------------------------------------------------------------------- + +/*! + * @fn extendAlignment + * @headerfile + * @brief X-Drop extension for alignment objects. + * @signature TScoreValue extendAlignment(align, [origScore,] hSeq, vSeq, positions, extensionDirection, + * [lowerDiag, upperDiag,] [xDrop,] scoreScheme); + * + * @param[in,out] align The @link Align @endlink object to work on. Must be an alignment over the + * @link InfixSegment infix @endlink of the const type of hSeq + * and vSeq. Also see section "Returned Alignment". + * @param[in] origScore Original score value of the alignment (optional; computed if not provided). + * @param[in] hSeq Full horizontal sequence. + * @param[in] vSeq Full vertical sequence. + * @param[in] positions A @link Tuple @endlink of length 4 with the begin and end position of the + * infixes in align. + * @param[in] extensionDirection + * The extension direction (@link ExtensionDirection @endlink). + * @param[in] lowerDiag Lower alignment diagonal to use (int). + * @param[in] upperDiag Upper alignment diagonal to use (int). + * @param[in] xDrop The X-drop value to use (integral value). It only limits computation of new + * columns in the DP-Matrix and has no influence on the diagonals (but can be combined with them). + * @param[in] scoringScheme + * The @link Score @endlink to use. + * + * @return TScoreValue + * The score of the new alignment. TScoreValue is the value type of + * scoringScheme. + * + * @section Returned Alignment + * + * The resulting alignment has the infixes extended to the whole underlying sequence. The alignment + * is clipped to give the parts of the aligned sequences. + * + * @section Example + * + * @include demos/dox/align_extend/extend_alignment.cpp + * + * The output is as follows: + * + * @include demos/dox/align_extend/extend_alignment.cpp.stdout + * + * @section Remarks + * + * It is necessary to explicitly pass hSeq, vSeq and the positions, because the + * original hSeq and vSeq (that Align was created on), might have been infixes, + * (especially if they are members of a ConcatDirect set) in which cases their + * actual begin and end positions cannot be inferred from the Align object's + * rows' source(). + */ + +// NO BAND, NO XDROP +template +inline TScoreValue +extendAlignment(Align & align, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + Score const & scoreScheme) +{ + return _extendAlignmentImpl(align, minValue(), hSeq, vSeq, positions, direction, 0, 0, 0, scoreScheme, + False(), False()); +} + +template +inline TScoreValue +extendAlignment(Align & align, + TScoreValue const & origScore, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + Score const & scoreScheme) +{ + return _extendAlignmentImpl(align, origScore, hSeq, vSeq, positions, direction, 0, 0, 0, scoreScheme, False(), + False()); +} + +// BAND, NO XDROP +template +inline TScoreValue +extendAlignment(Align & align, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + int const lowerDiag, + int const upperDiag, + Score const & scoreScheme) +{ + return _extendAlignmentImpl(align, minValue(), hSeq, vSeq, positions, direction, lowerDiag, upperDiag, + 0, scoreScheme, True(), False()); +} + +template +inline TScoreValue +extendAlignment(Align & align, + TScoreValue const & origScore, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + int const lowerDiag, + int const upperDiag, + Score const & scoreScheme) +{ + return _extendAlignmentImpl(align, origScore, hSeq, vSeq, positions, direction, lowerDiag, upperDiag, 0, + scoreScheme, True(), False()); +} + +// NO BAND, XDROP +template +inline TScoreValue +extendAlignment(Align & align, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + TScoreValue const & xDrop, + Score const & scoreScheme) +{ + return _extendAlignmentImpl(align, minValue(), hSeq, vSeq, positions, direction, 0, 0, xDrop, + scoreScheme, False(), True()); +} + +template +inline TScoreValue +extendAlignment(Align & align, + TScoreValue const & origScore, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + TScoreValue const & xDrop, + Score const & scoreScheme) +{ + return _extendAlignmentImpl(align, origScore, hSeq, vSeq, positions, direction, 0, 0, xDrop, scoreScheme, False(), + True()); +} + +// BAND, XDROP +template +inline TScoreValue +extendAlignment(Align & align, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + int const lowerDiag, + int const upperDiag, + TScoreValue const & xDrop, + Score const & scoreScheme) +{ + return _extendAlignmentImpl(align, minValue(), hSeq, vSeq, positions, direction, lowerDiag, upperDiag, + xDrop, scoreScheme, True(), True()); +} + +template +inline TScoreValue +extendAlignment(Align & align, + TScoreValue const & origScore, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + int const lowerDiag, + int const upperDiag, + TScoreValue const & xDrop, + Score const & scoreScheme) +{ + return _extendAlignmentImpl(align, origScore, hSeq, vSeq, positions, direction, lowerDiag, upperDiag, xDrop, + scoreScheme, True(), True()); +} + +template +inline TScoreValue +extendAlignment(Align & align, + TAliExtContext & alignContext, + TScoreValue const & origScore, + TString const & hSeq, + TString const & vSeq, + Tuple const & positions, + ExtensionDirection const & direction, + int const lowerDiag, + int const upperDiag, + TScoreValue const & xDrop, + Score const & scoreScheme) +{ + return _extendAlignmentImpl(align, origScore, hSeq, vSeq, positions, direction, lowerDiag, upperDiag, xDrop, + scoreScheme, True(), True(), alignContext); +} + +} + +#endif // INCLUDE_ALIGN_ALIGN_EXTEND_H diff --git a/seqan/align_extend/align_extend_base.h b/seqan/align_extend/align_extend_base.h new file mode 100644 index 0000000..336daed --- /dev/null +++ b/seqan/align_extend/align_extend_base.h @@ -0,0 +1,201 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Hannes Hauswedell +// ========================================================================== +// This file contains routines to extend an existing Align object +// ========================================================================== + + +#ifndef INCLUDE_ALIGN_ALIGN_EXTEND_BASE_H +#define INCLUDE_ALIGN_ALIGN_EXTEND_BASE_H + +namespace seqan { + + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +template +struct AlignExtend_ +{ +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + + +// overrides for AligExtend general case +template +struct SetupAlignmentProfile_, TAlignConfig, TGapCosts, + TTraceSwitch> +{ + typedef DPProfile_, TGapCosts, TracebackOn<> > Type; +}; + +template +struct TraceTail_ > : False +{}; + +template +struct TraceHead_ > : True +{}; + +template +struct IsFreeEndGap_, DPLastRow> : True +{}; + +template +struct IsFreeEndGap_, DPLastColumn> : True +{}; + + + +// ---------------------------------------------------------------------------- +// Class DPMetaColumn_ [FullColumn] +// ---------------------------------------------------------------------------- + +template +struct DPMetaColumn_, TGapCosts, + TTraceback>, + MetaColumnDescriptor > +{ + + typedef typename If, RecursionDirectionZero, + RecursionDirectionHorizontal + >::Type TRecursionTypeFirstCell_; + typedef typename If, RecursionDirectionVertical, + RecursionDirectionAll + >::Type TRecursionTypeInnerCell_; + typedef typename If, RecursionDirectionVertical, + RecursionDirectionAll + >::Type TRecursionTypeLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + + +// ---------------------------------------------------------------------------- +// Class DPMetaColumn_ [PartialColumnTop] +// ---------------------------------------------------------------------------- + +template +struct DPMetaColumn_, TGapCosts, + TTraceback>, + MetaColumnDescriptor > +{ + + typedef typename If, RecursionDirectionZero, + RecursionDirectionHorizontal + >::Type TRecursionTypeFirstCell_; + typedef typename If, RecursionDirectionVertical, + RecursionDirectionAll + >::Type TRecursionTypeInnerCell_; + typedef typename If, RecursionDirectionVertical, + RecursionDirectionLowerDiagonal + >::Type TRecursionTypeLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + +// ---------------------------------------------------------------------------- +// Class DPMetaColumn_ [PartialColumnMiddle] +// ---------------------------------------------------------------------------- + +template +struct DPMetaColumn_, TGapCosts, + TTraceback>, + MetaColumnDescriptor > +{ + typedef typename If, RecursionDirectionZero, + RecursionDirectionUpperDiagonal + >::Type TRecursionTypeFirstCell_; + typedef typename If, RecursionDirectionVertical, + RecursionDirectionAll + >::Type TRecursionTypeInnerCell_; + typedef typename If, RecursionDirectionVertical, + RecursionDirectionLowerDiagonal + >::Type TRecursionTypeLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + +// ---------------------------------------------------------------------------- +// Class DPMetaColumn_ [PartialColumnBottom] +// ---------------------------------------------------------------------------- + +template +struct DPMetaColumn_, TGapCosts, + TTraceback>, + MetaColumnDescriptor > +{ + typedef typename If, RecursionDirectionZero, + RecursionDirectionUpperDiagonal + >::Type TRecursionTypeFirstCell_; + typedef typename If, RecursionDirectionVertical, + RecursionDirectionAll + >::Type TRecursionTypeInnerCell_; + typedef typename If, RecursionDirectionVertical, + RecursionDirectionAll + >::Type TRecursionTypeLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + +} +#endif diff --git a/seqan/align_extend/dp_scout_xdrop.h b/seqan/align_extend/dp_scout_xdrop.h new file mode 100644 index 0000000..8331f22 --- /dev/null +++ b/seqan/align_extend/dp_scout_xdrop.h @@ -0,0 +1,206 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Hannes Hauswedell +// ========================================================================== +// This file contains routines to extend an existing Align object +// ========================================================================== + +#ifndef INCLUDE_SEQAN_ALIGN_DP_SCOUT_EXTEND_H_ +#define INCLUDE_SEQAN_ALIGN_DP_SCOUT_EXTEND_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Tag XDropScout. +// ---------------------------------------------------------------------------- + +template +struct XDrop_ +{ +}; + +// ---------------------------------------------------------------------------- +// Class DPScoutState_ +// ---------------------------------------------------------------------------- + +template +class DPScoutState_ > > +{ +public: + TScoreValue const terminationThreshold; + TScoreValue columnMax; + + DPScoutState_() : + terminationThreshold(MaxValue::VALUE), + columnMax(MinValue::VALUE) + { + } + + DPScoutState_(TScoreValue const & _terminationThreshold) : + terminationThreshold(_terminationThreshold), + columnMax(MinValue::VALUE) + { + } +}; + + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// overrides for AligExtend XDrop case +template +struct HasTerminationCriterium_ > > : True {}; + +template +struct ScoutSpecForAlignmentAlgorithm_ >, DPScoutState_ > +{ + typedef Terminator_ > Type; +}; + +template +struct ScoutSpecForAlignmentAlgorithm_ > const, DPScoutState_ > +{ + typedef Terminator_ > Type; +}; + +template +struct ScoutStateSpecForScout_< + DPScout_< + TDPCell, Terminator_::Type> > > > +{ + typedef Terminator_::Type> > Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _scoutBestScore() [DPScout_] +// ---------------------------------------------------------------------------- + +// NOTE: The original code here used Value::Type instead of TDPCellValue but this caused ambiguous call +// errors in MSVC. + +template +inline void +_scoutBestScore(DPScout_ > > & dpScout, + TDPCell const & activeCell, + TTraceMatrixNavigator const & navigator, + TIsLastColumn const & /**/, + False const & /*IsLastRow*/) +{ + typedef typename Value::Type TScoreValue; + typedef XDrop_ TXDrop; + typedef DPScout_ > TDPScout; + typedef typename TDPScout::TParent TParent; + + // global maximum + _scoutBestScore(static_cast( dpScout ), activeCell, navigator); + + // column maximum + dpScout.state->columnMax = _max(dpScout.state->columnMax, _scoreOfCell(activeCell)); +} + +template +inline void +_scoutBestScore(DPScout_ > > & dpScout, + TDPCell const & activeCell, + TTraceMatrixNavigator const & navigator, + TIsLastColumn const & /**/, + True const & /*IsLastRow*/) +{ + typedef typename Value::Type TScoreValue; + + _scoutBestScore(dpScout, activeCell, navigator, TIsLastColumn(), False()); + + // check termination condition + if (_scoreOfCell(dpScout._maxScore) - dpScout.state->columnMax >= dpScout.state->terminationThreshold) + terminateScout(dpScout); + else // reset columMax at end of column + dpScout.state->columnMax = MinValue::VALUE; +} + +// ---------------------------------------------------------------------------- +// Function _scoutBestScore() [DPScout_] +// ---------------------------------------------------------------------------- + +// Computes the score and tracks it if enabled. +template +inline void +_computeCell(TDPScout & scout, + TTraceMatrixNavigator & traceMatrixNavigator, + DPCell_ & activeCell, + DPCell_ const & previousDiagonal, + DPCell_ const & previousHorizontal, + DPCell_ const & previousVertical, + TSequenceHValue const & seqHVal, + TSequenceVValue const & seqVVal, + TScoringScheme const & scoringScheme, + TColumnDescriptor const &, + TCellDescriptor const &, // One of FirstCell, InnerCell or LastCell. + DPProfile_ >, TGapCosts, + TTraceback> const &) +{ + typedef DPProfile_ >, TGapCosts, TTraceback> TDPProfile; + typedef DPMetaColumn_ TMetaColumn; + + assignValue(traceMatrixNavigator, _computeScore(activeCell, previousDiagonal, previousHorizontal, previousVertical, + seqHVal, seqVVal, scoringScheme, + typename RecursionDirection_::Type(), + TDPProfile())); + if (TrackingEnabled_::VALUE) + { + typedef typename IsSameType< typename TColumnDescriptor::TColumnProperty, DPFinalColumn>::Type TIsLastColumn; + + // the following is the only change to the regular _computeCell: + // for the evaluation of the termination criterium we treat + // all lastCells as lastRows + typedef typename IsSameType::Type TIsLastRow; + _scoutBestScore(scout, activeCell, traceMatrixNavigator, TIsLastColumn(), TIsLastRow()); + } +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_ALIGN_DP_SCOUT_EXTEND_H_ diff --git a/seqan/align_profile.h b/seqan/align_profile.h new file mode 100644 index 0000000..f9436f8 --- /dev/null +++ b/seqan/align_profile.h @@ -0,0 +1,57 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for module align_profile. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_ALIGN_PROFILE_H_ +#define INCLUDE_SEQAN_ALIGN_PROFILE_H_ + +// =========================================================================== +// Prerequisites +// =========================================================================== + +#include +#include +#include +#include +#include + +// =========================================================================== +// Module Contents +// =========================================================================== + +#include +#include + +#endif // INCLUDE_SEQAN_ALIGN_PROFILE_H_ diff --git a/seqan/align_profile/add_to_profile.h b/seqan/align_profile/add_to_profile.h new file mode 100644 index 0000000..76f035d --- /dev/null +++ b/seqan/align_profile/add_to_profile.h @@ -0,0 +1,165 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Algorithm for profile-to-sequence alignment that then adds the resulting +// sequence alignment to the profile. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_PROFILE_ADD_TO_PROFILE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_PROFILE_ADD_TO_PROFILE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function addToProfile() +// ---------------------------------------------------------------------------- + +/*! + * @fn addToProfile + * @headerfile + * @brief Sequence-to-profile alignment with sequence integration. + * + * seq will be aligned to profile using @link globalAlignment @endlink. To compute a banded alignment + * lDiag and uDiag have to be given. + * The resulting alignment will then be integrated into profile by incrementing the count values of + * the profile entries that correspond to the seq row of the alignment. + * + * @signature void addToProfile(profile, seq[, lDiag, uDiag]); + * + * @param[in,out] profile The profile to add seq to. A @link String @endlink over @link ProfileChar @endlink. + * @param[in] seq @link String @endlink to align to profile. + * @param[in] lDiag Lower diagonal for alignment (@link SignedIntegerConcept @endlink). + * @param[in] uDiag Upper diagonal for alignment (@link SignedIntegerConcept @endlink). + */ + +// TODO(holtgrew): Add example? + +template +void addToProfile(String > & profile, + String /*const*/ & seq, + int lDiag = minValue(), + int uDiag = maxValue()) // non-const because of holder issues +{ + typedef ProfileChar TProfileChar; + + typedef String TProfileString; + typedef String TSequence; + + // Define gaps and scoring scheme. + Gaps gapsH(profile); + Gaps gapsV(seq); + seqan::Score sScheme(profile); + + // Perform the global alignment. + if (lDiag == minValue() || uDiag == maxValue()) + globalAlignment(gapsH, gapsV, sScheme, Gotoh()); + else + globalAlignment(gapsH, gapsV, sScheme, lDiag, uDiag, Gotoh()); + + // Construct a new profile from the alignment into buffer and finally swap out the new profile. + TProfileString buffer; + reserve(buffer, length(gapsH)); + typename Iterator, Standard>::Type + itH = begin(gapsH, Standard()), + itHEnd = end(gapsH, Standard()); + typename Iterator, Standard>::Type itV = begin(gapsV, Standard()); + + // std::cout << "--- BEFORE ----\n"; + // std::cout << "HORIZONTAL\n"; + // for (; itH != itHEnd; ++itH) + // { + // if (isGap(itH)) + // { + // std::cerr << "-\n"; + // } + // else + // { + // TProfileChar c = (TProfileChar)*itH; + // std::cout << "(" << c.count[0] << ", " << c.count[1] << ", " << c.count[2] << ", " << c.count[3] << ", " << c.count[4] << ")\n"; + // } + //} + //std::cout << "VERTICAL\n"; + //std::cout << gapsV << "\n"; + + itH = begin(gapsH, Standard()); + SEQAN_ASSERT_EQ(length(gapsH), length(gapsV)); + for (; itH != itHEnd; ++itH, ++itV) + { + if (isGap(itH)) + { + SEQAN_ASSERT_NOT_MSG(isGap(itV), "Must not generate gaps columns!"); + appendValue(buffer, TProfileChar()); + back(buffer).count[valueSize()] += 1; + back(buffer).count[ordValue(TChar(*itV))] += 1; + } + else + { + TProfileChar c = *itH; + appendValue(buffer, c); + if (isGap(itV)) + back(buffer).count[valueSize()] += 1; + else + back(buffer).count[ordValue(TChar(*itV))] += 1; + } + } + + //std::cout << "--- AFTER ----\n"; + //std::cout << "HORIZONTAL\n"; + //for (typename Iterator::Type it = begin(buffer, Standard()); it != end(buffer, Standard()); ++it) + //{ + // std::cout << "(" << it->count[0] << ", " << it->count[1] << ", " << it->count[2] << ", " + // << it->count[3] << ", " << it->count[4] << ")\n"; + //} + + swap(buffer, profile); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_PROFILE_ADD_TO_PROFILE_H_ diff --git a/seqan/align_profile/score_profile_seq.h b/seqan/align_profile/score_profile_seq.h new file mode 100644 index 0000000..86b9a26 --- /dev/null +++ b/seqan/align_profile/score_profile_seq.h @@ -0,0 +1,536 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef SEQAN_INCLUDE_PROFILE_SPROFILE_SEQ_H_ +#define SEQAN_INCLUDE_PROFILE_SPROFILE_SEQ_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ProfileSeqScore + +struct ProfileSeqScore_; +typedef Tag ProfileSeqScore; + +template +class Score; + +template +inline void +assignProfile(Score & me, TString const & profile); + +// ProfileSeqFracScore + +struct ProfileSeqFracScore_; +typedef Tag ProfileSeqFracScore; + +template +class Score; + +template +inline void +assignProfile(Score & me, TString const & profile); + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class ProfileSeq Score +// ---------------------------------------------------------------------------- + +struct ProfileSeqScore_; +typedef Tag ProfileSeqScore; + +/*! + * @class ProfileSeqScore ProfileSeq Score + * @extends Score + * @headerfile + * @brief Score for sequence-to-profile alignments. + * + * Using this class, you can align sequences to profiles. The profile is assumed to be in the horizontal direction + * (first row), the sequence in the vertical direction (second row). + * + * Scoring works as follows. + * + * The integer SEQAN_CONSENSUS_UNITY and fractions thereof are used to express scores. Gap opens in the + * profile are scored proportional to the number of gaps in the profile with two times unity, gap extends with one times + * unity at the position. + * + * Gap opens in the sequence are scored with two times unity, gap extends in the sequence with unity. Alignments of + * profile characters to sequence characters are scored with the fraction of profile characters that match the sequence + * characters times unity. + * + * @signature template + * class Score; + * + * @tparam TValue The integer type to use for representing scores. + * + * @section Examples + * + * The following example uses the ProfileSeq Score to align a sequence against a profile. + * Note that we print the gap state for each position since profiles cannot be printed to one stdout character. + * + * @include demos/dox/align_profile/profile_seq_score.cpp + * + * The output is as follows: + * + * @code{.output} + * score value = -2097152 + * gaps in profile/sequence + * pos G S + * 0 0 0 + * 1 1 0 + * 2 0 0 + * 3 1 0 + * 4 0 0 + * 5 0 0 + * @endcode + */ + +/*! + * @fn ProfileSeqScore::Score + * @brief Constructor + * + * @signature Score::Score(); + * @signature Score::Score(profile); + * + * @param[in] profile The profile to copy from (@link AllocString @endlink of @link ProfileChar @endlink objects). + * + * When providing profile, the function @link ProfileSeqScore#assignProfile @endlink is automatically used to + * assign the profile to this class. + */ + +template +class Score +{ + public: + // A table of position x (ord value) giving the counts of the characters at the given positions. + String consensusSet; + + Score() {} + + // Construct given a profile string. + template + explicit + Score(TProfile const & profile) + { + assignProfile(*this, profile); + } +}; + +// ---------------------------------------------------------------------------- +// Class ProfileSeqFrac Score +// ---------------------------------------------------------------------------- + +struct ProfileSeqFracScore_; +typedef Tag ProfileSeqFracScore; + +/*! + * @class ProfileSeqFracScore ProfileSeqFrac Score + * @extends Score + * @headerfile + * @brief Score for sequence-to-profile alignments. + * + * Using this class, you can align sequences to profiles. The profile is assumed to be in the horizontal direction + * (first row), the sequence in the vertical direction (second row). + * + * Scoring works as follows. + * + * The integer SEQAN_CONSENSUS_UNITY and fractions thereof are used to express scores. Gap opens in the + * profile are scored proportional to the number of gaps in the profile two times unity, gap extends are scored + * proportional to the number of gaps in the profile at the position. Gap opens in the sequence are scored with two + * times unity, gap extends with one times unity. + * + * @signature template + * class Score; + * + * @tparam TValue The integer type to use for representing scores. + * + * @section Examples + * + * The following example uses the ProfileSeqFrac Score to align a sequence against a profile. Note that we print the + * gap state for each position since profiles cannot be printed to one stdout character. + * + * @include demos/dox/align_profile/profile_seq_frac_score.cpp + * + * The output is as follows: + * + * @code + * score value = -2097152 + * gaps in profile/sequence + * pos G S + * 0 0 0 + * 1 1 0 + * 2 0 0 + * 3 1 0 + * 4 0 0 + * 5 0 0 + * @endcode + */ + +/*! + * @fn ProfileSeqFracScore::Score + * @brief Constructor + * + * @signature Score::Score(); + * @signature Score::Score(profile); + * + * @param[in] profile The profile to copy from (@link AllocString @endlink of @link ProfileChar @endlink objects). + * + * When providing profile, the function @link ProfileSeqFracScore#assignProfile @endlink is automatically used to + * assign the profile to this class. + */ + + +template +class Score +{ + public: + // Total number of profile characters in each column + String sum; + + Score() {} + + // Construct given a profile string. + template + explicit + Score(TProfile const & profile) + { + assignProfile(*this, profile); + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// -------------------------------------------------------------------------- +// Metafunction SequenceEntryForScore [ProfileSeq Score] +// -------------------------------------------------------------------------- + +// Returns the type that holds a sequence entry. This is used for abstracting away the access to sequence characters. + +template +struct SequenceEntryForScore, TSequence> +{ + typedef ConsensusScoreSequenceEntry Type; +}; + +template +struct SequenceEntryForScore const, TSequence> : + SequenceEntryForScore, TSequence> +{}; + +// -------------------------------------------------------------------------- +// Metafunction SequenceEntryForScore [ProfileSeqFrac Score] +// -------------------------------------------------------------------------- + +// Returns the type that holds a sequence entry. This is used for abstracting away the access to sequence characters. + +template +struct SequenceEntryForScore, TSequence> +{ + typedef ConsensusScoreSequenceEntry Type; +}; + +template +struct SequenceEntryForScore const, TSequence> : + SequenceEntryForScore, TSequence> +{}; + +// ============================================================================ +// Functions +// ============================================================================ + +// -------------------------------------------------------------------------- +// Function sequenceEntryForScore() [ProfileSeq Score] +// -------------------------------------------------------------------------- + +template +inline ConsensusScoreSequenceEntry +sequenceEntryForScore(Score const & /*sScheme*/, + TSequence const & seq, TPosition pos) +{ + return ConsensusScoreSequenceEntry(seq, pos); +} + +// -------------------------------------------------------------------------- +// Function assignProfile() [ProfileSeq Score] +// -------------------------------------------------------------------------- + +/*! + * @fn ProfileSeqScore#assignProfile + * @brief Assign profile to ProfileSeqScore. + * + * @signature void assignProfile(score, profile); + * + * @param[out] score The ProfileSeqScore object to assign the profile for. + * @param[in] profile The profile to assign to the score. @link AllocString @endlink of @link ProfileChar @endlink. + */ + +template +inline void +assignProfile(Score & me, + TString const & profile) +{ + typedef typename Size::Type TSize; + TSize alphSize = ValueSize::Type>::VALUE; + resize(me.consensusSet, alphSize * length(profile)); + + typedef typename Iterator::Type TIter; + typedef typename Iterator, Standard>::Type TConsSetIter; + TConsSetIter itConsSet = begin(me.consensusSet, Standard()); + TIter it = begin(profile, Standard()); + TIter itEnd = end(profile, Standard()); + TSize maxCount = 0; + for (;it!=itEnd;++it) + { + maxCount = 0; + for (TSize i = 0; i maxCount) + maxCount = (*it).count[i]; + for (TSize i = 0; i +inline TValue +scoreGapExtendHorizontal( + Score const & me, + ConsensusScoreSequenceEntry const & entry1, + ConsensusScoreSequenceEntry const & entry2) +{ + typedef typename Value::Type TValue1; + if ((int)position(entry2) < 0) + return -SEQAN_CONSENSUS_UNITY; + else + return me.consensusSet[position(entry1) * (ValueSize::VALUE) + (ValueSize::VALUE - 1)]; +} + +// -------------------------------------------------------------------------- +// Function scoreGapOpenHorizontal() [ProfileSeq Score] +// -------------------------------------------------------------------------- + +template +inline TValue +scoreGapOpenHorizontal( + Score const & me, + ConsensusScoreSequenceEntry const & entry1, + ConsensusScoreSequenceEntry const & entry2) +{ + typedef typename Value::Type TValue1; + if ((int)position(entry2) < 0) + return -2 * SEQAN_CONSENSUS_UNITY; + else + return 2 * me.consensusSet[position(entry1) * (ValueSize::VALUE) + (ValueSize::VALUE - 1)]; +} + +// -------------------------------------------------------------------------- +// Function scoreGapExtendVertical() [ProfileSeq Score] +// -------------------------------------------------------------------------- + +template +inline TValue +scoreGapOpenVertical( + Score const &, + ConsensusScoreSequenceEntry const & /*entry1*/, + ConsensusScoreSequenceEntry const & /*entry2*/) +{ + return -2 * SEQAN_CONSENSUS_UNITY; +} + +// -------------------------------------------------------------------------- +// Function scoreGapOpenVertical() [ProfileSeq Score] +// -------------------------------------------------------------------------- + +template +inline TValue +scoreGapExtendVertical( + Score const &, + ConsensusScoreSequenceEntry const & /*entry1*/, + ConsensusScoreSequenceEntry const & /*entry2*/) +{ + return -SEQAN_CONSENSUS_UNITY; +} + +// -------------------------------------------------------------------------- +// Function score() [ProfileSeq Score] +// -------------------------------------------------------------------------- + +template +inline TValue +score(Score const & me, + ConsensusScoreSequenceEntry const & entry1, + ConsensusScoreSequenceEntry const & entry2) +{ + typedef typename Value::Type TValue1; + return me.consensusSet[position(entry1) * (ValueSize::VALUE) + ordValue(value(entry2))]; +} + +// -------------------------------------------------------------------------- +// Function sequenceEntryForScore() [ProfileSeqFrac Score] +// -------------------------------------------------------------------------- + +template +inline ConsensusScoreSequenceEntry +sequenceEntryForScore(Score const & /*sScheme*/, + TSequence const & seq, TPosition pos) +{ + return ConsensusScoreSequenceEntry(seq, pos); +} + +// -------------------------------------------------------------------------- +// Function assignProfile() [ProfileSeqFrac Score] +// -------------------------------------------------------------------------- + +/*! + * @fn ProfileSeqFracScore#assignProfile + * @brief Assign profile to ProfileSeqFrac Score. + * + * @signature void assignProfile(score, profile); + * + * @param[out] score The ProfileSeqScore object to assign the profile for. + * @param[in] profile The profile to assign to the score. @link AllocString @endlink of @link ProfileChar @endlink. + */ + +template +inline void +assignProfile(Score & me, + TString const & profile) +{ + typedef typename Size::Type TSize; + resize(me.sum, length(profile)); + typedef typename Iterator::Type TIter; + typedef typename Iterator, Standard>::Type TSumIter; + TSumIter itSum = begin(me.sum, Standard()); + TIter it = begin(profile, Standard()); + TIter itEnd = end(profile, Standard()); + for (; it!=itEnd; ++it, ++itSum) + { + *itSum = 0; + for (TSize i = 0; i < (TSize) ValueSize::Type>::VALUE; ++i) + *itSum += (*it).count[i]; + } +} + +// -------------------------------------------------------------------------- +// Function scoreGapExtendHorizontal() [ProfileSeqFrac Score] +// -------------------------------------------------------------------------- + +template +inline TValue +scoreGapExtendHorizontal( + Score const & me, + ConsensusScoreSequenceEntry const & entry1, + ConsensusScoreSequenceEntry const & entry2) +{ + if (((int)position(entry2) < 0) || (!me.sum[position(entry1)])) + return -SEQAN_CONSENSUS_UNITY; + else + return ((TValue) (( (int)value(entry1).count[ValueSize::Type>::VALUE - 1] - me.sum[position(entry1)]) * SEQAN_CONSENSUS_UNITY) / me.sum[position(entry1)]); +} + +// -------------------------------------------------------------------------- +// Function scoreGapOpenHorizontal() [ProfileSeqFrac Score] +// -------------------------------------------------------------------------- + +template +inline TValue +scoreGapOpenHorizontal( + Score const & me, + ConsensusScoreSequenceEntry const & entry1, + ConsensusScoreSequenceEntry const & entry2) +{ + if (((int)position(entry2) < 0) || (!me.sum[position(entry1)])) + return -SEQAN_CONSENSUS_UNITY; + else + return ((TValue) (((int)value(entry1).count[ValueSize::Type>::VALUE - 1] - me.sum[position(entry1)]) * SEQAN_CONSENSUS_UNITY) / me.sum[position(entry1)]); +} + +// -------------------------------------------------------------------------- +// Function scoreGapExtendVertical() [ProfileSeqFrac Score] +// -------------------------------------------------------------------------- + +template +inline TValue +scoreGapOpenVertical( + Score const &, + ConsensusScoreSequenceEntry const & /*entry1*/, + ConsensusScoreSequenceEntry const & /*entry2*/) +{ + return -SEQAN_CONSENSUS_UNITY; +} + +// -------------------------------------------------------------------------- +// Function scoreGapOpenVertical() [ProfileSeqFrac Score] +// -------------------------------------------------------------------------- + +template +inline TValue +scoreGapExtendVertical( + Score const &, + ConsensusScoreSequenceEntry const & /*entry1*/, + ConsensusScoreSequenceEntry const & /*entry2*/) +{ + return -SEQAN_CONSENSUS_UNITY; +} + +// -------------------------------------------------------------------------- +// Function score() [ProfileSeqFrac Score] +// -------------------------------------------------------------------------- + +template +inline TValue +score(Score const & me, + ConsensusScoreSequenceEntry const & entry1, + ConsensusScoreSequenceEntry const & entry2) +{ + if (!me.sum[position(entry1)]) + return -SEQAN_CONSENSUS_UNITY; + else + return ((TValue) (((int)value(entry1).count[ordValue(value(entry2))] - me.sum[position(entry1)]) * SEQAN_CONSENSUS_UNITY) / me.sum[position(entry1)]); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_PROFILE_SPROFILE_SEQ_H_ diff --git a/seqan/align_split.h b/seqan/align_split.h new file mode 100644 index 0000000..b08ac58 --- /dev/null +++ b/seqan/align_split.h @@ -0,0 +1,55 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for module align_split. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_SPLIT_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_SPLIT_H_ + +// =========================================================================== +// Prerequisites. +// =========================================================================== + +#include +#include +#include + +// =========================================================================== +// Split Alignment Impelmentation. +// =========================================================================== + +#include +#include + +#endif // SEQAN_INCLUDE_SEQAN_ALIGN_SPLIT_H_ diff --git a/seqan/align_split/align_split_interface.h b/seqan/align_split/align_split_interface.h new file mode 100644 index 0000000..658536a --- /dev/null +++ b/seqan/align_split/align_split_interface.h @@ -0,0 +1,751 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Split alignment implementation. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_SPLIT_ALIGN_SPLIT_INTERFACE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_SPLIT_ALIGN_SPLIT_INTERFACE_H_ + +#include "dp_scout_split.h" + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// Tag for the split alignment algorithm in DPProfile_. + +template +struct SplitAlignment_ {}; + +// Tag for the split alignment algorithm. + +struct SplitAlignmentAlgo_; +typedef Tag SplitAlignmentAlgo; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction ScoutSpecForAlignmentAlgorithm_ +// ---------------------------------------------------------------------------- + +// For the split alignment, we will use our SplitAlignmentScout specialization of DPScout. + +template +struct ScoutSpecForAlignmentAlgorithm_, DPScoutState_ > +{ + typedef SplitAlignmentScout Type; +}; + +template +struct ScoutSpecForAlignmentAlgorithm_ const, DPScoutState_ > +{ + typedef SplitAlignmentScout Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction IsSplitAlignment_ +// ---------------------------------------------------------------------------- + +// Convenience function used in the DP configuration below. + +template +struct IsSplitAlignment_ : False {}; + +template +struct IsSplitAlignment_ >: + True {}; + +template +struct IsSplitAlignment_ const>: + True {}; + +template +struct IsSplitAlignment_ >: + IsSplitAlignment_ {}; + +template +struct IsSplitAlignment_ const>: + IsSplitAlignment_ {}; + +// ---------------------------------------------------------------------------- +// Metafunction IsFreeEndGap_ +// ---------------------------------------------------------------------------- + +// We want the same free endgaps configuration as for global alignments. + +template +struct IsFreeEndGap_, TRow> : + IsFreeEndGap_, TRow> +{}; + +template +struct IsFreeEndGap_ const, TRow> : + IsFreeEndGap_ const, TRow> +{}; + +// ---------------------------------------------------------------------------- +// Metafunction IsGlobalAlignment_ +// ---------------------------------------------------------------------------- + +// We use similar functionality as the global alignment. + +template +struct IsGlobalAlignment_ > : + True +{}; + +template +struct IsGlobalAlignment_ const> : + True +{}; + +// ---------------------------------------------------------------------------- +// Metafunction TraceTail_ +// ---------------------------------------------------------------------------- + +template +struct TraceTail_ > : + False +{}; + +// ---------------------------------------------------------------------------- +// Metafunction LastColumnEnabled_ +// ---------------------------------------------------------------------------- + +template +struct LastColumnEnabled_, TColumnDescriptor> +{ + typedef typename If, + typename IsFreeEndGap_, DPLastColumn>::Type, + False>::Type Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction LastRowEnabled_ +// ---------------------------------------------------------------------------- + +template +struct LastRowEnabled_, LastCell, TColumnDescriptor> +{ + typedef typename If, + IsSameType >, + typename IsFreeEndGap_, DPLastRow>::Type, + False>::Type Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction DPMetaColumn_ +// ---------------------------------------------------------------------------- + +template +struct DPMetaColumn_, TGapCosts, TTraceFlag>, MetaColumnDescriptor > +{ + typedef DPProfile_, TGapCosts, TTraceFlag> TDPProfile; + typedef typename IsLocalAlignment_::Type TIsLocal; + + // If InitialColumn -> Zero, Vertical | Zero, Vertical | Zero // Within the algorithm we need to define the first row as only one cell if it is no initial column + // If InnerColumn -> Horizontal | Zero, All, All + // If FinalColumn -> Horizontal | Zero, All, All + + typedef typename If, + IsFreeEndGap_ >, RecursionDirectionZero, RecursionDirectionHorizontal>::Type TRecursionTypeFirstCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeInnerCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + + +template +struct DPMetaColumn_, TGapCosts, TTraceFlag>, MetaColumnDescriptor > +{ + typedef DPProfile_, TGapCosts, TTraceFlag> TDPProfile; + typedef typename IsLocalAlignment_::Type TIsLocal; + + // How does the recursion directions look like? + + // If InitialColumn -> Zero, Vertical | Zero, Vertical | Zero // Within the algorithm we need to define the first row as only one cell if it is no initial column + // If InnerColumn -> Horizontal | Zero, All, LowerBand + // If FinalColumn -> Horizontal | Zero, All, LowerBand + + typedef typename If, + IsFreeEndGap_ >, RecursionDirectionZero, RecursionDirectionHorizontal>::Type TRecursionTypeFirstCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeInnerCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionLowerDiagonal>::Type TRecursionTypeLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + +template +struct DPMetaColumn_, TGapCosts, TTraceFlag>, MetaColumnDescriptor > +{ + typedef DPProfile_, TGapCosts, TTraceFlag> TDPProfile; + typedef typename IsLocalAlignment_::Type TIsLocal; + + // If InitialColumn -> Zero, Vertical | Zero, Vertical | Zero // Within the algorithm we need to define the first row as only one cell if it is no initial column + // If InnerColumn -> UpperDiagonal, All, LowerDiagonal + // If FinalColumn -> UpperDiagonal, All, LowerDiagonal + + typedef typename If, RecursionDirectionZero, RecursionDirectionUpperDiagonal>::Type TRecursionTypeFirstCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeInnerCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionLowerDiagonal>::Type TRecursionTypeLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + +template +struct DPMetaColumn_, TGapCosts, TTraceFlag>, MetaColumnDescriptor > +{ + typedef DPProfile_, TGapCosts, TTraceFlag> TDPProfile; + typedef typename IsLocalAlignment_::Type TIsLocal; + + // If InitialColumn -> Zero, Vertical | Zero, Vertical | Zero // Within the algorithm we need to define the first row as only one cell if it is no initial column + // If InnerColumn -> UpperDiagonal, All, All + // If FinalColumn -> UpperDiagonal, All, All + + typedef typename If, RecursionDirectionZero, RecursionDirectionUpperDiagonal>::Type TRecursionTypeFirstCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeInnerCell_; + typedef typename If, + typename If, RecursionDirectionZero, RecursionDirectionVertical>::Type, + RecursionDirectionAll>::Type TRecursionTypeLastCell_; + + typedef DPMetaCell_ TFirstCell_; + typedef DPMetaCell_ TInnerCell_; + typedef DPMetaCell_ TLastCell_; +}; + +// ---------------------------------------------------------------------------- +// Metafunction SetupAlignmentProfile_ +// ---------------------------------------------------------------------------- + +template +struct SetupAlignmentProfile_ +{ + typedef DPProfile_, TGapCosts, TTraceSwitch> Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _reverseTrace() +// ---------------------------------------------------------------------------- + +// Reverse a trace string and adapt internal position. +template +void _reverseTrace(String, TSpec> & trace, + size_t const lengthH, + size_t const lengthV) +{ + typedef String, TSpec> TTrace; + typedef typename Iterator::Type TTraceIter; + + if (empty(trace)) + return; + + for (TTraceIter it = begin(trace, Rooted()); !atEnd(it); goNext(it)) + { + it->_horizontalBeginPos = lengthH - _getEndHorizontal(*it); + it->_verticalBeginPos = lengthV - _getEndVertical(*it); + } + reverse(trace); +} + +// ---------------------------------------------------------------------------- +// Function _computeSplitTrace() +// ---------------------------------------------------------------------------- + +template +void _computeSplitTrace(TTarget & target, + TSeqH const & seqH, + TSeqV const & seqV, + TDPContext const & dpContext, + TMatPos const matPos, + AlignConfig2, TFreeEndGaps, TTraceConfig> const & config) +{ + typedef typename SetupAlignmentProfile_::Type TDPProfile; + + typedef typename GetDPTraceMatrix::Type TDPTraceMatrixHost; + typedef typename Value::Type TTraceValue; + + typedef DPMatrix_ TDPTraceMatrix; + typedef DPMatrixNavigator_, NavigateColumnWise> TDPTraceMatrixNavigator; + + TDPTraceMatrix matrix; + setLength(matrix, +DPMatrixDimension_::HORIZONTAL, length(seqH) + 1 - std::max(0, lowerDiagonal(config._band))); + + if (IsSameType::VALUE) + { + setLength(matrix, +DPMatrixDimension_::VERTICAL, length(seqV) + 1); + } + else + { + int bandSize = _min(static_cast(length(seqH)), upperDiagonal(config._band)) - + _max(lowerDiagonal(config._band), -static_cast(length(seqV))) + 1; + setLength(matrix, +DPMatrixDimension_::VERTICAL, _min(static_cast(length(seqV)) + 1, bandSize)); + } + + setHost(matrix, getDpTraceMatrix(dpContext)); + resize(matrix); + SEQAN_ASSERT_EQ(length(getDpTraceMatrix(dpContext)), length(matrix)); + TDPTraceMatrixNavigator navi; + _init(navi, matrix, config._band); + _computeTraceback(target, navi, matPos, seqH, seqV, config._band, TDPProfile()); +} + +// ---------------------------------------------------------------------------- +// Function _splitAlignmentImpl() +// ---------------------------------------------------------------------------- + +// We call the long sequence contig and the shorter one read but could be changed roles. +template +auto _splitAlignmentImpl(Gaps & gapsContigL, + Gaps & gapsReadL, + Gaps & gapsContigR, + Gaps & gapsReadR, + Score const & scoringScheme, + TAlignConfigL const & alignConfigL, + TAlignConfigR const & alignConfigR, + TGapModel const & /*gapModel*/) +{ + typedef Gaps TGaps; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + typedef TraceSegment_ TTraceSegment; + + // Compute trace and split score sequence for the left alignment. + // We actually need to first compute the scores, than trace from the choosen split position. + DPContext dpContextL; + DPScoutState_ scoutStateL; + resize(scoutStateL.splitScore, length(source(gapsContigL)) + 1, minValue() / 2); + resize(scoutStateL.splitPos, length(scoutStateL.splitScore)); + + String traceL; + _setUpAndRunAlignment(dpContextL, traceL, scoutStateL, source(gapsContigL), source(gapsReadL), scoringScheme, alignConfigL); + + // Get reversed versions of the right contig and read sequence. + ModifiedString revContigR(source(gapsContigR)); + ModifiedString revReadR(source(gapsReadR)); + + // Compute trace and split score sequence for the right alignment. + DPContext dpContextR; + DPScoutState_ scoutStateR; + resize(scoutStateR.splitScore, length(source(gapsContigR)) + 1, minValue() / 2); + resize(scoutStateR.splitPos, length(scoutStateR.splitScore)); + + String traceR; + _setUpAndRunAlignment(dpContextR, traceR, scoutStateR, revContigR, revReadR, scoringScheme, alignConfigR); + + // Reverse trace so it fits to the forward right sequences. Also reverse the trace such that we can directly apply + // it for the right alignment. + reverse(scoutStateR.splitScore); + reverse(scoutStateR.splitPos); + + SEQAN_ASSERT_EQ(length(scoutStateL.splitScore), length(scoutStateR.splitScore)); + + // We will split the left and right alignments into two parts such that the alignment score is optimal. We compute + // the leftmost best position for a split (equivalent to the best prefix of the first left alignment). Note that + // placing the breakpoint at the leftmost position is coherent with the SNPdb semantics but there are other data + // bases that use rightmost placement. + + // TODO(holtgrew): Make selecting the left/right split position from interface possible? Maybe not necessary. + + auto itBegin = makeZipIterator(begin(scoutStateL.splitScore), begin(scoutStateR.splitScore)); + auto res = std::max_element(itBegin, makeZipIterator(end(scoutStateL.splitScore), end(scoutStateR.splitScore)), + [] (auto const & lhs, auto const & rhs) + { + return std::get<0>(lhs) + std::get<1>(lhs) < std::get<0>(rhs) + std::get<1>(rhs); + }); + auto bestPrefixLength = res - itBegin; + + // std::cerr << "bestPrefixLength = " << bestPrefixLength << "\n"; + + // std::cerr << "split store left "; + // for (unsigned i = 0; i < length(scoutStateL.splitScore); ++i) + // fprintf(stderr, " %3d", scoutStateL.splitScore[i]); + // std::cerr << "\n"; + // std::cerr << "split store right"; + // for (unsigned i = 0; i < length(scoutStateR.splitScore); ++i) + // fprintf(stderr, " %3d", scoutStateR.splitScore[i]); + // std::cerr << "\n"; + + // Recompute the best trace starting from the recorded split position for left ... + clear(traceL); + _computeSplitTrace(traceL, source(gapsContigL), source(gapsReadL), dpContextL, + scoutStateL.splitPos[bestPrefixLength], alignConfigL); + _adaptTraceSegmentsTo(gapsContigL, gapsReadL, traceL); + // ... and right anchor. + clear(traceR); + _computeSplitTrace(traceR, source(gapsContigR), source(gapsReadR), dpContextR, + scoutStateR.splitPos[bestPrefixLength], alignConfigR); + + _reverseTrace(traceR, length(source(gapsContigR)), length(source(gapsReadR))); + _adaptTraceSegmentsTo(gapsContigR, gapsReadR, traceR); + + // We have to correct the clipping position for the left alignment because of the to-right projection. The + // insertion itself is not part of the alignment. + TPosition cePosL = toViewPosition(gapsContigL, bestPrefixLength); + if (bestPrefixLength > 0) + cePosL = toViewPosition(gapsContigL, bestPrefixLength - 1) + 1; + setClippedEndPosition(gapsContigL, cePosL); + setClippedEndPosition(gapsReadL, cePosL); + + return std::make_pair(std::get<0>(*res), std::get<1>(*res)); +} + +template +auto _splitAlignmentImpl(Gaps & gapsContigL, + Gaps & gapsReadL, + Gaps & gapsContigR, + Gaps & gapsReadR, + Score const & scoringScheme, + AlignConfig const &, + int lowerDiagonal, + int upperDiagonal, + TGapModel const & /*gapModel*/) +{ + typedef typename SubstituteAlignConfig_ >::Type TFreeEndGaps; + // Check whether we need to run the banded versions. + if (lowerDiagonal != minValue() && upperDiagonal != maxValue()) + { + typedef AlignConfig2, TFreeEndGaps, + TracebackOn > > TAlignConfigL; + typedef AlignConfig2, TFreeEndGaps, + TracebackOn > > TAlignConfigR; + return _splitAlignmentImpl(gapsContigL, gapsReadL, gapsContigR, gapsReadR, scoringScheme, + TAlignConfigL(lowerDiagonal, upperDiagonal), + TAlignConfigR(lowerDiagonal, upperDiagonal), + TGapModel()); + } + else + { + typedef AlignConfig2, TFreeEndGaps, + TracebackOn > > TAlignConfigL; + typedef AlignConfig2, TFreeEndGaps, + TracebackOn > > TAlignConfigR; + return _splitAlignmentImpl(gapsContigL, gapsReadL, gapsContigR, gapsReadR, scoringScheme, TAlignConfigL(), + TAlignConfigR(), TGapModel()); + } +} + +template +auto _splitAlignmentImpl(Gaps & gapsContigL, + Gaps & gapsReadL, + Gaps & gapsContigR, + Gaps & gapsReadR, + Score const & scoringScheme, + AlignConfig const & config, + int lowerDiagonal = minValue(), + int upperDiagonal = maxValue()) +{ + if (_usesAffineGaps(scoringScheme, source(gapsContigL), source(gapsReadL))) + return _splitAlignmentImpl(gapsContigL, gapsReadL, gapsContigR, gapsReadR, + scoringScheme, config, lowerDiagonal, upperDiagonal, AffineGaps()); + else + return _splitAlignmentImpl(gapsContigL, gapsReadL, gapsContigR, gapsReadR, + scoringScheme, config, lowerDiagonal, upperDiagonal, LinearGaps()); +} + +// ---------------------------------------------------------------------------- +// Function splitAlignment() +// ---------------------------------------------------------------------------- + +/*! + * @fn splitAlignment + * @headerfile + * @brief Compute split alignments. + * + * @signature TScoreValue splitAlignment(alignL, alignR, scoringScheme[, config][, lowerDiag, upperDiag]); + * @signature TScoreValue splitAlignment(gapsHL, gapsVL, gapsHR, gapsVR, scoringScheme[, config][, lowerDiag, upperDiag]); + * + * @param[in,out] alignL @link Align @endlink object with two rows for the left alignment. + * @param[in,out] alignR @link Align @endlink object with two rows for the right alignment. + * @param[in,out] gapsHL @link Gaps @endlink object with the horizontal/contig row for the left alignment. + * @param[in,out] gapsVL @link Gaps @endlink object with the vertical/read row for the left alignment. + * @param[in,out] gapsHR @link Gaps @endlink object with the horizontal/contig row for the right alignment. + * @param[in,out] gapsVR @link Gaps @endlink object with the vertical/read row for the right alignment. + * @param[in] scoringScheme The scoring scheme to use for the alignment. + * @param[in] config A configuration object of type @link AlignConfig @endlink, to specify free-end-gaps. + * @param[in] lowerDiag The lower diagonal.You have to specify the upper and lower diagonals for the left + * alignment. For the right alignment, the corresponding diagonals are chosen for the + * lower right part of the DP matrix, int. + * @param[in] upperDiag The lower diagonal. Also see remark for lowerDiag, int. + * + * @return TScoreValue The sum of the alignment scores of both alignments (Metafunction: @link Score#Value @endlink + * of the type of scoringScheme). + * + * There are two variants of the split alignment problem. In the first variant, we want to align two sequences where the + * first (say the reference) one is shorter than the second (say a read) and the read contains an insertion with respect + * to the reference. We now want to align the read agains the reference such that the left part of the read aligns well + * against the left part of the reference and the right part of the read aligns well against the right part of the + * reference. The center gap in the reference is free. + * + * For example: + * + * @code{.console} + * reference AGCATGTTAGATAAGATAGC-----------TGTGCTAGTAGGCAGTCAGCGCCAT + * |||||||||||||||||||| ||||||||||||||||||||||||| + * read AGCATGTTAGATAAGATAGCCCCCCCCCCCCTGTGCTAGTAGGCAGTCAGCGCCAT + * @endcode + * + * The second variant is to align two sequences A and B against a reference such that the left part of A aligns well to + * the left part of the reference and the right part of B aligns well to the right part of the reference. Together, + * both reads span the whole reference and overlap with an insertion in the reference. + * + * @code{.console} + * reference AGCATGTTAGATAAGATAGCTGTGCTAGTAGGCAGTCAGCGCCAT + * |||||||||||||||||| | || + * AGCATGTTAGATAAGATATCCGTCC + * read 1 + * ||| ||||||||||||||||||||||| + * CCGCTATGCTAGTAGGCAGTCAGCGCCAT + * read 2 + * @endcode + * + * The resulting alignment of the left/right parts is depicted below. The square brackets indicate clipping positions. + * + * @code{.console} + * reference AGCATGTTAGATAAGATA [GCTGTGCTAGTAGGCAGTCAGCGCCAT + * |||||||||||||||||| [ | || + * AGCATGTTAGATAAGATA [TCCGTCC + * read 1 + * reference AGCATGTTAGATAAGATA] GTGCTAGTAGGCAGTCAGCGCCAT + * ] ||||||||||||||||||||||| + * CCGCT] ATGCTAGTAGGCAGTCAGCGCCAT + * read 2 + * @endcode + * + * In the first case, we want to find the one breakpoint in the reference and the two breakpoints in the reads and the + * alignment of the left and right well-aligning read parts. In the second case, we want to find the one breakpoint in + * the reference and the breakpoint/clipping position in each read. + * + * The splitAlignment() function takes as the input two alignments. The sequence in each alignment's first row + * is the reference and the sequence of the second row is the read. The sequence has to be the same sequence whereas + * the reads might differ. If the reads are the same then this is the same as the first case and if the reads differ + * then this is the second case. + * + * The result is two alignments of the left and right contig path clipped appropriately. The resulting score is the sum + * of the scores of both alignments. + * + * @section Remarks + * + * The DP algorithm is chosen automatically depending on whether the gap open and extension costs are equal. + * + * @section Example + * + * The following example demonstrates the usage of splitAlignment in the first case. The second case + * works accordingly. + * + * @include demos/dox/align_split/split_alignment.cpp + * + * The output is as follows. + * + * @include demos/dox/align_split/split_alignment.cpp.stdout + */ + +// Variant: unbanded, with Align objects. + +template +int splitAlignment(Align & alignL, + Align & alignR, + Score const & scoringScheme, + AlignConfig const & config) +{ + SEQAN_ASSERT_EQ_MSG(source(row(alignL, 0)), source(row(alignR, 0)), + "Contig must be the same for left and right split alignment."); + + auto tmp = _splitAlignmentImpl(row(alignL, 0), row(alignL, 1), row(alignR, 0), row(alignR, 1), scoringScheme, config); + return std::get<0>(tmp) + std::get<1>(tmp); +} + +template +int splitAlignment(Align & alignL, + Align & alignR, + Score const & scoringScheme) +{ + return splitAlignment(alignL, alignR, scoringScheme, AlignConfig()); +} + +// Variant: unbanded, with Gaps objects. + +template +int splitAlignment(Gaps & gapsHL, + Gaps & gapsVL, + Gaps & gapsHR, + Gaps & gapsVR, + Score const & scoringScheme, + AlignConfig const & config) +{ + SEQAN_ASSERT_EQ_MSG(source(gapsHL), source(gapsHR), + "Contig must be the same for left and right split alignment."); + + auto tmp = _splitAlignmentImpl(gapsHL, gapsVL, gapsHR, gapsVR, scoringScheme, config); + return std::get<0>(tmp) + std::get<1>(tmp); +} + +template +int splitAlignment(Gaps & gapsHL, + Gaps & gapsVL, + Gaps & gapsHR, + Gaps & gapsVR, + Score const & scoringScheme) +{ + return splitAlignment(gapsHL, gapsVL, gapsHR, gapsVR, scoringScheme, AlignConfig()); +} + +// Variant: banded, with Align objects. +template +int splitAlignment(Align & alignL, + Align & alignR, + Score const & scoringScheme, + AlignConfig const & config, + int const lowerDiagonal, + int const upperDiagonal) +{ + SEQAN_ASSERT_EQ_MSG(source(row(alignL, 0)), source(row(alignR, 0)), + "Contig must be the same for left and right split alignment."); + + auto tmp = _splitAlignmentImpl(row(alignL, 0), row(alignL, 1), row(alignR, 0), row(alignR, 1), + scoringScheme, config, lowerDiagonal, upperDiagonal); + return std::get<0>(tmp) + std::get<1>(tmp); +} + +template +int splitAlignment(Align & alignL, + Align & alignR, + Score const & scoringScheme, + int const lowerDiagonal, + int const upperDiagonal) +{ + return splitAlignment(alignL, alignR, scoringScheme, AlignConfig(), + lowerDiagonal, upperDiagonal); +} + +// Variant: banded, with Gaps objects. +template +int splitAlignment(Gaps & gapsHL, + Gaps & gapsVL, + Gaps & gapsHR, + Gaps & gapsVR, + Score const & scoringScheme, + AlignConfig const & config, + int const lowerDiagonal, + int const upperDiagonal) +{ + SEQAN_ASSERT_EQ_MSG(source(gapsHL), source(gapsHR), + "Contig must be the same for left and right split alignment."); + + auto tmp = _splitAlignmentImpl(gapsHL, gapsVL, gapsHR, gapsVR, scoringScheme, config, lowerDiagonal, upperDiagonal); + return std::get<0>(tmp) + std::get<1>(tmp); +} + +template +int splitAlignment(Gaps & gapsHL, + Gaps & gapsVL, + Gaps & gapsHR, + Gaps & gapsVR, + Score const & scoringScheme, + int const lowerDiagonal, + int const upperDiagonal) +{ + return splitAlignment(gapsHL, gapsVL, gapsHR, gapsVR, scoringScheme, AlignConfig(), + lowerDiagonal, upperDiagonal); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_SPLIT_ALIGN_SPLIT_INTERFACE_H_ diff --git a/seqan/align_split/dp_scout_split.h b/seqan/align_split/dp_scout_split.h new file mode 100644 index 0000000..b107e43 --- /dev/null +++ b/seqan/align_split/dp_scout_split.h @@ -0,0 +1,137 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// DPScout_ specialization for the split alignment implementation. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGN_SPLIT_DP_SCOUT_SPLIT_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGN_SPLIT_DP_SCOUT_SPLIT_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Tag SplitAlignmentScout. +// ---------------------------------------------------------------------------- + +struct SplitAlignmentScout_; +typedef Tag SplitAlignmentScout; + +// ---------------------------------------------------------------------------- +// Class DPScoutState_ +// ---------------------------------------------------------------------------- + +template <> +class DPScoutState_ +{ +public: + // The best score for each column. Initialized with 0.5*minValue(). + seqan::String splitScore; + seqan::String splitPos; + + DPScoutState_() + {} +}; + +// ---------------------------------------------------------------------------- +// Class DPScout_ +// ---------------------------------------------------------------------------- + +template +class DPScout_ : public DPScout_ +{ +public: + typedef DPScout_ TParent; + + DPScoutState_ * state; + + DPScout_() : TParent(), state(0) + {} + + DPScout_(DPScoutState_ & state) : TParent(), state(&state) + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _scoutBestScore() [DPScout_] +// ---------------------------------------------------------------------------- + +template +inline void +_scoutBestScore(DPScout_ & dpScout, + TDPCell const & activeCell, + TTraceMatrixNavigator const & navigator, + TIsLastColumn /*isLastColumn*/, + TIsLastRow /*isLastRow*/ ) +{ + //typedef typename Value::Type TScoreValue; + // Note that the underlying matrix has the coordinates flipped. We use posH/posV as we would in pairwise alignments + // and thus this is the reverse from the matrix representation. + unsigned posH = coordinate(navigator, +DPMatrixDimension_::HORIZONTAL); + // unsigned posV = coordinate(navigator, +DPMatrixDimension_::VERTICAL); + + int & i = dpScout.state->splitScore[posH]; + if (i < _scoreOfCell(activeCell)) + { + i = _scoreOfCell(activeCell); + dpScout.state->splitPos[posH] = position(navigator); + } + + // TODO(rrahn): Do we need the optimal end-point? + // We track only the last row for the best traceback score. + if (TIsLastColumn::VALUE || TIsLastRow::VALUE) + { + typedef DPScout_ TDPScout; + typedef typename TDPScout::TParent TParent; + _scoutBestScore(static_cast(dpScout), activeCell, navigator); + } +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_SPLIT_DP_SCOUT_SPLIT_H_ diff --git a/seqan/alignment_free.h b/seqan/alignment_free.h new file mode 100644 index 0000000..8a68853 --- /dev/null +++ b/seqan/alignment_free.h @@ -0,0 +1,63 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Jonathan Goeke +// ========================================================================== +// Facade header for module alignment_free. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_H_ + +// =========================================================================== +// Prerequisites. +// =========================================================================== + +#include +#include +#include +#include +#include + +// =========================================================================== +// Module's headers. +// =========================================================================== + +#include +#include +#include +#include +#include +#include + +#include + +#endif // SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_H_ diff --git a/seqan/alignment_free/af_d2.h b/seqan/alignment_free/af_d2.h new file mode 100644 index 0000000..7e5bcbe --- /dev/null +++ b/seqan/alignment_free/af_d2.h @@ -0,0 +1,124 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Jonathan Goeke +// ========================================================================== +// This header contains the implementation of the D2 score for alignment free +// sequence comparison (inner product of kmer counts). +// +// These functions can be called with alignmentFreeComparison(). +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_D2_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_D2_H_ + +namespace seqan { + +/* + * _alignmentFreeComparison is called by alignmentFreeComparison() (see alignment_free_comparison.h) + */ +template +void _alignmentFreeComparison(Matrix & scoreMatrix, + TStringSet const & sequenceSet, + AFScore const & score) +{ + //typedef typename Value::Type TString; + //typedef typename Value::Type TAlphabet; + typedef typename Iterator::Type TIteratorSet; + typedef typename Iterator > >::Type TIteratorSetInt; + //typedef Matrix TMatrix; + + unsigned seqNumber = length(sequenceSet); + + // Resize the scoreMatrix + setLength(scoreMatrix, 0, seqNumber); + setLength(scoreMatrix, 1, seqNumber); + resize(scoreMatrix, (TValue) 0); + + StringSet > kmerCounts; + resize(kmerCounts, seqNumber); + + // Count all kmers + TIteratorSetInt itKmerCounts = begin(kmerCounts); + TIteratorSet itSeqSet = begin(sequenceSet); + + for (; itSeqSet < end(sequenceSet); ++itSeqSet) + { + countKmers(value(itKmerCounts), value(itSeqSet), score.kmerSize); + ++itKmerCounts; + } + if(score.verbose) + { + std::cout << "\ncounted words"; + } + + // Calculate all pairwise scores and store them in scoreMatrix + for (unsigned rowIndex = 0; rowIndex < seqNumber; ++rowIndex) + { + if(score.verbose) + { + std::cout << "\nSequence number " << rowIndex; + } + for (unsigned colIndex = rowIndex; colIndex < seqNumber; ++colIndex) + { + _alignmentFreeCompareCounts(value(scoreMatrix, rowIndex, colIndex), kmerCounts[rowIndex], kmerCounts[colIndex], score); + value(scoreMatrix, colIndex, rowIndex) = value(scoreMatrix, rowIndex, colIndex); // Copy symmetric entries + } + } + +} + +/* + * Calculate pairwise score given the counts of all kmers + */ +template +void +_alignmentFreeCompareCounts(TValue & result, + String const & kmerCounts1, + String const & kmerCounts2, + AFScore const & /*score*/) +{ + typedef typename Iterator const>::Type TIteratorInt; + + TIteratorInt it1 = begin(kmerCounts1); + TIteratorInt it2 = begin(kmerCounts2); + + result = 0; + for (; it1 < end(kmerCounts1); ++it1) + { + result += value(it1) * value(it2); + ++it2; + } +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_D2_H_ diff --git a/seqan/alignment_free/af_d2star.h b/seqan/alignment_free/af_d2star.h new file mode 100644 index 0000000..c6bf16f --- /dev/null +++ b/seqan/alignment_free/af_d2star.h @@ -0,0 +1,224 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Jonathan Goeke +// ========================================================================== +// This header contains the implementation of the D2star score for alignment +// free sequence comparison. +// +// See: Reinert et al. J Comput Biol. 2009 Dec;16(12):1615-34. +// +// These functions can be called with alignmentFreeComparison(). +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_D2STAR_ORIGINAL_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_D2STAR_ORIGINAL_H_ + +namespace seqan { + +/* + * _alignmentFreeComparison is called by alignmentFreeComparison() (see alignment_free_comparison.h) + */ +template +void _alignmentFreeComparison(Matrix & scoreMatrix, + TStringSet const & sequenceSet, + AFScore const & score) +{ + + //typedef typename Iterator::Type TIteratorSet; + //typedef typename Iterator > >::Type TIteratorSetDouble; + + //typedef Matrix TMatrix; + + unsigned seqNumber = length(sequenceSet); + + // Resize the scoreMatrix + setLength(scoreMatrix, 0, seqNumber); + setLength(scoreMatrix, 1, seqNumber); + resize(scoreMatrix, (TValue) 0); + StringSet > standardisedKmerCounts; + resize(standardisedKmerCounts, seqNumber); + + // Calculate all pairwise scores and store them in scoreMatrix + for (unsigned rowIndex = 0; rowIndex < seqNumber; ++rowIndex) + { + if(score.verbose) + { + std::cout << "\nSequence number " << rowIndex; + } + for (unsigned colIndex = rowIndex; colIndex < seqNumber; ++colIndex) + { + _d2star(value(scoreMatrix, rowIndex, colIndex), sequenceSet[rowIndex], sequenceSet[colIndex], score); + value(scoreMatrix, colIndex, rowIndex) = value(scoreMatrix, rowIndex, colIndex); // Copy symmetric entries + } + } +} + +/* + * _d2star calculates the pairwise score of two sequences according to the paper referenced above. + */ +template +void _d2star(TValue & result, + TSequence const & sequence1, + TSequence const & sequence2, + AFScore const & score) +{ + typedef typename Value::Type TAlphabet; + typedef typename UnmaskedAlphabet_::Type TUnmaskedAlphabet; + + TValue missing = -pow(10.0, 10); + TSequence seq1seq2; + append(seq1seq2, sequence1); + append(seq1seq2, sequence2); + result = 0.0; + + // Note that there is some code below that looks like copy-and-paste. However, pulling this out into another + // function is the only way to get rid of the duplicate lines since we use different types. After some discussion, + // weese, goeke and holtgrew agreed that it is probably easier to read and maintain this way than to spread the code + // over to one more function. + if (score.bgModelOrder == 0) + { + // -------------------------------------------------------------------- + // Order 0 Background Model + // -------------------------------------------------------------------- + + String kmerCounts1; + String kmerCounts2; + String backgroundCounts; + String backgroundFrequencies; + resize(backgroundFrequencies, 4, 0); + countKmers(kmerCounts1, sequence1, score.kmerSize); + countKmers(kmerCounts2, sequence2, score.kmerSize); + countKmers(backgroundCounts, seq1seq2, 1); + int sumBG = 0; + for (unsigned i = 0; i < length(backgroundCounts); ++i) + { + sumBG += backgroundCounts[i]; + } + for (unsigned i = 0; i < length(backgroundCounts); ++i) + { + backgroundFrequencies[i] = backgroundCounts[i] / ((double)sumBG); + } + unsigned nvals = length(kmerCounts1); // Number of kmers + int len1 = 0; + int len2 = 0; + + for (unsigned l = 0; l < nvals; l++) + { + len1 += kmerCounts1[l]; + len2 += kmerCounts2[l]; + } + + String probabilities; // String of TValue to store the word probabilities p_w + resize(probabilities, nvals, missing); + + for (unsigned i = 0; i < nvals; ++i) + { + TValue p_w = 1; // Probability of kmer + + String w; + unhash(w, i, score.kmerSize); + calculateProbability(p_w, w, backgroundFrequencies); + TValue variance1 = 0.0; + TValue variance2 = 0.0; + + variance1 = pow(len1 * p_w, 0.5); + variance2 = pow(len2 * p_w, 0.5); + + // Test if variance is larer than 0 and smaller than inf before dividing + if ((variance1 > missing) && (variance1 < pow(10.0, 10))) + { + if (p_w > 0) + { + TValue stCount1 = (kmerCounts1[i] - p_w * len1) / variance1; + TValue stCount2 = (kmerCounts2[i] - p_w * len2) / variance2; + result += stCount1 * stCount2; + } + } + } + } + else + { + // -------------------------------------------------------------------- + // Higher Order Background Model + // -------------------------------------------------------------------- + + String kmerCounts1; + String kmerCounts2; + StringSet > bgSequences; + stringToStringSet(bgSequences, seq1seq2); // Create unmasked sequences + MarkovModel backgroundModel(score.bgModelOrder); + buildMarkovModel(backgroundModel, bgSequences); + countKmers(kmerCounts1, sequence1, score.kmerSize); + countKmers(kmerCounts2, sequence2, score.kmerSize); + + unsigned nvals = length(kmerCounts1); // Number of kmers + int len1 = 0; + int len2 = 0; + + for (unsigned l = 0; l < nvals; l++) + { + len1 += kmerCounts1[l]; + len2 += kmerCounts2[l]; + } + String probabilities; + resize(probabilities, nvals, missing); + for (unsigned i = 0; i < nvals; ++i) + { + TValue p_w = 1.0; // Probability of kmer + TValue variance = 0.0; + String w; + unhash(w, i, score.kmerSize); + p_w = emittedProbability(backgroundModel, w); + variance = ((TValue) pow(((TValue) len1 * len2), 0.5)) * p_w; + TValue variance1 = 0.0; + TValue variance2 = 0.0; + + variance1 = pow(len1 * p_w, 0.5); + variance2 = pow(len2 * p_w, 0.5); + + // Calculate standardised kmer Count + if ((variance > pow(10.0, -10)) && (variance < pow(10.0, 10))) + { + if (p_w > 0) + { + TValue stCount1 = (kmerCounts1[i] - p_w * len1) / variance1; + TValue stCount2 = (kmerCounts2[i] - p_w * len2) / variance2; + result += stCount1 * stCount2; + } + } + } + } +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_D2STAR_ORIGINAL_H_ diff --git a/seqan/alignment_free/af_d2z.h b/seqan/alignment_free/af_d2z.h new file mode 100644 index 0000000..6325af2 --- /dev/null +++ b/seqan/alignment_free/af_d2z.h @@ -0,0 +1,631 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Jonathan Goeke +// ========================================================================== +// This header contains the implementation of the D2z score for +// alignment free sequence comparison. +// +// See Kantorovitz et al. Bioinformatics 2007, Volume23, Issue13, +// Pp. i249-i255. +// +// These functions can be called with alignmentFreeComparison(). +// ========================================================================== + +// TODO(goeke): const could be added below for the input variables but the function value() in matrix_base (align) is not defined for const. Similarly, the function emittedProbabilty is not defined for const in statistics_markov_model.h + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_D2Z_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_D2Z_H_ + +namespace seqan { + +/* + * _alignmentFreeComparison is called by alignmentFreeComparison() (see alignment_free_comparison.h) + */ +template +void _alignmentFreeComparison(Matrix & scoreMatrix, + TStringSet const & sequenceSet, + AFScore const & score) +{ + typedef typename Value::Type TString; + typedef typename Value::Type TAlphabet; + typedef typename UnmaskedAlphabet_::Type TUnmaskedAlphabet; + typedef typename Iterator::Type TIteratorSet; + typedef typename Iterator > >::Type TIteratorSetUnsigned; + typedef typename Iterator > >::Type TIteratorSetDouble; + typedef typename Iterator > >::Type TIteratorMarkovModel; + + unsigned seqNumber = length(sequenceSet); + + // Resize scoreMatrix + setLength(scoreMatrix, 0, seqNumber); + setLength(scoreMatrix, 1, seqNumber); + resize(scoreMatrix, (TValue) 0); + + StringSet > kmerCounts; + resize(kmerCounts, seqNumber); + + // Note that there is some code below that looks like copy-and-paste. However, pulling this out into another + // function is the only way to get rid of the duplicate lines since we use different types. After some discussion, + // weese, goeke and holtgrew agreed that it is probably easier to read and maintain this way than to spread the code + // over to one more function. + if (score.bgModelOrder == 0) + { + // -------------------------------------------------------------------- + // Order 0 Background Model + // -------------------------------------------------------------------- + + StringSet > backgroundFrequencies; + resize(backgroundFrequencies, seqNumber); + + // Count all kmers and all background nucleotide frequencies and store them in stringSets + TIteratorSetUnsigned itKmerCounts = begin(kmerCounts); + TIteratorSetDouble itBackgroundFrequencies = begin(backgroundFrequencies); + + TIteratorSet itSeqSet = begin(sequenceSet); + for (; itSeqSet < end(sequenceSet); ++itSeqSet) + { + countKmers(*itKmerCounts, *itBackgroundFrequencies, *itSeqSet, score.kmerSize); + ++itKmerCounts; + ++itBackgroundFrequencies; + } + if(score.verbose) + { + std::cout << "\ncounted words"; + } + // Calculate all pairwise scores and store them in scoreMatrix + for (unsigned rowIndex = 0; rowIndex < seqNumber; ++rowIndex) + { + if(score.verbose) + { + std::cout << "\nSequence number " << rowIndex; + } + for (unsigned colIndex = rowIndex; colIndex < seqNumber; ++colIndex) + { + _alignmentFreeCompareCounts(value(scoreMatrix, rowIndex, colIndex), kmerCounts[rowIndex], + backgroundFrequencies[rowIndex], kmerCounts[colIndex], + backgroundFrequencies[colIndex], score); + value(scoreMatrix, colIndex, rowIndex) = value(scoreMatrix, rowIndex, colIndex); // Copy symmetric entries + } + } + } + else + { + // -------------------------------------------------------------------- + // Higher Order Background Model + // -------------------------------------------------------------------- + + String > backgroundModels; + resize(backgroundModels, seqNumber, MarkovModel(score.bgModelOrder)); + TIteratorMarkovModel itMM = begin(backgroundModels); + TIteratorSet itSeqSet = begin(sequenceSet); + // Count all kmers and all background nucleotide frequencies and store them in StringSets + TIteratorSetUnsigned itKmerCounts = begin(kmerCounts); + + for (; itSeqSet < end(sequenceSet); ++itSeqSet) + { + countKmers(*itKmerCounts, *itMM, *itSeqSet, score.kmerSize); + ++itKmerCounts; + if (itMM < end(backgroundModels)) + { + itMM->_computeAuxiliaryMatrices(); + ++itMM; + } + + } + if(score.verbose) + { + std::cout << "\ncounted words"; + } + // Calculate all pairwise scores and store them in scoreMatrix + for (unsigned rowIndex = 0; rowIndex < seqNumber; ++rowIndex) + { + if(score.verbose) + { + std::cout << "\nSequence number " << rowIndex; + } + for (unsigned colIndex = rowIndex; colIndex < seqNumber; ++colIndex) + { + _alignmentFreeCompareCounts(value(scoreMatrix, rowIndex, colIndex), kmerCounts[rowIndex], + backgroundModels[rowIndex], kmerCounts[colIndex], + backgroundModels[colIndex], score); + value(scoreMatrix, colIndex, rowIndex) = value(scoreMatrix, rowIndex, colIndex); // Copy symmetric entries + } + } + } +} + +/* + * computeExpectationD2 calculates the expected value of the D2 score given a Bernoulli model, + * see paper referenced above + */ +template +double computeExpectationD2(int const len1, int const len2, unsigned const k, TValue const * q1, TValue const * q2) +{ + TValue p2 = 0; + for (int i = 0; i < 4; i++) + p2 += q1[i] * q2[i]; + + int nbar1 = len1 - k + 1; + int nbar2 = len2 - k + 1; + + TValue retval = nbar1; + retval *= nbar2; + retval *= pow((double)p2, (int)k); + return retval; +} + +/* + * computeExpectationD2 calculates the expected value of the D2 score given a Markov model, + * see paper referenced above + */ +template +double computeExpectationD2(int const slen1, + int const slen2, + unsigned const k, + MarkovModel /*const*/ & bkg1, + MarkovModel /*const*/ & bkg2, + TValue & indicatorexpectation) +{ + unsigned mo = bkg1.order; + if (mo >= k) + { + // Error: Can't suppport markov order greater or equal to word length + exit(1); + } + + long emo = 1 << (2 * mo); // This is equal to pow(4, mo) + long ekmo = 1 << (2 * (k - mo)); // This is equal to pow(4, k - mo) + + TValue mean = 0; + for (long i = 0; i < emo; i++) + { + TValue term = value(bkg1.stationaryDistribution, i) * value(bkg2.stationaryDistribution, i); + TValue subterm = 0; + + for (long j = 0; j < ekmo; j++) + { + TValue subprob1 = _computeWordProbGivenPrefix(i, j, bkg1, k, mo); + TValue subprob2 = _computeWordProbGivenPrefix(i, j, bkg2, k, mo); + subterm += subprob1 * subprob2; + } + mean += term * subterm; + } + + indicatorexpectation = mean; // This is E[Y_ij], see paper referenced above. + int nbar1 = slen1 - k + 1; // Number of kmers in sequence1 + int nbar2 = slen2 - k + 1; // Number of kmers in sequence2 + return mean * ((TValue) nbar1 * nbar2); +} + +/* + * computeVarianceD2 calculates the variance of the D2 score given a Bernoulli model, + * see paper referenced above + */ +template +double computeVarianceD2(int len1, int len2, unsigned k, TValue * q1, TValue * q2) +{ + int nbar1 = len1 - k + 1; // Number of kmers in sequence 1 + int nbar2 = len2 - k + 1; // Number of kmers in sequence 2 + + int qbar1 = len1 - 2 * k + 2; // Number of overlapping kmers in sequence 1 + int qbar2 = len2 - 2 * k + 2; + + TValue p2 = 0, p31 = 0, p32 = 0; + for (int i = 0; i < 4; i++) + { + p2 += q1[i] * q2[i]; + p31 += q1[i] * q2[i] * q1[i]; + p32 += q1[i] * q2[i] * q2[i]; + } + + TValue variance = 0; + // 'Crabgrass' with l = 0 (= complete overlap), see paper referenced above + TValue power1 = pow((double)p32, (int)k) - pow((double)p2, 2 * (int)k); + power1 *= TValue(nbar1) * TValue(qbar2) * TValue(qbar2 - 1); + TValue power2 = pow((double)p31, (int)k) - pow((double)p2, 2 * (int)k); + power2 *= TValue(nbar2) * TValue(qbar1) * TValue(qbar1 - 1); + variance += power1 + power2; + + // 'Crabgrasses' with l > 0, see paper referenced above + for (unsigned l = 1; l <= k - 1; l++) + variance += 2 * TValue(nbar1 - l) * TValue(qbar2) * TValue(qbar2 - 1) * (pow((double)p2, (int)(2 * l)) * pow((double)p32, (int)(k - l)) - pow((double)p2, (int)(2 * k))) + 2 * TValue(nbar2 - l) * TValue(qbar1) * TValue(qbar1 - 1) * (pow((double)p2, (int)(2 * l)) * pow((double)p31, (int)(k - l)) - pow((double)p2, (int)(2 * k))); + + // Accordion main diagonal, see paper referenced above + variance += TValue(nbar1) * TValue(nbar2) * (pow((double)p2, (int)(k)) - pow((double)p2, (int)(2 * k))); + for (unsigned l = 1; l <= k - 1; l++) + variance += 2 * TValue(nbar1 - l) * TValue(nbar2 - l) * (pow((double)p2, (int)(k + l)) - pow((double)p2, (int)(2 * k))); + + return variance; +} + + +/* + * computeVarianceD2 calculates the variance of the D2 score given a Markov model, + * see paper referenced above + */ +template +double computeVarianceD2(int const slen1, + int const slen2, + unsigned const k, + MarkovModel /*const*/ & bkg1, + MarkovModel /*const*/ & bkg2, + TValue indicatorexpectation) +{ + unsigned mo = bkg1.order; + if (mo >= k) + { + // Error: Can't support markov order greater or equal to word length + exit(1); + } + + long emo = 1 << (2 * mo); // Equivalent to pow(4, mo); + long ekmo = 1 << (2 * (k - mo)); // Equivalent to pow(4, k - mo); + + int q1 = slen1 - 2 * k + 2; + int q2 = slen2 - 2 * k + 2; + int nbar1 = slen1 - k + 1; + int nbar2 = slen2 - k + 1; + + // Create matrix for Sbctilde + Matrix Sbctilde1; + setLength(Sbctilde1, 0, emo); + setLength(Sbctilde1, 1, emo); + resize(Sbctilde1); + + Matrix Sbctilde2; + setLength(Sbctilde2, 0, emo); + setLength(Sbctilde2, 1, emo); + resize(Sbctilde2); + + for (long i = 0; i < emo; i++) + { + for (long j = 0; j < emo; j++) + { + value(Sbctilde1, i, j) = (q1 * (q1 + 1) / 2) * value(bkg1.stationaryDistribution, j) - (q1 - 1) * value(bkg1._qppp, i, j) - value(bkg1._qppqpp, i, j); + value(Sbctilde2, i, j) = (q2 * (q2 + 1) / 2) * value(bkg2.stationaryDistribution, j) - (q2 - 1) * value(bkg2._qppp, i, j) - value(bkg2._qppqpp, i, j); + } + } + + // Compute sums of word probabilities and star probabilities of x-mers (x between mo + 1 and k) conditional on last or first (resp) mo-word, see paper referenced above + Matrix sump; // sump[x][wk] is the total word probability of every x-word ending with wk (which is of length mo) + setLength(sump, 0, k + 1); + setLength(sump, 1, emo); + resize(sump, 0.0); + + Matrix sumpstar; + setLength(sumpstar, 0, k + 1); + setLength(sumpstar, 1, emo); + resize(sumpstar, 0.0); + + + for (unsigned x = 0; x <= k; x++) + { + if (x <= mo) + { + + continue; + } + + for (long wk = 0; wk < emo; wk++) + { + TValue sum = 0; + long exmo = 1 << (2 * (x - mo)); // Equivalent to pow(4, x - mo); + for (long wpre = 0; wpre < exmo; wpre++) + { + sum += _computeWordProb((wpre << (2 * mo)) + wk, bkg1, x, mo) * _computeWordProb((wpre << (2 * mo)) + wk, bkg2, x, mo); + } + value(sump, x, wk) = sum; + } + + for (long u1 = 0; u1 < emo; u1++) + { + TValue sum = 0; + long exmo = 1 << (2 * (x - mo)); // Equivalent to pow(4, x - mo); + for (long usuf = 0; usuf < exmo; usuf++) + { + sum += _computeWordProbGivenPrefix(u1, usuf, bkg1, x, mo) * _computeWordProbGivenPrefix(u1, usuf, bkg2, x, mo); + } + value(sumpstar, x, u1) = sum; + } + } + + // Handle the non overlap terms first + TValue covnonoverlap = 0; + for (long wk = 0; wk < emo; wk++) + { + for (long u1 = 0; u1 < emo; u1++) + { + TValue term = value(Sbctilde1, wk, u1) * value(Sbctilde2, wk, u1) * value(sump, k, wk) * value(sumpstar, k, u1); + covnonoverlap += 4 * term; + } + } + TValue subtractFromNonOverlap = (TValue)q1 * (q1 - 1) * q2 * (q2 - 1); + subtractFromNonOverlap *= pow(indicatorexpectation, 2); + covnonoverlap -= subtractFromNonOverlap; + // Compute 'crabgrass' terms, see paper referenced above + TValue covcrabgrass = 0; + + // Case 1: overlap >= mo + for (unsigned m = 1; m <= k - mo; m++) + { + long ekm = 1 << (2 * (k - m)); // Equivalent to pow(4, k - m) + long moonesflag = (1 << (2 * mo)) - 1; + long kmmoonesflag = (1 << (2 * (k - m - mo))) - 1; + for (long v = 0; v < ekm; v++) + { + long vsuf = v & moonesflag; // Last morder chars of v + long vpre = v >> (2 * (k - m - mo)); // First morder chars of v, equivalent to v / pow(4, k - m - mo) + long vsuf2 = v & kmmoonesflag; // Remaining k-m-morder chars of v; equivalent to v % pow(4, k - m - mo) + // In the following, if m = k - mo, _computeWordProbGivenPrefix(.,.,.,k - m, mo) will return 1, as it should + // Overlap in A, separate in B + TValue term1 = value(Sbctilde2, vsuf, vpre); + term1 *= _computeWordProbGivenPrefix(vpre, vsuf2, bkg1, k - m, mo); + term1 *= pow(_computeWordProbGivenPrefix(vpre, vsuf2, bkg2, k - m, mo), 2); + term1 *= value(sump, m + mo, vpre); + term1 *= value(sumpstar, m + mo, vsuf); + // Overlap in B, separate in A + TValue term2 = value(Sbctilde1, vsuf, vpre); + term2 *= _computeWordProbGivenPrefix(vpre, vsuf2, bkg2, k - m, mo); + term2 *= pow(_computeWordProbGivenPrefix(vpre, vsuf2, bkg1, k - m, mo), 2); + term2 *= value(sump, m + mo, vpre); + term2 *= value(sumpstar, m + mo, vsuf); + + covcrabgrass += 4 * q1 * term1 + 4 * q2 * term2; + } + } + // Case 2: overlap < morder + for (unsigned m = k - mo + 1; m <= k - 1; m++) + { + int tlen = 2 * mo - (k - m); + long et = 1 << (2 * tlen); // Equivalent to pow(4, tlen); + long moonesflag = (1 << (2 * mo)) - 1; + long tmoonesflag = (1 << (2 * (tlen - mo))) - 1; + for (long t = 0; t < et; t++) + { + long tsuf = t & moonesflag; // Last morder chars of t; equivalent to t % emo; + long tpre = t >> (2 * (tlen - mo)); // First morder chars of t, equivalent to t / pow(4, tlen - mo) + long tsuf2 = t & tmoonesflag; // Remaining tlen-morder chars of t, equivalent to t % etmo; + // Overlap in A, separate in B + TValue term1 = value(Sbctilde2, tpre, tsuf); + term1 *= _computeWordProbGivenPrefix(tpre, tsuf2, bkg1, tlen, mo); + term1 *= value(sump, k, tpre); + term1 *= value(sumpstar, k, tsuf); + // Overlap in B, separate in A + TValue term2 = value(Sbctilde1, tpre, tsuf); + term2 *= _computeWordProbGivenPrefix(tpre, tsuf2, bkg2, tlen, mo); + term2 *= value(sump, k, tpre); + term2 *= value(sumpstar, k, tsuf); + + covcrabgrass += 4 * q1 * term1 + 4 * q2 * term2; + } + } + + // Case 3: m=0 (complete overlap) + long moonesflag = (1 << (2 * mo)) - 1; + for (long wpre = 0; wpre < emo; wpre++) + { + // First morder chars of w + TValue term1 = 0; + TValue term2 = 0; + for (long wsuf2 = 0; wsuf2 < ekmo; wsuf2++) + { + // Remaining k-morder chars of w + long wsuf = ((wpre << (2 * (k - mo))) + wsuf2) & moonesflag; // Last morder chars of w + term1 += 2 * nbar1 * value(Sbctilde2, wsuf, wpre) * _computeWordProbGivenPrefix(wpre, wsuf2, bkg1, k, mo) * pow(_computeWordProbGivenPrefix(wpre, wsuf2, bkg2, k, mo), 2); + term2 += 2 * nbar2 * value(Sbctilde1, wsuf, wpre) * _computeWordProbGivenPrefix(wpre, wsuf2, bkg2, k, mo) * pow(_computeWordProbGivenPrefix(wpre, wsuf2, bkg1, k, mo), 2); + } + covcrabgrass += (term1 + term2) * value(bkg1.stationaryDistribution, wpre) * value(bkg2.stationaryDistribution, wpre); + } + + // Ignored edge effects, see paper referened above + // Subtract expectations + TValue subtractfromcrabgrass = (((2 * q1 * k - nbar1) * (double)q2 * double(q2 - 1)) + ((2 * q2 * k - nbar2) * (double)q1 * double(q1 - 1))); + subtractfromcrabgrass *= pow(indicatorexpectation, 2); + covcrabgrass -= subtractfromcrabgrass; + + // Compute the accordion main diagonal terms + TValue covaccordiondiag = 0; + + for (unsigned m = 1; m <= k - 1; m++) + { + long tlen; + if (m <= mo - 1) + tlen = m + mo; + else + tlen = 2 * mo - 1; + long et = 1 << (2 * tlen); // Equivalent to pow(4, tlen) + long moonesflag = (1 << (2 * mo)) - 1; + long tmoonesflag = (1 << (2 * (tlen - mo))) - 1; + + TValue mterm = 0; + for (long t = 0; t < et; t++) + { + TValue term = 1; + long tpre = t >> (2 * (tlen - mo)); // First morder chars of t, equivalent to t / pow(4, tlen - mo) + long tsuf2 = t & tmoonesflag; // The remaining tlen - morder chars of t, equivalent to t % etmo; + term *= _computeWordProbGivenPrefix(tpre, tsuf2, bkg1, tlen, mo) * _computeWordProbGivenPrefix(tpre, tsuf2, bkg2, tlen, mo); + term *= value(sump, k, tpre); + if (m >= mo) + { + long tsuf = t & moonesflag; // Last morder chars of t, equivalent to t%emo; + term *= value(sumpstar, m + 1, tsuf); + } + mterm += term; + } + covaccordiondiag += 2 * (nbar1 - m) * (nbar2 - m) * mterm; + } + covaccordiondiag += nbar1 * nbar2 * indicatorexpectation; // Complete overlap term + covaccordiondiag -= (nbar1 * nbar2 * (2 * k - 1) - (nbar1 + nbar2) * k * (k - 1) + (k - 1) * k * (2 * k - 1) / 3) * pow(indicatorexpectation, 2); + TValue variance = covnonoverlap + covcrabgrass + covaccordiondiag; + return variance; + +} + +/* + * Calculate pairwise score given the counts of all kmers and the background Bernoulli models + */ +template +void _alignmentFreeCompareCounts(TValue & result, + String const & kmerCounts1, + TStringBG const & backgroundFrequencies1, + String const & kmerCounts2, + TStringBG const & backgroundFrequencies2, + AFScore const & score) +{ + typedef typename Value::Type TValueBG; + TValueBG sum = 0; + unsigned len1 = score.kmerSize - 1; + unsigned len2 = score.kmerSize - 1; + unsigned nvals = length(kmerCounts1); + + for (unsigned l = 0; l < nvals; l++) + { + len1 += kmerCounts1[l]; + len2 += kmerCounts2[l]; + + sum += kmerCounts1[l] * kmerCounts2[l]; + } + + TValueBG q1[4]; + TValueBG q2[4]; + for (int l = 0; l < 4; l++) + { + q1[l] = backgroundFrequencies1[l]; + q2[l] = backgroundFrequencies2[l]; + } + + // Compute expected value and variance (IID) + double E = computeExpectationD2(len1, len2, score.kmerSize, q1, q2); + double var = computeVarianceD2(len1, len2, score.kmerSize, q1, q2); + + if ((var <= 0)) + { + if(score.verbose) + { + std::cout << "Error: negative variance\n"; + } + result = 0; + return; + } + // Calculate z-score + result = (TValue) (sum - E) / pow(var, 0.5); +} + +/* + * Calculate pairwise score given the counts of all kmers and the background Markov models + */ +template +void _alignmentFreeCompareCounts(TValue & result, + String const & kmerCounts1, + MarkovModel /*const*/ & bgModel1, + String const & kmerCounts2, + MarkovModel /*const*/ & bgModel2, + AFScore const & score) +{ + unsigned nvals = length(kmerCounts1); + int sum = 0; + int sumCounts1 = score.kmerSize - 1; + int sumCounts2 = score.kmerSize - 1; + + for (unsigned l = 0; l < nvals; l++) + { + sumCounts1 += kmerCounts1[l]; + sumCounts2 += kmerCounts2[l]; + sum += value(kmerCounts1, l) * value(kmerCounts2, l); // Calculate the inner product + } + + TValue D2 = (TValue) sum; + + // Compute mean and variance + TValue indicatorexpectation = 0; + + double E = computeExpectationD2(sumCounts1, sumCounts2, score.kmerSize, bgModel1, bgModel2, indicatorexpectation); + double var = computeVarianceD2(sumCounts1, sumCounts2, score.kmerSize, bgModel1, bgModel2, indicatorexpectation); + + if (var <= 0) + { + result = 0; + return; + } + // Return z-score of D2 + result = (D2 - E) / pow(var, 0.5); +} + +/* + * Compute the word probability given a Markov model + * see paper referenced on top + */ +template +double _computeWordProb(long const word, MarkovModel /*const*/ & bkg, unsigned const k, int const mo) +{ + // mo needs to be passed, since that decides the prefix + // Similarly, this function needs to know the total length of the word k + long prefix = word >> (2 * (k - mo)); // Equivalent to word / pow(4, k - mo); gets the first mo chars of word + long suffix = word & ((1 << (2 * (k - mo))) - 1); // Get the last (k - mo) chars of word + return value(bkg.stationaryDistribution, prefix) * _computeWordProbGivenPrefix(prefix, suffix, bkg, k, mo); +} + +/* + * Compute the word probability given a Markov model + * see paper referenced on top + */ +template +double _computeWordProbGivenPrefix(long const prefix, long const suffix, MarkovModel /*const*/ & bkg, unsigned const k, unsigned const mo) +{ + // Computes p_ * (prefix suffix) + // Calculate only if k - mo >= 1; otherwise return 1 + if (k - mo <= 0) + return 1; + + TValue prob = 1; + long pre = prefix; + long jcopy = suffix; + + // Iterate through successive positions of the suffix + for (unsigned l = 0; l < k - mo; l++) + { + // Get the first char of jcopy, which is of length k - mo; equivalent to jcopy / pow(4, k - mo - 1) + long jcopyfirst = jcopy >> (2 * (k - mo - 1)); + long suf = ((pre & ((1 << (2 * (mo - 1))) - 1)) << 2) + jcopyfirst; + + // prob *=P[pre][suf]; P is the transition matrix + prob *= value(bkg.transition, pre, suf); + // Erase the first char of jcopy, and preserve its length at k - mo by shifting one char to the left; equivalent to (jcopy % pow(4, k - mo - 1)) * 4; + jcopy = (jcopy & ((1 << (2 * (k - mo - 1))) - 1)) << 2; + pre = suf; + } + return prob; +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_D2Z_H_ diff --git a/seqan/alignment_free/af_n2.h b/seqan/alignment_free/af_n2.h new file mode 100644 index 0000000..ac2110a --- /dev/null +++ b/seqan/alignment_free/af_n2.h @@ -0,0 +1,641 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Jonathan Goeke +// ========================================================================== +// This header contains the implementation of the N2 score for alignment free +// sequence comparison with word neighbourhood counts +// +// See: Goeke et al, to appear. +// +// These functions can be called with alignmentFreeComparison(). +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_N2_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_N2_H_ + +namespace seqan { + +/* + * This function returns a string with indices indicating which k-mer is the + * reverse complement k-mer: i=revComIndex[revComIndex[i]] + */ +inline void _initialiseRevComIndex(String & revComIndex, unsigned const k) +{ + unsigned myLength = (unsigned)pow(4.0, (int)k); + resize(revComIndex, myLength, 0); + Shape myShape; + resize(myShape, k); + for (unsigned i = 0; i < myLength; ++i) + { + String w; + unhash(w, i, k); + DnaStringReverseComplement wRC(w); + unsigned hashValue = hash(myShape, begin(wRC)); + revComIndex[i] = hashValue; + } + +} + +/* + * This function returns a stringSet with strings of indices indicating which + * k-mers belong to the word neighbourhood for every k-mer (all k-mers with + * one mismatch) + */ +inline void _initialiseKmerNeighbourhood(StringSet > & kmerNeighbourhood, + unsigned const k, bool const revCom, + String const & revComIndex) +{ + unsigned myLength = (unsigned)pow(4.0, (int)k); + Shape myShape; + resize(myShape, k); + resize(kmerNeighbourhood, myLength); + for (unsigned i = 0; i < myLength; ++i) + { + resize(kmerNeighbourhood[i], 1, i); + + String w; + unhash(w, i, k); + if ((revComIndex[i] != i) && (revCom == true)) + { + appendValue(kmerNeighbourhood[i], revComIndex[i]); + } + for (unsigned j = 0; j < k; ++j) + { + for (unsigned l = 0; l < 4; ++l) + { + String wTMP; + wTMP = w; + if (wTMP[j] != l) + { + wTMP[j] = l; + unsigned hashValue = hash(myShape, begin(wTMP)); + // Check for double word occurrences + bool duplicate = false; + if (revCom == true) + { + + for (unsigned n = 0; n < length(kmerNeighbourhood[i]); ++n) + { + if ((hashValue) == kmerNeighbourhood[i][n]) + { + duplicate = true; + break; + } + } + + } + + if (duplicate == false) + { + appendValue(kmerNeighbourhood[i], hashValue); + if (revCom == true) + { + if (revComIndex[hashValue] != hashValue) + { + appendValue(kmerNeighbourhood[i], revComIndex[hashValue]); + } + } + } + } + } + } + } +} + +/* + * _alignmentFreeComparison is called by alignmentFreeComparison() (see alignment_free_comparison.h) + */ +template +void _alignmentFreeComparison(Matrix & scoreMatrix, + TStringSet const & sequenceSet, + AFScore const & score) +{ + + + + typedef typename Value::Type TString; + typedef typename Value::Type TAlphabet; + typedef typename UnmaskedAlphabet_::Type TUnmaskedAlphabet; + typedef typename Iterator::Type TIteratorSet; + typedef typename Iterator > >::Type TIteratorSetDouble; + + + // Initialise the reverse complement hash table + String revComIndex; + StringSet > kmerNeighbourhood; + _initialiseRevComIndex(revComIndex, score.kmerSize); + if (score.revCom == "both_strands") + { + _initialiseKmerNeighbourhood(kmerNeighbourhood, score.kmerSize, true, revComIndex); + } + else + { + _initialiseKmerNeighbourhood(kmerNeighbourhood, score.kmerSize, false, revComIndex); + } + + unsigned seqNumber = length(sequenceSet); + + setLength(scoreMatrix, 0, seqNumber); + setLength(scoreMatrix, 1, seqNumber); + resize(scoreMatrix, (TValue) 0); + + StringSet > standardisedKmerCounts; + resize(standardisedKmerCounts, seqNumber); + // Count all kmers and all background nucleotide frequencies and store them in StringSets + TIteratorSetDouble itStandardisedKmerCounts = begin(standardisedKmerCounts); + TIteratorSet itSeqSet = begin(sequenceSet); + for (; itSeqSet < end(sequenceSet); ++itSeqSet) + { + + _standardiseCounts(*itStandardisedKmerCounts, revComIndex, kmerNeighbourhood, *itSeqSet, score); + if(score.verbose) + { + std::cout << "\n" << position(itSeqSet); + } + ++itStandardisedKmerCounts; + } + + if (score.norm == true) // Normalise the score so that sequence-self-comparisons are always 1 + { + itStandardisedKmerCounts = begin(standardisedKmerCounts); + for (; itStandardisedKmerCounts < end(standardisedKmerCounts); ++itStandardisedKmerCounts) + { + TValue normValue = 0.0; + for (unsigned i = 0; i < length(value(itStandardisedKmerCounts)); ++i) + { + normValue += value(itStandardisedKmerCounts)[i] * value(itStandardisedKmerCounts)[i]; + } + for (unsigned i = 0; i < length(value(itStandardisedKmerCounts)); ++i) + { + value(itStandardisedKmerCounts)[i] /= sqrt(normValue); + } + + } + } + + if (!(score.outputFile == "")) + { + std::ofstream myfile; + myfile.open(toCString(score.outputFile)); + for (unsigned i = 0; i < length(standardisedKmerCounts[0]); ++i) + { + String w; + unhash(w, i, score.kmerSize); + myfile << "\t" << w; + } + myfile << "\n"; + for (unsigned seqIndex = 0; seqIndex < seqNumber; ++seqIndex) + { + myfile << "Seq" << seqIndex; + for (unsigned i = 0; i < length(standardisedKmerCounts[seqIndex]); ++i) + { + myfile << "\t" << standardisedKmerCounts[seqIndex][i]; + } + myfile << "\n"; + } + myfile.close(); + } + + if(score.verbose) + { + std::cout << "\ncounted words"; + } + + // Calculate all pairwise scores and store them in scoreMatrix + for (unsigned rowIndex = 0; rowIndex < seqNumber; ++rowIndex) + { + if(score.verbose) + { + std::cout << "\nSequence number " << rowIndex; + } + for (unsigned colIndex = rowIndex; colIndex < seqNumber; ++colIndex) + { + _alignmentFreeCompareCounts(value(scoreMatrix, rowIndex, colIndex), revComIndex, standardisedKmerCounts[rowIndex], standardisedKmerCounts[colIndex], score); + value(scoreMatrix, colIndex, rowIndex) = value(scoreMatrix, rowIndex, colIndex); // Copy symmetric entries + } + } +} + +/* + * Calculate pairwise score given the counts of all kmers + */ +template +void +_alignmentFreeCompareCounts(TValue & result, + String const revComIndex, + TString const & kmerCounts1, + TString const & kmerCounts2, + AFScore const & score) +{ + typedef typename Iterator::Type TIteratorTString; + + TIteratorTString it1 = begin(kmerCounts1); + TIteratorTString it2 = begin(kmerCounts2); + result = 0.0; + TValue resultRC = 0.0; + for (; it1 < end(kmerCounts1); ++it1) + { + result += (TValue)(value(it1) * value(it2)); + // Computation of the reverse complement strand score + if ((score.revCom != "") && (score.revCom != "both_strands")) + { + unsigned hashValue = revComIndex[position(it1)]; + resultRC += (TValue)(value(it1) * kmerCounts2[hashValue]); + } + ++it2; + } + + if (score.revCom == "mean") + { + result = (TValue) (resultRC + result) / 2; + } + else if (score.revCom == "max") + { + result = std::max(resultRC, result); + } + else if (score.revCom == "min") + { + result = std::min(resultRC, result); + } +} + +/* + * count kmers and standardise count vectors for Dna5 and markov model background + */ +template +void _standardiseCounts(TString & standardisedCounts, + String const & revComIndex, + StringSet > const & kmerNeighbourhood, + TSequence const & sequence, + AFScore const & score) +{ + typedef typename Value::Type TAlphabet; + typedef typename UnmaskedAlphabet_::Type TUnmaskedAlphabet; + typedef typename Value::Type TValue; + typedef typename Iterator, Rooted>::Type TIteratorUnsigned; + typedef typename Iterator::Type TIteratorTString; + + unsigned alphabetSize = ValueSize::VALUE; + + // Save all word covariances which are computed in covariance Matrix to avoid double computations + Matrix covarianceMatrix; + TValue missing = -pow(10.0, 10); + if (score.mismatches > 0) + { + setLength(covarianceMatrix, 0, pow((double)alphabetSize, (int)score.kmerSize)); + setLength(covarianceMatrix, 1, pow((double)alphabetSize, (int)score.kmerSize)); + resize(covarianceMatrix, missing); + } + + // Note that there is some code below that looks like copy-and-paste. However, pulling this out into another + // function is the only way to get rid of the duplicate lines since we use different types. After some discussion, + // weese, goeke and holtgrew agreed that it is probably easier to read and maintain this way than to spread the code + // over to one more function. + if (score.bgModelOrder == 0) + { + // ---------------------------------------------------------------------- + // Order 0 Background Model + // ---------------------------------------------------------------------- + + String kmerCounts; + String backgroundFrequencies; + countKmers(kmerCounts, backgroundFrequencies, sequence, score.kmerSize); + int nvals = length(kmerCounts); // Number of kmers + int len1 = 0; + for (int l = 0; l < nvals; l++) + { + len1 += kmerCounts[l]; + } + resize(standardisedCounts, nvals, (TValue) 0.0); + + // String of TValue to store the word probabilites p_w + String probabilities; + resize(probabilities, nvals, missing); + + TIteratorUnsigned itCounts; + TIteratorTString itStandardisedCounts; + + itCounts = begin(kmerCounts); + itStandardisedCounts = begin(standardisedCounts); + + for (; itCounts < end(kmerCounts); ++itCounts) + { + // Temporary counter for mismatch kmer counting + TValue counterTMP = 0; + TValue p_w = 1; // Probability of kmer + + String w; + unhash(w, (unsigned)position(itCounts), score.kmerSize); + calculateProbability(p_w, w, backgroundFrequencies); + TValue variance = 0; + if ((score.mismatches == 1)) // Mismatch score calculation + { + p_w = 0; + // The first word in the kmerNeighbourhood is the kmer itself, it is weighted normally + // Sum of all entries in the covariance matrix. only once computed + unsigned wordHash = position(itCounts); + unsigned wordRCHash = revComIndex[wordHash]; + + for (unsigned row = 0; row < length(kmerNeighbourhood[wordHash]); ++row) + { + unsigned wordRowHash = kmerNeighbourhood[wordHash][row]; + // The kmer itself is weighted normally + if (wordRowHash == wordHash) // The first word in the kmerNeighbourhood is the kmer itself, it is weighted normally + { + counterTMP += (TValue) kmerCounts[wordRowHash]; + } + else if ((score.revCom == "both_strands") && (wordRowHash == wordRCHash)) + { + counterTMP += ((TValue) kmerCounts[wordRowHash]); + } + else + { + counterTMP += ((TValue) kmerCounts[wordRowHash]) * score.mismatchWeight; + } + String wMM1; + unhash(wMM1, wordRowHash, score.kmerSize); + + for (unsigned col = row; col < length(kmerNeighbourhood[wordHash]); ++col) + { + unsigned wordColHash = kmerNeighbourhood[wordHash][col]; + if (value(covarianceMatrix, wordColHash, wordRowHash) == missing) + { + String wMM2; + + unhash(wMM2, wordColHash, score.kmerSize); + calculateCovariance(value(covarianceMatrix, wordColHash, wordRowHash), wMM1, wMM2, backgroundFrequencies, (len1 + score.kmerSize - 1)); + value(covarianceMatrix, wordRowHash, wordColHash) = value(covarianceMatrix, wordColHash, wordRowHash); + } + if (row == col) // Variance of weighted variables + { + if ((wordRowHash == wordHash) || (score.revCom == "both_strands" && (wordRowHash == wordRCHash))) // The variance of the kmer is counted full + { + variance += value(covarianceMatrix, wordRowHash, wordColHash); + } + else + { + variance += pow(score.mismatchWeight, 2) * value(covarianceMatrix, wordRowHash, wordColHash); // Calculate weighted variances + } + } + // The covariance of the kmer and the reverse complement is weighted full + else if ((score.revCom == "both_strands") && (((wordRowHash == wordHash) && (wordColHash == wordRCHash)) || ((wordRowHash == wordRCHash) && (wordColHash == wordHash)))) + { + variance += (2.0) * value(covarianceMatrix, wordRowHash, wordColHash); + } + else if ((wordRowHash == wordHash || wordColHash == wordHash) || (score.revCom == "both_strands" && (wordRowHash == wordRCHash || wordColHash == wordRCHash))) // The covariance is weighted half + { + variance += (2.0) * score.mismatchWeight * value(covarianceMatrix, wordRowHash, wordColHash); + } + else // The covariance is weighted^2 + { + variance += (2.0) * pow(score.mismatchWeight, 2) * value(covarianceMatrix, wordRowHash, wordColHash); + } + } + if (probabilities[wordRowHash] == missing) + { + calculateProbability(probabilities[wordRowHash], wMM1, backgroundFrequencies); + } + if (wordRowHash == wordHash) //Weight the probabilities and expected values, normal weight for the kmer itself + { + p_w += probabilities[wordRowHash]; + } + else if ((score.revCom == "both_strands") && (wordRowHash == wordRCHash)) // Weight the probabiliets and expected values, normal weight for the reverse complement kmer itself + { + p_w += probabilities[wordRowHash]; + } + else + { + p_w += score.mismatchWeight * probabilities[wordRowHash]; + } + } + variance = pow(variance, 0.5); + } // End of mismatch calculation + else if (score.revCom == "both_strands") + { + TValue variance1; + TValue variance2; + TValue covariance; + String wRC; + unhash(wRC, (unsigned) revComIndex[(unsigned)position(itCounts)], score.kmerSize); + calculateVariance(variance1, w, backgroundFrequencies, (len1 + score.kmerSize - 1)); + calculateVariance(variance2, wRC, backgroundFrequencies, (len1 + score.kmerSize - 1)); + calculateCovariance(covariance, w, wRC, backgroundFrequencies, (len1 + score.kmerSize - 1)); + variance = pow((variance1 + variance2 + (2.0) * covariance), 0.5); + TValue p_wRC = 1; // Probability of the reverse complement kmer + calculateProbability(p_wRC, wRC, backgroundFrequencies); + p_w += p_wRC; + } + else + { + calculateVariance(variance, w, backgroundFrequencies, (len1 + score.kmerSize - 1)); + variance = pow(variance, 0.5); + } + if ((variance > pow(10.0, -10)) && (variance < pow(10.0, 10))) + { + if (p_w > 0) + { + if (score.mismatches > 0) + { + value(itStandardisedCounts) = ((TValue) ((TValue) counterTMP) - p_w * ((TValue)len1)) / variance; + } + else if (score.revCom == "both_strands") + { + value(itStandardisedCounts) = ((TValue) ((TValue) value(itCounts) + kmerCounts[revComIndex[(unsigned)position(itCounts)]]) - p_w * ((TValue)len1)) / variance; + } + else + { + value(itStandardisedCounts) = ((TValue) ((TValue) value(itCounts)) - p_w * ((TValue)len1)) / variance; + } + } + } + ++itStandardisedCounts; + } + } + else + { + // ---------------------------------------------------------------------- + // Higher Order Background Model + // ---------------------------------------------------------------------- + + String kmerCounts; + MarkovModel backgroundModel(score.bgModelOrder); + countKmers(kmerCounts, backgroundModel, sequence, score.kmerSize); + + int nvals = length(kmerCounts); // Number of kmers + int len1 = 0; + for (int l = 0; l < nvals; l++) + { + len1 += kmerCounts[l]; + } + resize(standardisedCounts, nvals, (TValue) 0.0); + String probabilities; + resize(probabilities, nvals, missing); + TIteratorUnsigned itCounts; + TIteratorTString itStandardisedCounts; + itCounts = begin(kmerCounts); + itStandardisedCounts = begin(standardisedCounts); + + for (; itCounts < end(kmerCounts); ++itCounts) + { + TValue p_w = 1; // Probability of kmer + TValue variance = 0; + String w; + unhash(w, (unsigned)position(itCounts), score.kmerSize); + p_w = emittedProbability(backgroundModel, w); + + TValue counterTMP = 0.0; + if ((score.mismatches == 1)) // Start of mismatch calculations + { + p_w = 0; + // The first word in the kmerNeighbourhood is the kmer itself, it is weighted normally + // Sum of all entries in the covariance matrix, computed and stored dynamically + unsigned wordHash = position(itCounts); + unsigned wordRCHash = revComIndex[wordHash]; + + for (unsigned row = 0; row < length(kmerNeighbourhood[wordHash]); ++row) + { + unsigned wordRowHash = kmerNeighbourhood[wordHash][row]; + // The kmer itself is weighted normally + if (wordRowHash == wordHash) // The first word in the kmerNeighbourhood is the kmer itself, it is weighted normally + { + counterTMP += (TValue) kmerCounts[wordRowHash]; + } + else if ((score.revCom == "both_strands") && (wordRowHash == wordRCHash)) + { + counterTMP += ((TValue) kmerCounts[wordRowHash]); + } + else + { + counterTMP += ((TValue) kmerCounts[wordRowHash]) * score.mismatchWeight; + } + String wMM1; + unhash(wMM1, wordRowHash, score.kmerSize); + for (unsigned col = row; col < length(kmerNeighbourhood[wordHash]); ++col) + { + unsigned wordColHash = kmerNeighbourhood[wordHash][col]; + if (value(covarianceMatrix, wordColHash, wordRowHash) == missing) + { + String wMM2; + unhash(wMM2, wordColHash, score.kmerSize); + calculateCovariance(value(covarianceMatrix, wordColHash, wordRowHash), wMM1, wMM2, backgroundModel, (len1 + score.kmerSize - 1)); + value(covarianceMatrix, wordRowHash, wordColHash) = value(covarianceMatrix, wordColHash, wordRowHash); + } + if (row == col) // Variance of weighted variables + { + if ((wordRowHash == wordHash) || (score.revCom == "both_strands" && (wordRowHash == wordRCHash))) // The variance of the kmer is counted full + { + variance += value(covarianceMatrix, wordRowHash, wordColHash); + } + else + { + variance += pow(score.mismatchWeight, 2) * value(covarianceMatrix, wordRowHash, wordColHash); + } + } + // The covariance of the kmer and the reverse complement is weighted full + else if ((score.revCom == "both_strands") && (((wordRowHash == wordHash) && (wordColHash == wordRCHash)) || ((wordRowHash == wordRCHash) && (wordColHash == wordHash)))) + { + variance += (2.0) * value(covarianceMatrix, wordRowHash, wordColHash); + } + else if ((wordRowHash == wordHash || wordColHash == wordHash) || (score.revCom == "both_strands" && (wordRowHash == wordRCHash || wordColHash == wordRCHash))) // The covariance is weighted half + { + variance += (2.0) * score.mismatchWeight * value(covarianceMatrix, wordRowHash, wordColHash); + } + else // The covariance is weighted^2 + { + variance += (2.0) * pow(score.mismatchWeight, 2) * value(covarianceMatrix, wordRowHash, wordColHash); + } + } + if (probabilities[wordRowHash] == missing) + { + probabilities[wordRowHash] = emittedProbability(backgroundModel, wMM1); + } + if (wordRowHash == wordHash) //Weight the probabiliets and expected values, normal weight for the kmer itself + { + p_w += probabilities[wordRowHash]; + } + else if ((score.revCom == "both_strands") && (wordRowHash == wordRCHash)) // Weight the probabiliets and expected values, normal weight for the reverse complement kmer itself + { + p_w += probabilities[wordRowHash]; + } + else + { + p_w += score.mismatchWeight * probabilities[wordRowHash]; + } + } + variance = pow(variance, 0.5); // Calculate the standard deviation + } // End of mismatch calculations + else if (score.revCom == "both_strands") + { + TValue variance1; + TValue variance2; + TValue covariance; + String wRC; + unhash(wRC, (unsigned)revComIndex[(unsigned)position(itCounts)], score.kmerSize); + calculateVariance(variance1, w, backgroundModel, (len1 + score.kmerSize - 1)); + calculateVariance(variance2, wRC, backgroundModel, (len1 + score.kmerSize - 1)); + calculateCovariance(covariance, w, wRC, backgroundModel, (len1 + score.kmerSize - 1)); + variance = pow((variance1 + variance2 + (2.0) * covariance), 0.5); + TValue p_wRC = 1; // Probability of the reverse complement kmer + p_wRC = emittedProbability(backgroundModel, wRC); + p_w += p_wRC; + } + else + { + calculateVariance(variance, w, backgroundModel, (len1 + score.kmerSize - 1)); + variance = pow(variance, 0.5); + } + if ((variance > pow(10.0, -10)) && (variance < pow(10.0, 10))) + { + if (p_w > 0) + { + if (score.mismatches > 0) + { + value(itStandardisedCounts) = ((TValue) ((TValue) counterTMP) - p_w * ((TValue)len1)) / variance; + } + else if (score.revCom == "both_strands") + { + value(itStandardisedCounts) = ((TValue) ((TValue) value(itCounts) + kmerCounts[revComIndex[(unsigned)position(itCounts)]]) - p_w * ((TValue)len1)) / variance; + } + else + { + value(itStandardisedCounts) = ((TValue) ((TValue) value(itCounts)) - p_w * ((TValue)len1)) / ((TValue) variance); + } + } + ++itStandardisedCounts; + } + } + } +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_AF_N2_H_ diff --git a/seqan/alignment_free/alignment_free_base.h b/seqan/alignment_free/alignment_free_base.h new file mode 100644 index 0000000..c3a7471 --- /dev/null +++ b/seqan/alignment_free/alignment_free_base.h @@ -0,0 +1,340 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Jonathan Goeke +// ========================================================================== +// Definition of all AFScore and the specialisations, D2, D2star, D2z +// and N2. +// ========================================================================== + +// TODO(holtgrew): Make struct a class here. + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_ALIGNMENT_FREE_BASE_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_ALIGNMENT_FREE_BASE_H_ + +namespace seqan { + +/*! + * @class AFScore + * @headerfile + * @brief Used to specify parameters and methods for alignment-free sequence comparison. + * + * @signature template + * struct AFScore; + * + * @tparam TSpec Tag for specialization. + * + * @see alignmentFreeComparison + */ + +template +struct AFScore; + +/*! + * @class D2AFScore D2 AFScore + * @extends AFScore + * @headerfile + * + * @brief D2 computes the inner product of the kmer count vectors. + * + * @signature template <> + * struct AFScore; + * + * To be used for alignment free comparison. + * + * @section References + * + * Lippert RA, et al. Distributional regimes for the number of k-word matches between two random sequences. Proc. Natl + * Acad. Sci. USA 2002. + * + * @see alignmentFreeComparison + * + * @var unsigned D2AFScore::kmerSize; + * @brief Size of the kmers. + * + * @var bool D2AFScore::verbose; + * @brief true to enable verbose debug output. + * + * @fn D2AFScore::AFScore + * + * @brief Constructor + * + * @signature AFScore::AFScore(kmerSize, verbose); + * + * @param[in] verbose This option will report progress to standard output (boolunsigned). + * + * @see alignmentFreeComparison + */ + +struct D2_; // Inner product of k-mer counts, d2 score +typedef Tag const D2; + +template <> +struct AFScore +{ + unsigned kmerSize; + bool verbose; + AFScore(unsigned k, bool verbose_ = false) : kmerSize(k), verbose(verbose_) + {} +}; + +/*! + * @class D2StarAFScore D2Star AFSScore + * @extends AFScore + * @headerfile + * @brief D2Star computes the inner product of the standardised kmer count vectors. + * + * @signature template <> + * struct AFScore; + * + * D2Star can be used for alignment-free sequence comparison, this version calculates the background model on the + * concatenation of both sequences + * + * @section References + * + * Reinert, G.; Chew, D.; Sun, F., Waterman, M. S. Alignment-Free Sequence Comparison (I): Statistics and Power. J + * Comput Biol, 2009. + * + * @see alignmentFreeComparison + * + * @fn D2StarAFScore::AFScore + * @brief Constructor + * @signature AFScore::AFScore(kmerSize, bgModelOrder, verbose); + * + * @param[in] kmerSize Size of kmer, unsigned. + * @param[in] bgModelOrder Order of the background Markov model, unsigned. + * @param[in] verbose This option will report progress to standard output, bool. + * + * @var unsigned D2StarAFScore::kmerSize + * @brief Size of the kmers. + * + * @var CharString D2StarAFScore::outputFile + * @brief When specified, all kmerWeights will be written to this file, for every sequence, and for every sequence + * comparison. + * + * @var unsigned D2StarAFScore::bgModelOrder + * @brief Order of the background model. + */ + +struct D2Star_; // Reinert and Waterman, D2 with centralised and standardised counts +typedef Tag const D2Star; + +template <> +struct AFScore +{ + unsigned kmerSize; + unsigned bgModelOrder; + bool verbose; + + + AFScore(unsigned k, unsigned m, bool verbose_ = false) : + kmerSize(k), bgModelOrder(m), verbose(verbose_) + {} +}; + +/*! + * @class N2AFScore N2 AFScore + * @extends AFScore + * @headerfile + * @brief N2 computes the inner product of the standardised neighbourhood kmer count vectors. + * + * @signature template <> + * struct AFScore; + * + * N2 can be used for alignment-free sequence comparison. + * + * @section References + * + * Jonathan Goeke, Marcel H. Schulz, Julia Lasserre, and Martin Vingron. + Estimation of Pairwise Sequence Similarity of Mammalian Enhancers with Word Neighbourhood Counts. Bioinformatics + (2012). + * + * @fn N2AFScore::AFScore + * + * @brief Constructor + * + * @signature AFScore::AFScore(kmerSize, bgModelOrder, outputFile, verbose); + * @signature AFScore::AFScore(kmerSize, bgModelOrder, revCom, outputFile, verbose); + * @signature AFScore::AFScore(kmerSize, bgModelOrder, revCom, mismatches, mismatchWeight, outputFile, verbose); + * + * @param[in] kmerSize Size of kmer, unsigned. + * @param[in] bgModelOrder Order of the background Markov model, unsigned. + * @param[in] outputFile When specified, all normalised and standardised kmer neighbourhood counts will be written + * to this file for every sequence, @link CharString @endlink. + * @param[in] revCom Scoring of reverse complements words [''/'max'/'min'/'mean'/'both_strands'/], + * @link CharString @endlink. + * @param[in] verbose This option will report progress to standard output, bool, defaults to + * false. + * @param[in] mismatches Includes words with one mismatch into the word neighbourhood, unsigned, 0 or 1. + * @param[in] mismatchWeight Weight of word counts with one mismatch, double. + * + * @see alignmentFreeComparison + * + * @var unsigned N2AFScore::kmerSize; + * @brief Size of the kmers. + * + * @var double N2AFScore::mismatchWeight; + * @brief Weight for approximate word matches + * + * @var CharString N2AFScore::revCom; + * @brief Scoring of reverse complements words, @link CharString @endlink [''/'max'/'min'/'mean'/'both_strands'/]. + * + * @var CharString N2AFScore::outputFile; + * @brief When specified, all kmerWeights for every sequence will be written to this file. + * + * @var unsigned N2AFScore::bgModelOrder; + * @brief Order of the background model + * + * @var unsigned N2AFScore::mismatches; + * @brief Approximate word matches [0(exact)/1(one mismatch)] + * + * @var bool N2AFScore::verbose; + * @brief true to enable verbose debug output. + */ + +struct N2_; // Reinert and Waterman, D2 with centralised and standardised counts +typedef Tag const N2; + +template <> +struct AFScore +{ + unsigned kmerSize; + unsigned bgModelOrder; + String revCom; // Count reverse complement words? + // revCom="";"mean","max","both_strands" + unsigned mismatches; // Currently 0 or 1 + double mismatchWeight; // Weight of words in the mismatch neighbourhood + bool verbose; + bool norm; // Normalize score? Needed to provide a proper similarity measure + String outputFile; // Output of all kmer weights for every sequence into this file + + // Constructor for the simple case with only exact word counts (N2*) + AFScore(unsigned k, unsigned m, String kmerWeightsFile = "", bool verbose_ = false) + { + kmerSize = k; + bgModelOrder = m; + outputFile = kmerWeightsFile; + verbose = verbose_; + revCom = ""; + mismatches = 0; + mismatchWeight = 1.0; + norm = true; + + }; + + // Constructor for the case with exact word counts and reverse complement (N2rc) + AFScore(unsigned k, unsigned m, String revCom_, String kmerWeightsFile = "", bool verbose_ = false) + { + kmerSize = k; + bgModelOrder = m; + revCom = revCom_; + outputFile = kmerWeightsFile; + verbose = verbose_; + mismatches = 0; + mismatchWeight = 1.0; + norm = true; + }; + + // Constructor for the case with mismatch-neighbourhood word counts and reverse complement (N2mmrc) + AFScore(unsigned k, + unsigned m, + String revCom_, + unsigned mm, double mmw, + String kmerWeightsFile = "", + bool verbose_ = false) + { + kmerSize = k; + bgModelOrder = m; + revCom = revCom_; + mismatches = mm; + mismatchWeight = mmw; + outputFile = kmerWeightsFile; + verbose = verbose_; + norm = true; + }; +}; + +/*! + * @class D2zAFScore D2zAFScore + * @extends AFScore + * @headerfile + * @brief D2z computes a z-score of the inner product of kmer count vectors + * + * @signature template <> + * struct AFScore; + * + * D2z can be used for alignment-free sequence comparison. The algorithm differs from the original implementation by + * the way masked sequences are handled + * + * @section References + * + * Kantorovitz, M. R.; Robinson, G. E., Sinha, S. A statistical method for alignment-free comparison of regulatory + * sequences. Bioinformatics, 2007. + * + * @fn D2zAFScore::AFScore + * + * @brief Constructor + * + * @signature AFScore::AFScore(kmerSize, bgModelOrder[, verbose]); + * + * @param[in] kmerSize Size of kmer, unsigned. + * @param[in] bgModelOrder Order of the background Markov model, unsigned. + * @param[in] verbose This option will report progress to standard output; bool, defaults to + * false. + * + * @var unsigned D2zAFScore::bgModelOrder; + * @brief Order of the background model + * + * @var unsigned D2zAFScore::kmerSize; + * @brief Size of the kmers + * + * @var bool D2zAFScore::verbose; + * @brief true to enable verbose debug output. +] */ + +struct D2z_; // Inner product of k-mer counts, d2 score with z-score +typedef Tag const D2z; + +template <> +struct AFScore +{ + unsigned kmerSize; + unsigned bgModelOrder; + bool verbose; + AFScore(unsigned k, unsigned m, bool verbose_ = false) : + kmerSize(k), bgModelOrder(m), verbose(verbose_) + {} +}; + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_ALIGNMENT_FREE_BASE_H_ diff --git a/seqan/alignment_free/alignment_free_comparison.h b/seqan/alignment_free/alignment_free_comparison.h new file mode 100644 index 0000000..bf33fa0 --- /dev/null +++ b/seqan/alignment_free/alignment_free_comparison.h @@ -0,0 +1,106 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Jonathan Goeke +// ========================================================================== +// This file contains the function that calls alignment free sequence +// comparisons algorithms (see AFScore): +// alignmentFreeComparison() +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_ALIGNMENT_FREE_COMPARISON_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_ALIGNMENT_FREE_COMPARISON_H_ + +namespace seqan { + +/*! + * @fn alignmentFreeComparison + * @headerfile + * @brief Computes the pairwise similarity scores for a set of sequences. + * + * @signature void alignmentFreeComparison(scoreMatrix, sequenceSet, score); + * + * @param[out] scoreMatrix A two-dimensional @link Matrix @endlink, used to store all pairwise scores. + * @param[in] sequenceSet @link StringSet @endlink containing all sequences for which pairwise scores will be + * computed. + * @param[in] score The @link AFScore @endlink object to be used for computing the alignment. + * + * @section Examples + * + * Calculate the alignment free sequence similarity of two masked DNA sequences. + * + * @code{.cpp} + * using namespace seqan; + * StringSet sequences; + * Dna5String seq1 = + * "TAGGTTTTCCGAAAAGGTAGCAACTTTACGTGATCAAACCTCTGACGGGGTTTTCCCCGTCGAAATTGGGTG" + * "TTTCTTGTCTTGTTCTCACTTGGGGCATCTCCGTCAAGCCAAGAAAGTGCTCCCTGGATTCTGTTGCTAACG" + * "AGTCTCCTCTGCATTCCTGCTTGACTGATTGGGCGGACGGGGTGTCCACCTGACGCTGAGTATCGCCGTCAC" + * "GGTGCCACATGTCTTATCTATTCAGGGATCAGAATTTATTCAGGAAATCAGGAGATGCTACACTTGGGTTAT" + * "CGAAGCTCCTTCCAAGGCGTAGCAAGGGCGACTGAGCGCGTAAGCTCTAGATCTCCTCGTGTTGCAACTACA" + * "CGCGCGGGTCACTCGAAACACATAGTATGAACTTAACGACTGCTCGTACTGAACAATGCTGAGGCAGAAGAT" + * "CGCAGACCAGGCATCCCACTGCTTGAAAAAACTATNNNNCTACCCGCCTTTTTATTATCTCATCAGATCAAG"; + * Dna5String seq2 = + * "ACCGACGATTAGCTTTGTCCGAGTTACAACGGTTCAATAATACAAAGGATGGCATAAACCCATTTGTGTGAA" + * "AGTGCCCATCACATTATGATTCTGTCTACTATGGTTAATTCCCAATATACTCTCGAAAAGAGGGTATGCTCC" + * "CACGGCCATTTACGTCACTAAAAGATAAGATTGCTCAAANNNNNNNNNACTGCCAACTTGCTGGTAGCTTCA" + * "GGGGTTGTCCACAGCGGGGGGTCGTATGCCTTTGTGGTATACCTTACTAGCCGCGCCATGGTGCCTAAGAAT" + * "GAAGTAAAACAATTGATGTGAGACTCGACAGCCAGGCTTCGCGCTAAGGACGCAAAGAAATTCCCTACATCA" + * "GACGGCCGCGNNNAACGATGCTATCGGTTAGGACATTGTGCCCTAGTATGTACATGCCTAATACAATTGGAT" + * "CAAACGTTATTCCCACACACGGGTAGAAGAACNNNNATTACCCGTAGGCACTCCCCGATTCAAGTAGCCGCG"; + * + * clear(sequences); + * appendValue(sequences, seq1); + * appendValue(sequences, seq2); + * + * Matrix myMatrix; + * + * unsigned kmerSize = 5; + * unsigned bgModelOrder = 1; + * String revCom = "both_strands"; + * unsigned mismatches = 1; + * double mismatchWeight = 0.5; + * AFScore myScoreN2(kmerSize, bgModelOrder, revCom, mismatches, mismatchWeight); + * + * alignmentFreeComparison(myMatrix, sequences, myScoreN2); + * std::cout << myMatrix; + * @endcode + */ + +template +void alignmentFreeComparison(Matrix & scoreMatrix, TStringSet const & sequenceSet, TComparisonMethod const & comparisonMethod) +{ + _alignmentFreeComparison(scoreMatrix, sequenceSet, comparisonMethod); +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_COMPARISON_H_ diff --git a/seqan/alignment_free/kmer_functions.h b/seqan/alignment_free/kmer_functions.h new file mode 100644 index 0000000..118c7d8 --- /dev/null +++ b/seqan/alignment_free/kmer_functions.h @@ -0,0 +1,965 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Jonathan Goeke +// ========================================================================== +// This file contains helper functions to count words in sequences and to +// calculate probabilities and variances of word occurrences. +// ========================================================================== + +// TODO (goeke) const could be added below for the input variables but the function value() in matrix_base (align) is not defined for const. Similarly, the function emittedProbabilty is not defined for const in statistics_markov_model.h + +#ifndef SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_KMER_FUNCTIONS_H_ +#define SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_KMER_FUNCTIONS_H_ + +namespace seqan { + +template +struct UnmaskedAlphabet_ +{ + typedef TAlphabet Type; +}; + +template <> +struct UnmaskedAlphabet_ +{ + typedef Dna Type; +}; + +template +struct UnmaskedAlphabet_ +{ + typedef const typename UnmaskedAlphabet_::Type Type; +}; + +/*! + * @fn countKmers + * @headerfile + * @brief Counts kmers in a sequence. Optionally, a background model is returned. + * + * @signature void countKmers(kmerCounts, sequence, k); + * @signature void countKmers(kmerCounts, bgFrequencies, sequence, k); + * @signature void countKmers(kmerCounts, bgModel, sequence, k); + * + * @param[out] kmerCounts @link String @endlink of unsigned with kmer counts for every k-mer. + * @param[out] bgFrequencies @link String @endlink of background frequencies (double) representing the model. + * @param[out] bgModel @link MarkovModel @endlink to use. + * @param[in] sequence @link String @endlink (sequence) where k-mers are counted. + * @param[in] k k-mer length (unsigned). + * + * k-mers overlapping masked (aka 'N') letters are not counted in case of Dna5Strings. A Bernoulli or Markov Model + * can be choosen as a background model. + * + * @section Examples + * + * Calculate the alignment free sequence similarity o two masked DNA sequences. + * + * @code{.cpp} + * using namespace seqan; + * // Masked sequence, we do not want to count words overlapping 'N' + * Dna5String sequenceDna5 = + * "TAGGTTTTCCGAAAAGGTAGCAACTTTACGTGATCAAACCTCTGACGGGGTTTTCCCCGTCGAAATTGGGTG" + * "TTTCTTGTCTTGTTCTCACTTGGGGCATCTCCGTCAAGCCAAGAAAGTGCTCCCTGGATTCTGTTGCTAACG" + * "AGTCTCCTCTGCATTCCTGCTTGACTGATTGGGCGGACGGGGTGTCCACCTGACGCTGAGTATCGCCGTCAC" + * "GGTGCCACATGTCTTATCTATTCAGGGATCAGAATTTATTCAGGAAATCAGGAGATGCTACACTTGGGTTAT" + * "CGAAGCTCCTTCCAAGGCGTAGCAAGGGCGACTGAGCGCGTAAGCTCTAGATCTCCTCGTGTTGCAACTACA" + * "CGCGCGGGTCACTCGAAACACATAGTATGAACTTAACGACTGCTCGTACTGAACAATGCTGAGGCAGAAGAT" + * "CGCAGACCAGGCATCCCACTGCTTGAAAAAACTATNNNNCTACCCGCCTTTTTATTATCTCATCAGATCAAG"; + * + * String kmerCounts; + * unsigned k = 2; // Count all 2-mers + * countKmers(kmerCounts, sequenceDna5, k); + * + * for(unsigned i = 0; i<16; ++i) // Print the 2-mer counts + * std::cout< nucleotideFrequencies; // Defines a Bernoulli model for DNA sequences. + * // Count all 2-mers and save the nucleotide frequencies + * countKmers(kmerCounts, nucleotideFrequencies, sequenceDna5, k); + * + * for(unsigned i = 0; i<4; ++i) // Print the nucleotide frequencies + * std::cout << nucleotideFrequencies[i] << "\n"; + * // => p(A) = 0.238; p(C) = 0.254; p(G) = 0.238; p(T) = 0.27; + * + * MarkovModel backgroundModel(1); // Markov model of order 1 + * // Count all 2-mers and return a Markov model + * countKmers(kmerCounts, backgroundModel, sequenceDna5, k); + * std::cout< +void countKmers(String & kmerCounts, TString const & sequence, unsigned const k) +{ + typedef typename Value::Type TAlphabet; + typedef typename UnmaskedAlphabet_::Type TUnmaskedAlphabet; + typedef typename Iterator::Type TIterator; + typedef typename Position::Type TPosition; + typedef Shape TShape; + // Declare variables + TShape myShape; // Shape, length can be changed (kmer_length) + resize(myShape, k); + // Calculate the number of kmers, length of count vector + int kmerNumber = _intPow((unsigned)ValueSize::VALUE, weight(myShape)); + clear(kmerCounts); + resize(kmerCounts, kmerNumber, 0); + TIterator itSequence = begin(sequence); + int counterN = 0; + + // Check for any N that destroys the first kmers + unsigned j = k - 1; + for (TPosition i = position(itSequence); i <= j; ++i) + { + if (_repeatMaskValue(sequence[i])) + { + counterN = i + 1; + } + } + for (; itSequence <= (end(sequence) - k); ++itSequence) + { + // Check if there is a "N" at the end of the new kmer + if (_repeatMaskValue(value(itSequence + (k - 1)))) + counterN = k; // Do not consider any kmer covering this "N" + + // If there is no "N" overlapping with the current kmer, count it + if (counterN <= 0) + { + unsigned hashValue = hash(myShape, itSequence); + ++kmerCounts[hashValue]; + } + counterN--; + } +} + +/* + * Function to count kmers and background nucleotide frequencies, Ns are not considered + * (for zero order background model) + */ +template +void countKmers(String & kmerCounts, String & backgroundFrequencies, TString const & sequence, unsigned const k) +{ + typedef typename Value::Type TAlphabet; + typedef typename UnmaskedAlphabet_::Type TUnmaskedAlphabet; + typedef typename Iterator::Type TIterator; + typedef typename Iterator >::Type TIteratorTStringBG; + typedef typename Position::Type TPosition; + typedef Shape TShape; + unsigned alphabetSize = ValueSize::VALUE; + + // Declare variables + TShape myShape; // Shape, length can be changed (kmer_length) + TShape myShapeBG; // Shape for background, set to markovlen+1, here zero order only + resize(myShape, k); + resize(myShapeBG, 1); // Markov model of zero order (count background frequencies) + + // Calculate number of kmers/ length of count vector, respectively background vector + unsigned kmerNumber = _intPow(alphabetSize, k); + unsigned kmerNumberBG = alphabetSize; // Zero order model for DNA sequences (Bernoulli model) + clear(kmerCounts); + resize(kmerCounts, kmerNumber, 0); + resize(backgroundFrequencies, kmerNumberBG, (TValueBG) 0); + TIterator itSequence = begin(sequence); + + int counterN = 0; // Counter that counts how many kmers are effected by a N + int counterNbg = 0; // Counter for background model (different shape size) + + // Check for any N that destroys the first kmers + unsigned j = k - 1; + for (TPosition i = position(itSequence); i <= j; ++i) + { + if (_repeatMaskValue(sequence[i])) + counterN = i + 1; + } + + int sumBG = 0; // Count the number of nucleotides for the nucleotide frequency calculation (Ns are not considered anymore). + for (; itSequence <= (end(sequence) - k); ++itSequence) + { + // Check if there is a "N" at the end of the new kmer + if (_repeatMaskValue(value(itSequence + (k - 1)))) + { + counterN = k; // Do not consider any kmer covering this "N" + } + // If there is no "N" overlapping with the current kmer, count it. + if (counterN <= 0) + { + unsigned hashValue = hash(myShape, itSequence); + ++kmerCounts[hashValue]; + } + // Check if there is a "N" at the end of the new background word, here single letters only. + if (_repeatMaskValue(value(itSequence))) + { + counterNbg = 1; + } + if (counterNbg <= 0) + { + unsigned hashValueBG = hash(myShapeBG, itSequence); + backgroundFrequencies[hashValueBG] += 1.0; + ++sumBG; + } + counterN--; + counterNbg--; + } + // The background counts are updated until the last base is covered. + for (; itSequence < end(sequence); ++itSequence) + { + if (_repeatMaskValue(value(itSequence))) + { + counterNbg = 1; + } + if (counterNbg <= 0) + { + unsigned hashValueBG = hash(myShapeBG, itSequence); + ++backgroundFrequencies[hashValueBG]; + ++sumBG; + } + counterNbg--; + } + // Normalise the background counts to obtain the nucleotide frequencies (Bernoulli model of DNA sequences). + TIteratorTStringBG itBackground = begin(backgroundFrequencies); + for (; itBackground < end(backgroundFrequencies); ++itBackground) + if (sumBG != 0) + value(itBackground) /= ((TValueBG) sumBG); +} + +/* + * Function to count kmers and build a background markov model with masked sequences + */ +template +void countKmers(String & kmerCounts, MarkovModel & backgroundModel, TString const & sequence, unsigned k) +{ + //typedef typename Value::Type TAlphabet; + //typedef typename UnmaskedAlphabet_::Type TUnmaskedAlphabet; + typedef typename Iterator::Type TIterator; + //typedef typename Iterator, Rooted>::Type TIteratorInt; + typedef typename Position::Type TPosition; + typedef Shape TShape; + + // Declare variables + TShape myShape; // Shape, length can be changed (kmer_length) + resize(myShape, k); + // Only consider kmers without N + int kmerNumber = _intPow((unsigned)ValueSize::VALUE, weight(myShape)); + clear(kmerCounts); + resize(kmerCounts, kmerNumber, 0); + + // Create sequence set for the markov model, if Ns occur, the sequence is split and Ns are removed + StringSet > seqSetMM; + + TIterator itSeq = begin(sequence); + + // Check for any N that destroys the first kmers + unsigned j = (k - 1); + for (TPosition i = position(itSeq); i <= j; ++i) + { + if (_repeatMaskValue(sequence[i])) + { + if ((i - position(itSeq)) > 0) + { + appendValue(seqSetMM, infix(sequence, position(itSeq), i)); + } + goFurther(itSeq, i + 1 - position(itSeq)); + j = i + k - 1; + } + } + + int counterN = 0; + TPosition startSplitSequence = position(itSeq); // The position of possible start of a sequence after NNs is stored to split sequences. + + for (; itSeq <= (end(sequence) - k); ++itSeq) + { + if (_repeatMaskValue(value(itSeq + (k - 1)))) + { + counterN = k; + + if (((position(itSeq) + k - 1) > startSplitSequence)) + appendValue(seqSetMM, infix(sequence, startSplitSequence, (position(itSeq) + k - 1))); + + startSplitSequence = (position(itSeq) + k); // Position after N, possible start + } + if (counterN <= 0) + { + unsigned hashValue = hash(myShape, itSeq); + ++kmerCounts[hashValue]; + } + + counterN--; + } + // Create a stringSet, needed to create the Markov model + if ((position(itSeq) + k - 1) > startSplitSequence) + { + appendValue(seqSetMM, infix(sequence, startSplitSequence, (position(itSeq) + k - 1))); + } + // Build background Markov model + buildMarkovModel(backgroundModel, seqSetMM); +} + +/*! + * @fn calculateProbability + * @headerfile + * @brief Calculates the probability of a sequence given a Bernoulli model. + * + * @signature void calculateProbability(probability, sequence, bgFrequencies); + * + * @param[out] probability Probability (double) of the sequence given the model. + * @param[in] sequence @link String @endlink, usually of Dna characters. + * @param[in] bgFrequencies @link String @endlink of background frequencies (double) representing the model. + * + * @section Examples + * + * Calculate the probability for the word CCCAAGTTT with p(A) = p(T) = 0.3 and p(C) = p(G) = 0.2. + * + * @code{.cpp} + * using namespace seqan; + * double p = 0.0; + * DnaString word = "CCCAAGTTT"; + * String model; + * resize(model, 4); + * model[0] = 0.3; // p(A) + * model[1] = 0.2; // p(C) + * model[2] = 0.2; // p(G) + * model[3] = 0.3; // p(T) + * calculateProbability(p, word, model); // p = 3.888e-06 + * @endcode + * + * @see calculateVariance + * @see alignmentFreeComparison + * @see calculateCovariance + * @see countKmers + */ + +template +void calculateProbability(TValue & probability, TString const & sequence, TStringBG const & backgroundFrequencies) +{ + typedef typename Iterator::Type TIteratorTString; + + TIteratorTString itSequence = begin(sequence); + probability = (TValue) 1; + for (; itSequence < end(sequence); ++itSequence) + probability *= backgroundFrequencies[ordValue(*itSequence)]; +} + +/*! + * @fn calculateVariance + * @headerfile + * @brief Calculates the variance for the number of word occurrences of a word in a sequence of length n given a + * background model. + * + * @signature void calculateVariance(variance, word, bgFrequencies, n); + * @signature void calculateVariance(variance, word, bgModel, n); + * + * @param[out] variance Variance of the number of occurrences of the word in a sequence of length n given the + * model; double. + * @param[in] word @link String @endlink, usually of Dna to compute variance for. + * @param[in] bgFrequencies @link String @endlink of bg frequencies representing the model. + * @param[in] bgModel @link MarkovModel @endlink to use. + * @param[in] n Length of the sequence where the occurrences of word are counted, int. + * + * Calculates the variance for the number of word occurrences of a word in a sequence of length n given a background + * model (Markov model or Bernoulli model). The formula is obtained from (Robin et al., 2005). + * + * @section References + * + * Robin, S., Rodolphe, F., and Schbath, S. (2005). DNA, Words and Models. Cambridge University Press. See Jonathan + * Goeke et al (to appear) for details on the implementation. + * + * @section Examples + * + * Calculate the variance for the number of occurrences of CAAGTC in a sequence of length 10000bp with + * p(A) = p(T) = 0.3 and p(C) = p(G) = 0.2. + * + * @code{.cpp} + * using namespace seqan; + * double var = 0.0; + * int n = 10000; + * DnaString word = "CAAGTC"; + * String model; + * resize(model, 4); + * model[0] = 0.3; // p(A) + * model[1] = 0.2; // p(C) + * model[2] = 0.2; // p(G) + * model[3] = 0.3; // p(T) + * calculateVariance(var, word, model, n); // var = 2.16 + * @endcode + * + * Estimate a Markov model on a set of sequences and calculate the variance for the number of occurrences of the word + * CAAGTC in a sequence of length 10000bp. + * + * @code{.cpp} + * using namespace seqan; + * double var = 0.0; + * int n = 10000; + * DnaString word = "CAAGTC"; + * StringSet sequences; + * appendValue(sequences, "CAGAAAAAAACACTGATTAACAGGAATAAGCAGTTTACTTATTTTGGGCCTGGGACCCGTGTCTCTAATTTAATTAGGTGATCCCTGCGAAGTTTCTCCA"); + * MarkovModel model(0); // Bernoulli model + * model.build(sequences); + * calculateVariance(var, word, model, n); // var = 2.16 + * MarkovModel model1(1); // First order Markov model + * model1.build(sequences); + * calculateVariance(var, word, model1, n); // var = 1.69716 + * @endcode + * + * @see calculateProbability + * @see calculateCovariance + * @see MarkovModel + * @see alignmentFreeComparison + * @see calculatePeriodicity + * @see countKmers + * @see calculateOverlapIndicator + */ + +template +void calculateVariance(TValue & variance, TString const & word, TStringBG const & backgroundFrequencies, int const n) +{ + typedef typename Value::Type TAlphabet; + typedef typename Value::Type TValueBG; + typedef typename Iterator, Rooted>::Type TIteratorInt; + + int l = length(word); + TValueBG p_w; + calculateProbability(p_w, word, backgroundFrequencies); + + String periodicity; + calculatePeriodicity(periodicity, word, word); + variance = (TValue) (n - l + 1) * p_w; + for (TIteratorInt i = begin(periodicity); i < end(periodicity); ++i) + { + TValueBG p_clump; + TValueBG p_tmp; + calculateProbability(p_tmp, word, backgroundFrequencies); + String wordPrefix = prefix(word, value(i)); + calculateProbability(p_clump, wordPrefix, backgroundFrequencies); + p_clump *= p_tmp; + variance += (TValue) 2 * (n - l + 1 - value(i)) * p_clump; + } + variance += (TValue) p_w * p_w * (n - 2 * n * l + 3 * l * l - 4 * l + 1); +} + + +template +void calculateVariance(TValue & variance, String const & word, MarkovModel /*const*/ & bgModel, int const n) +{ + typedef typename Iterator, Rooted>::Type TIteratorInt; + + int l = length(word); + TValue p_w; + p_w = emittedProbability(bgModel, word); + String periodicity; + calculatePeriodicity(periodicity, word, word); + variance = (TValue) (n - l + 1) * p_w; + for (TIteratorInt i = begin(periodicity); i < end(periodicity); ++i) + { + TValue p_clump; + String clump = prefix(word, value(i)); + append(clump, word); + p_clump = emittedProbability(bgModel, clump); + variance += (TValue) 2 * (n - l + 1 - value(i)) * p_clump; + } + variance += (TValue) p_w * p_w * (n - 2 * n * l + 3 * l * l - 4 * l + 1); +} + +/*! + * @fn calculateCovariance + * @headerfile + * @brief Calculates the covariance for the number of word occurrences for two words in a sequence of length n, given a + * background model. + * + * @signature void calculateCovariance(covariance, word1, word2, bgFrequencies, n); + * @signature void calculateCovariance(covariance, word1, word2, bgModel, n); + * + * @param[out] covariance Variance of the number of occurrences of the word in a sequence of length n given the + * model, double. + * @param[in] word1 @link String @endlink, usually of Dna. + * @param[in] word2 @link String @endlink, usually of Dna. + * @param[in] bgFrequencies @link String @endlink of double with the background frequencies representing + * @param[in] bgModel @link MarkovModel @endlink to use. + * @param[in] n Length of the sequence where the occurrences of word are counted, int. + * + * Calculates the covariance for the number of word occurrences for two words in a sequence of length n given a + * background model (Markov model or Bernoulli model). The covariance is influenced by the property of words to overlap, + * for example, the words ATAT and TATA have a high covariance since they are likely to overlap. The formula is based on + * (Robin et al., 2005). + * + * @section References + * + * Robin, S., Rodolphe, F., and Schbath, S. (2005). DNA, Words and Models. Cambridge University Press. See Jonathan + * Goeke et al (to appear) for details on the implementation. + * + * @section Examples + * + * Calculate the covariance for the number of occurrences of ATATAT and TATATA in a sequence of length 10000bp with + * p(A) = p(T) = 0.3 and p(C) = p(G) = 0.2. + * + * @code{.cpp} + * using namespace seqan; + * double covar = 0.0; + * int n = 10000; + * DnaString word1 = "ATATAT"; + * DnaString word2 = "TATATA"; + * String model; + * resize(model, 4); + * model[0] = 0.3; // p(A) + * model[1] = 0.2; // p(C) + * model[2] = 0.2; // p(G) + * model[3] = 0.3; // p(T) + * calculateCovariance(covar, word1, word2, model, n); // covar = 4.74 + * @endcode + * + * Estimate a Markov model on a set of sequences and calculate the covariance for the number of occurrences of ATATAT + * and TATATA in a sequence of length 10000bp. + * + * @code{.cpp} + * using namespace seqan; + * double covar = 0.0; + * int n = 10000; + * DnaString word1 = "ATATAT"; + * DnaString word2 = "TATATA"; + * StringSet sequences; + * appendValue(sequences, "CAGCACTGATTAACAGGAATAAGCAGTTTACTTCTGTCAGAATATTGGGCATATATA" + * "CTGGGACCCGTGTAATACTCTAATTTAATTAGGTGATCCCTGCGAAGTCTCCA"); + * MarkovModel modelMM0(0); // Bernoulli model + * modelMM0.build(sequences); + * calculateCovariance(covar, word1, word2, modelMM0, n); // covar = 4.74 + * MarkovModel modelMM1(1); // First order Markov model + * modelMM1.build(sequences); + * calculateCovariance(covar, word1, word2, modelMM1, n); // covar = 13.1541 + * @endcode + * + * @see calculateProbability + * @see calculateVariance + * @see MarkovModel + * @see alignmentFreeComparison + * @see calculatePeriodicity + * @see countKmers + * @see calculateOverlapIndicator + */ + +template +void calculateCovariance(TValue & covariance, TString const & word1, TString const & word2, TStringBG const & backgroundFrequencies, int const n) +{ + if (word1 == word2) + { + calculateVariance(covariance, word1, backgroundFrequencies, n); + return; + } + typedef typename Value::Type TAlphabet; + typedef typename Value::Type TValueBG; + typedef typename Iterator, Rooted>::Type TIteratorInt; + + covariance = 0; + int l1 = length(word1); + TValueBG p_w1; + calculateProbability(p_w1, word1, backgroundFrequencies); + String periodicity1; + calculatePeriodicity(periodicity1, word1, word2); + for (TIteratorInt i = begin(periodicity1); i < end(periodicity1); ++i) + { + TValueBG p_clump; + TValueBG p_tmp; + calculateProbability(p_tmp, word2, backgroundFrequencies); + String wordPrefix = prefix(word1, value(i)); + calculateProbability(p_clump, wordPrefix, backgroundFrequencies); + p_clump *= p_tmp; + covariance += (TValue) (n - l1 + 1 - value(i)) * p_clump; + } + + int l2 = length(word2); + TValueBG p_w2; + calculateProbability(p_w2, word2, backgroundFrequencies); + String periodicity2; + calculatePeriodicity(periodicity2, word2, word1); + for (TIteratorInt i = begin(periodicity2); i < end(periodicity2); ++i) + { + TValueBG p_clump; + TValueBG p_tmp; + calculateProbability(p_tmp, word1, backgroundFrequencies); + String wordPrefix = prefix(word2, value(i)); + calculateProbability(p_clump, wordPrefix, backgroundFrequencies); + p_clump *= p_tmp; + covariance += (TValue) (n - l2 + 1 - value(i)) * p_clump; + } + covariance += (TValue) p_w1 * p_w2 * (n - 2 * n * l1 + 3 * l1 * l1 - 4 * l1 + 1); +} + +template +void calculateCovariance(TValue & covariance, String const & word1, String const & word2, MarkovModel /*const*/ & bgModel, int const n) +{ + if (word1 == word2) + { + calculateVariance(covariance, word1, bgModel, n); + return; + } + typedef typename Iterator, Rooted>::Type TIteratorInt; + + covariance = 0; + int l1 = length(word1); + TValue p_w1; + p_w1 = emittedProbability(bgModel, word1); + String periodicity1; + calculatePeriodicity(periodicity1, word1, word2); // word2 is right + for (TIteratorInt i = begin(periodicity1); i < end(periodicity1); ++i) + { + TValue p_clump; + String clump = prefix(word1, value(i)); + append(clump, word2); + + p_clump = emittedProbability(bgModel, clump); + + covariance += (TValue) (n - l1 + 1 - value(i)) * p_clump; + } + TValue p_w2; + p_w2 = emittedProbability(bgModel, word2); + String periodicity2; + calculatePeriodicity(periodicity2, word2, word1); + for (TIteratorInt i = begin(periodicity2); i < end(periodicity2); ++i) + { + TValue p_clump; + String clump = prefix(word2, value(i)); + append(clump, word1); + + p_clump = emittedProbability(bgModel, clump); + + covariance += (TValue) (n - l1 + 1 - value(i)) * p_clump; + } + covariance += (TValue) p_w1 * p_w2 * (n - 2 * n * l1 + 3 * l1 * l1 - 4 * l1 + 1); +} + +/*! + * @fn calculatePeriodicity + * @headerfile + * @brief Calculate word periodicity (indicator for overlaps) + * + * @signature void calculatePeriodicity(periodicity, word1, word2); + * + * @param[out] periodicity String of int values giving the periodicity (overlap indicator) of + * word1 and word2. + * @param[int] word1 String, usually of Dna characters. + * @param[int] word2 String, usually of Dna characters. + * + * Calculate word periodicity (indicator for overlaps) for two words. + * + * @section Examples + * + * Calculate the periodicity of two words (At which positions can they overlap?) + * + * @code{.cpp} + * using namespace seqan; + * DnaString word1 = "ATATA"; + * DnaString word2 = "TATAT"; + * String periodicity; + * calculatePeriodicity(periodicity, word1, word2); + * for(unsigned i = 0; i < length(periodicity); ++i) // Print the periodicity + * std::cout << periodicity[i] << "\t"; + * + * // periodocity[0] = 1: + * // i = 01234 + * // word1 = ATATA + * // word2 = -TATAT + * + * // periodocity[1] = 3: + * // i = 01234 + * // word1 = ATATA + * // word2 = ---TATAT + * @endcode + * + * @see calculateVariance + * @see calculateCovariance + * @see calculateOverlapIndicator + * @see alignmentFreeComparison + */ + +template +void calculatePeriodicity(String & periodicity, TString const & word1, TString const & word2) +{ + typedef typename Value::Type TAlphabet; + //typedef typename Iterator::Type TIterator; + typedef typename Size::Type TSize; + + TSize length1 = length(word1); + TSize length2 = length(word2); + for (TSize i = 1; i < length1; ++i) + { + String my_suffix = suffix(word1, i); // Overlap of suffix of word1 with prefix of word2 + TSize my_min = std::min(length2, (length1 - i)); + String my_prefix = prefix(word2, my_min); + if (my_suffix == my_prefix) + { + appendValue(periodicity, i); + } + } +} + +/*! + * @fn calculateOverlapIndicator + * @headerfile + * @brief Calculate word overlaps: epsilon(word1, word2) = 1 where word2[j] = word1[j+p] for + * all j = 1..(k-p). + * + * @signature void calculateOverlapIndicator(epsilon, word1, word2); + * + * @param[out] epsilon String of int giving the periodicity (overlap indicator) of word1 and word2. + * @param[in] word1 String (for example a DNA sequence). + * @param[in] word2 String (for example a DNA sequence). + * + * Calculate the indicator for overlaps of two words. The formula is based on (Robin et al., 2005) + * + * @section References + * + * Robin, S., Rodolphe, F., and Schbath, S. (2005). DNA, Words and Models. Cambridge University Press. See Jonathan + * Goeke et al (to appear) for details on the implementation. + * + * @section Examples + * + * Calculate the overlap indicator (epsilon) for two words + * + * @code{.cpp} + * using namespace seqan; + * DnaString word1 = "ATATA"; + * DnaString word2 = "TATAT"; + * String epsilon; + * calculateOverlapIndicator(epsilon, word1, word2); + * for(unsigned i = 0; i < length(epsilon); ++i) + * std::cout << epsilon[i] << "\t"; + * // epsilon = 01010: + * // word1 ATATA + * // word2 overlap 1: -TATAT + * // word2 overlap 2: ---TATAT + * @endcode + * + * @see calculateVariance + * @see calculateCovariance + * @see calculatePeriodicity + * @see alignmentFreeComparison + */ + +template +void calculateOverlapIndicator(String & epsilon, TString const & word1, TString const & word2) +{ + typedef typename Value::Type TAlphabet; + //typedef typename Iterator::Type TIterator; + typedef typename Size::Type TSize; + + TSize length1 = length(word1); + TSize length2 = length(word2); + clear(epsilon); + resize(epsilon, length1, 0); + for (TSize i = 0; i < length1; ++i) + { + String my_suffix = suffix(word1, length1 - i - 1); // Overlap of suffix of word1 with prefix of word2 + TSize my_min = std::min(length2, i + 1); + String my_prefix = prefix(word2, my_min); + if (my_suffix == my_prefix) + epsilon[i] = 1; + } +} + +/*! + * @fn stringToStringSet + * @headerfile + * @brief Transform a String into a StringSet containing this String. + * + * @signature void stringToStringSet(stringSet, string); + * @signature void stringToStringSet(dnaStringSet, dna5String); + * + * @param[out] stringSet @link StringSet @endlink to create with one sequence. + * @param[in] string @link String @endlink to create the string set of. + * @param[out] dnaStringSet @link StringSet @endlink of @link String Strings @endlink over the alphabet @link Dna @endlink. + * @param[in] dna5String @link String @endlink over the alphabet @link Dna5 @endlink to convert. + * + * @note The second variant removes all N characters from the @link Dna5String @endlink. + * + * @section Examples + * + * Transform a masked DNA sequence into a set of sequences with all masked parts removed. + * + * @code{.cpp} + * using namespace seqan; + * Dna5String sequenceDna5 = + * "NNNNNNTTTCCGAAAAGGTANNNNNGCAACTTTANNNCGTGATCAAAGTTTTCCCCGTCGAAATTGGGNNTG"; + * StringSet sequencesDna; + * stringToStringSet(sequencesDna, sequenceDna5); + * // Print the masked sequence + * std::cout< +void +stringToStringSet(StringSet & stringSet, TString const & sequence) +{ + resize(stringSet, 1); + stringSet[0] = sequence; +} + +inline void +stringToStringSet(StringSet > & dnaStringSet, String const & sequence) +{ + typedef Iterator const, Rooted>::Type TIterator; + typedef Position::Type TPosition; + + TIterator itSeq = begin(sequence); + // Check for any N that destroys the first kmers + unsigned j = 0; + for (TPosition i = position(itSeq); i <= j; ++i) + { + if (sequence[i] == 'N') + { + if ((i - position(itSeq)) > 0) + appendValue(dnaStringSet, infix(sequence, position(itSeq), i)); + goFurther(itSeq, i + 1 - position(itSeq)); + j = i; + } + } + int counterN = 0; + TPosition startSplitSequence = position(itSeq); // The position of possible starts of a sequence after Ns is stored to split the sequence. + for (; itSeq <= (end(sequence) - 1); ++itSeq) + { + if (value(itSeq) == 'N') + { + counterN = 1; + if (((position(itSeq)) > startSplitSequence)) + { + appendValue(dnaStringSet, infix(sequence, startSplitSequence, position(itSeq))); + } + startSplitSequence = (position(itSeq) + 1); // Position after N, possible start + } + counterN--; + } + // Create the stringSet, the stringSet can be used to create a Markov model + if (position(itSeq) > startSplitSequence) + appendValue(dnaStringSet, infix(sequence, startSplitSequence, position(itSeq))); +} + +/*! + * @fn cutNs + * @headerfile + * @brief Cut out all masked sequences from a Dna5String. + * + * @signature void cutNs(sequenceCut, sequence); + * + * @param[out] sequenceCut Dna5String similar to sequence with all Ns cut out. + * @param[in] sequence Masked DNA sequence. + * + * This function concatenates the nonmasked parts of the sequence, thereby changing the word content. If you want to + * remove the masked parts of a sequence without concatenation, use stringToStringSet. + * + * @section Examples + * + * Transform a masked DNA sequence into an unmasked sequences with all masked parts cut out + * + * @code{.cpp} + * using namespace seqan; + * Dna5String sequenceMasked = + * "NNNNNNTTTCCGAAAAGGTANNNNNGCAACTTTANNNCGTGATCAAAGTTTTCCCCGTCGAAATTGGGNNTG"; + * Dna5String sequenceMaskedPartsRemoved; + * cutNs(sequenceMaskedPartsRemoved, sequenceMasked); + * // Print the masked sequence + * std::cout< & sequenceCut, String const & sequence) +{ + typedef Iterator const, Rooted>::Type TIterator; + typedef Position::Type TPosition; + + sequenceCut = ""; + TIterator itSeq = begin(sequence); + + // Check for any N that destroys the first kmers + unsigned j = 0; + for (TPosition i = position(itSeq); i <= j; ++i) + { + if (sequence[i] == 'N') + { + if ((i - position(itSeq)) > 0) + sequenceCut += infix(sequence, position(itSeq), i); + goFurther(itSeq, i + 1 - position(itSeq)); + j = i; + } + } + int counterN = 0; + TPosition startSplitSequence = position(itSeq); // The position of possible starts of a sequence after Ns is stored to split the sequence. + for (; itSeq <= (end(sequence) - 1); ++itSeq) + { + if (value(itSeq) == 'N') + { + counterN = 1; + if (((position(itSeq)) > startSplitSequence)) + sequenceCut += infix(sequence, startSplitSequence, position(itSeq)); + startSplitSequence = (position(itSeq) + 1); // Position after N, possible start + } + counterN--; + } + // Create the sequence with any N cut out. + if (position(itSeq) > startSplitSequence) + { + sequenceCut += infix(sequence, startSplitSequence, position(itSeq)); + } +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ALIGNMENT_FREE_KMER_FUNCTIONS_H_ diff --git a/seqan/arg_parse.h b/seqan/arg_parse.h new file mode 100644 index 0000000..06b2d8d --- /dev/null +++ b/seqan/arg_parse.h @@ -0,0 +1,79 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== +// Facade header for module arg_parse. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_H_ +#define SEQAN_INCLUDE_SEQAN_ARG_PARSE_H_ + +// =========================================================================== +// Prerequisites. +// =========================================================================== + +#include +//#include +#include +#include + +#include +#include +#ifndef STDLIB_VS +#include +#endif + +#include +#include +#include + +// =========================================================================== +// The ArgParse Headers. +// =========================================================================== + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +#endif // SEQAN_INCLUDE_SEQAN_ARG_PARSE_H_ diff --git a/seqan/arg_parse/arg_parse_argument.h b/seqan/arg_parse/arg_parse_argument.h new file mode 100644 index 0000000..95ebf88 --- /dev/null +++ b/seqan/arg_parse/arg_parse_argument.h @@ -0,0 +1,1164 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_ARGUMENT_H_ +#define SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_ARGUMENT_H_ + +#include +#include + +#include +#include +#include + +namespace seqan { + +// ========================================================================== +// Forwards +// ========================================================================== + +// Required for _checkStringRestrictions(). +inline std::string getFileExtension(ArgParseArgument const & me, unsigned pos); + +// ========================================================================== +// Tags, Classes, Enums +// ========================================================================== + +// ---------------------------------------------------------------------------- +// Class ArgParseArgument +// ---------------------------------------------------------------------------- + +/*! + * @class ArgParseArgument + * @implements AssignableConcept + * @headerfile + * @brief Information for a specific command line argument. + * + * @signature class ArgParseArgument + */ + +/*! + * @enum ArgParseArgument::ArgumentType + * @headerfile + * @brief Define the type of an @link ArgParseArgument @endlink. + * + * @signature enum ArgParseArgument::ArgumentType; + * + * @section Examples + * + * In the following example, the types INPUT_FILE, OUTPUT_FILE, and DOUBLE are used. + * + * @include demos/dox/arg_parse/argument_parser.cpp + */ + +/*! + * @val ArgParseArgument::ArgumentType STRING + * @brief Argument is a string. + * + * @val ArgParseArgument::ArgumentType ArgParseArgument::INTEGER; + * @brief Argument is a signed 32 bit integer. + * + * @val ArgParseArgument::ArgumentType ArgParseArgument::INT64; + * @brief Argument is a signed 64 bit integer. + * + * @val ArgParseArgument::ArgumentType ArgParseArgument::DOUBLE; + * @brief Argument is a floating point number stored as double. + * + * @val ArgParseArgument::ArgumentType ArgParseArgument::INPUT_FILE; + * @brief Argument is an input file. + * + * @val ArgParseArgument::ArgumentType ArgParseArgument::OUTPUT_FILE; + * @brief Argument is an output file. + * + * @val ArgParseArgument::ArgumentType ArgParseArgument::INPUT_PREFIX; + * @brief Argument is a prefix to input file(s). + * + * @val ArgParseArgument::ArgumentType ArgParseArgument::OUTPUT_PREFIX; + * @brief Argument is a prefix to output file(s). + */ + +/*! + * @fn ArgParseArgument::ArgParseArgument + * @brief Constructor + * + * @signature ArgParseArgument::ArgParseArgument(argumentType[, argumentLabel[, isListArgument[, numberOfArgument]]]); + * + * @param[in] argumentType Type of the argument (ArgParseArgument::ArgumentType). + * @param[in] argumentLabel Label for the argument (char const *). + * @param[in] isListArgument Whether or not this argument can be given multiple times (bool). + * @param[in] numberOfArguments Number of times the argument must be given. E.g. set to 2 for the parser to always + * expect two values (int, default is 1). + */ + +class ArgParseArgument +{ +public: + enum ArgumentType + { + // argument is + BOOL, + STRING, // .. a string + INTEGER, // .. an integer + INT64, // .. a 64 bit integer + DOUBLE, // .. a float + INPUT_FILE, // .. an inputfile (implicitly also a string) + OUTPUT_FILE, // .. an outputfile (implicitly also a string) + INPUT_PREFIX, // .. an inputprefix (implicitly also a string) + ///@deprecated use INPUT_PREFIX instead + INPUTPREFIX = INPUT_PREFIX, + OUTPUT_PREFIX, // .. an outoutprefix (implicitly also a string) + INPUT_DIRECTORY, + OUTPUT_DIRECTORY + }; + + + // ---------------------------------------------------------------------------- + // Members to store type information + // ---------------------------------------------------------------------------- + ArgumentType _argumentType; + unsigned _numberOfValues; + std::string _argumentLabel; + bool _isListArgument; + + // ---------------------------------------------------------------------------- + // Members to store the values + // ---------------------------------------------------------------------------- + std::vector defaultValue; + std::vector value; + // Override for the file extension; only used for input/output file arguments. + std::vector _fileExtensions; + + // ---------------------------------------------------------------------------- + // Members for restrictions + // ---------------------------------------------------------------------------- + std::string minValue; + std::string maxValue; + std::vector validValues; + + // ---------------------------------------------------------------------------- + // Tags + // ---------------------------------------------------------------------------- + // Tags can be used to attach hints to the arguments (and options). Currently, + // this is used for tagging the "-file-ext" arguments as "file-ext-override" + // and "gkn-ignore" for ignoring in GKN. + std::vector tags; + + // ---------------------------------------------------------------------------- + // Members to help text + // ---------------------------------------------------------------------------- + std::string _helpText; // The help text shown on the command line + + // ---------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------- + + ArgParseArgument(ArgumentType argumentType, + std::string const & argumentLabel = "", + bool isListArgument = false, + unsigned numberOfValues = 1) : + _argumentType(argumentType), + _numberOfValues(numberOfValues), + _argumentLabel(argumentLabel), + _isListArgument(isListArgument), + minValue(""), + maxValue(""), + _helpText("") + { + if (argumentType == ArgParseArgument::BOOL) + { + copy(BooleanArgumentValues_<>::LIST_TRUE.begin(), BooleanArgumentValues_<>::LIST_TRUE.end(), + std::back_inserter(validValues)); + copy(BooleanArgumentValues_<>::LIST_FALSE.begin(), BooleanArgumentValues_<>::LIST_FALSE.end(), + std::back_inserter(validValues)); + } + } +}; + +// ========================================================================== +// Metafunctions +// ========================================================================== + +// ========================================================================== +// Functions +// ========================================================================== + +// ---------------------------------------------------------------------------- +// Helper Function _typeToString() +// ---------------------------------------------------------------------------- + +inline std::string _typeToString(ArgParseArgument const & me) +{ + switch (me._argumentType) + { + case ArgParseArgument::BOOL: + return "bool"; + + case ArgParseArgument::DOUBLE: + return "double"; + + case ArgParseArgument::INTEGER: + return "integer"; + + case ArgParseArgument::INT64: + return "int64"; + + case ArgParseArgument::STRING: + return "string"; + + case ArgParseArgument::INPUT_FILE: + return "input_file"; + + case ArgParseArgument::OUTPUT_FILE: + return "output_file"; + + case ArgParseArgument::INPUT_PREFIX: + return "input_prefix"; + + case ArgParseArgument::OUTPUT_PREFIX: + return "output_prefix"; + + case ArgParseArgument::INPUT_DIRECTORY: + return "input_directory"; + + case ArgParseArgument::OUTPUT_DIRECTORY: + return "output_directory"; + + default: + return "unknown"; + } +} + +// ---------------------------------------------------------------------------- +// Function isListArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isListArgument + * @headerfile + * + * @brief Returns whether the argument can be given more than one time. + * + * @signature bool isListArgument(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if it can be given multiple times, false otherwise. + */ + +inline bool isListArgument(ArgParseArgument const & me) +{ + return me._isListArgument; +} + +// ---------------------------------------------------------------------------- +// Function isBooleanArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isBooleanArgument + * @headerfile + * @brief Returns whether the argument is a bool. + * + * @signature bool isBooleanArgument(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if it is a bool, false otherwise. + */ + +inline bool isBooleanArgument(ArgParseArgument const & me) +{ + return me._argumentType == ArgParseArgument::BOOL; +} + +// ---------------------------------------------------------------------------- +// Function isStringArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isStringArgument + * @headerfile + * + * @brief Returns whether the argument is a string. + * + * @signature bool isStringArgument(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if it is a string, false otherwise. + */ + +inline bool isStringArgument(ArgParseArgument const & me) +{ + return (me._argumentType == ArgParseArgument::STRING) || + (me._argumentType == ArgParseArgument::INPUT_FILE) || + (me._argumentType == ArgParseArgument::OUTPUT_FILE) || + (me._argumentType == ArgParseArgument::INPUT_PREFIX) || + (me._argumentType == ArgParseArgument::OUTPUT_PREFIX) || + (me._argumentType == ArgParseArgument::INPUT_DIRECTORY) || + (me._argumentType == ArgParseArgument::OUTPUT_DIRECTORY); +} + +// ---------------------------------------------------------------------------- +// Function isIntegerArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isIntegerArgument + * @headerfile + * @brief Returns whether the argument is an integer. + * + * @signature bool isIntegerArgument(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if it is an integer, false otherwise. + */ + +inline bool isIntegerArgument(ArgParseArgument const & me) +{ + return me._argumentType == ArgParseArgument::INTEGER; +} + +// ---------------------------------------------------------------------------- +// Function isInt64Argument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isInt64Argument + * @headerfile + * @brief Returns whether the argument is a 64 bit integer. + * + * @signature bool isInt64Argument(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if it is a 64 bit integer, false otherwise. + */ + +inline bool isInt64Argument(ArgParseArgument const & me) +{ + return me._argumentType == ArgParseArgument::INT64; +} + +// ---------------------------------------------------------------------------- +// Function isDoubleArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isDoubleArgument + * @headerfile + * @brief Returns whether the argument is a double integer. + * + * @signature bool isDoubleArgument(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if it is a double argument, false otherwise. + */ + +inline bool isDoubleArgument(ArgParseArgument const & me) +{ + return me._argumentType == ArgParseArgument::DOUBLE; +} + +// ---------------------------------------------------------------------------- +// Function isInputFileArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isInputFileArgument + * @headerfile + * @brief Returns whether the argument is a input file. + * + * @signature bool isInputFileArgument(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if it is a input file argument, false otherwise. + */ + +inline bool isInputFileArgument(ArgParseArgument const & me) +{ + return me._argumentType == ArgParseArgument::INPUT_FILE || + me._argumentType == ArgParseArgument::INPUT_DIRECTORY; +} + +// ---------------------------------------------------------------------------- +// Function isOutputFileArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isOutputFileArgument + * @headerfile + * @brief Returns whether the argument is a output file. + * + * @signature bool isOutputFileArgument(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if it is a output file argument, false otherwise. + */ + +inline bool isOutputFileArgument(ArgParseArgument const & me) +{ + return me._argumentType == ArgParseArgument::OUTPUT_FILE || + me._argumentType == ArgParseArgument::OUTPUT_DIRECTORY; +} + +// ---------------------------------------------------------------------------- +// Function isOutputPrefixArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isOutputPrefixArgument + * @headerfile + * @brief Returns whether the argument is an output prefix. + * + * @signature bool isOutputPrefixArgument(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if it is an output prefix argument, false otherwise. + */ + +inline bool isOutputPrefixArgument(ArgParseArgument const & me) +{ + return me._argumentType == ArgParseArgument::OUTPUT_PREFIX; +} + +// ---------------------------------------------------------------------------- +// Function isOutputFileArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isInputPrefixArgument + * @headerfile + * @brief Returns whether the argument is an input prefix argument. + * + * @signature bool isInputPrefixArgument(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if it is an input prefix argument, false otherwise. + */ + +inline bool isInputPrefixArgument(ArgParseArgument const & me) +{ + return me._argumentType == ArgParseArgument::INPUT_PREFIX; +} + +// ---------------------------------------------------------------------------- +// Function getArgumentType() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#getArgumentType + * @headerfile + * @brief Return the ArgParseArgument::ArgumentType. + * + * @signature std::string getArgumentType(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return ArgumentType The argument type. + */ + +inline ArgParseArgument::ArgumentType getArgumentType(ArgParseArgument const & me) +{ + return me._argumentType; +} + +// ---------------------------------------------------------------------------- +// Function getArgumentTypeAsString() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#getArgumentTypeAsString + * @headerfile + * @brief Return argument type As a string. + * + * @signature std::string getArgumentTypeAsString(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return std::string The argument type as a STL string. + */ + +inline std::string getArgumentTypeAsString(ArgParseArgument const & me) +{ + return _typeToString(me._argumentType); +} + +// ---------------------------------------------------------------------------- +// Function getArgumentLabel() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#getArgumentLabel + * @headerfile + * @brief Return argument label. + * + * @signature std::string getArgumentLabel(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return std::string The argument label as a STL string. + */ + +inline std::string getArgumentLabel(ArgParseArgument const & me) +{ + return me._argumentLabel; +} + +// ---------------------------------------------------------------------------- +// Helper Function _intervalAssert() +// ---------------------------------------------------------------------------- + +// this methods ensures that the given arguments define a valid interval +// otherwise it will trigger a SEQAN_CHECK failure +template +inline void _intervalAssert(const std::string minValueAsString, const std::string maxValueAsString) +{ + if (minValueAsString != "" && maxValueAsString != "") + SEQAN_CHECK(_cast(minValueAsString) <= _cast(maxValueAsString), + "The interval [%s:%s] is invalid. Please specify a valid interval.", + minValueAsString.c_str(), + maxValueAsString.c_str()); +} + +// ---------------------------------------------------------------------------- +// Function setMinValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#setMinValue + * @headerfile + * @brief Set smallest allowed value for the argument. + * + * @signature void setMinValue(arg, minValue); + * + * @param[in,out] arg The ArgParseArgument to set the smallest value of. + * @param[in] minValue The smallest value to set (std::string). + */ + +inline void setMinValue(ArgParseArgument & me, const std::string minValue) +{ + if (isDoubleArgument(me)) + { + SEQAN_CHECK(_isCastable(minValue), "The maximal value for a double argument must be double."); + _intervalAssert(minValue, me.maxValue); + me.minValue = minValue; + } + else if (isIntegerArgument(me)) + { + SEQAN_CHECK(_isCastable(minValue), "The maximal value for an integer argument must be an integer"); + _intervalAssert(minValue, me.maxValue); + me.minValue = minValue; + } + else if (isInt64Argument(me)) + { + SEQAN_CHECK(_isCastable(minValue), "The maximal value for a 64 integer argument must be a 64 bit integer"); + _intervalAssert(minValue, me.maxValue); + me.minValue = minValue; + } + else + SEQAN_FAIL("min/max values are not applicable to non numeric arguments"); +} + +// ---------------------------------------------------------------------------- +// Function setMaxValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#setMaxValue + * @headerfile + * @brief Set smallest allowed value for the argument. + * + * @signature void setMaxValue(arg, maxValue); + * + * @param[in,out] arg The ArgParseArgument to set the smallest value of. + * @param[in] maxValue The largest value to set (std::string). + */ + +inline void setMaxValue(ArgParseArgument & me, const std::string maxValue) +{ + if (isDoubleArgument(me)) + { + SEQAN_CHECK(_isCastable(maxValue), "The maximal value for a double argument must be double."); + _intervalAssert(me.minValue, maxValue); + me.maxValue = maxValue; + } + else if (isIntegerArgument(me)) + { + SEQAN_CHECK(_isCastable(maxValue), "The maximal value for an integer argument must be an integer"); + _intervalAssert(me.minValue, maxValue); + me.maxValue = maxValue; + } + else if (isInt64Argument(me)) + { + SEQAN_CHECK(_isCastable(maxValue), "The maximal value for a 64 bit integer argument must be an 64 bit integer"); + _intervalAssert(me.minValue, maxValue); + me.maxValue = maxValue; + } + else + SEQAN_FAIL("min/max values are not applicable to non numeric arguments"); +} + +// ---------------------------------------------------------------------------- +// Function setValidValues() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#setValidValues + * @headerfile + * @brief Set list of valid values. + * + * @signature void setValidValues(arg, values); + * + * @param[in,out] arg The ArgParseArgument to set the valid values for. + * @param[in] values Either a std::string containing all valid entries, separated by spaces or a + * std::vector<std::string> with the valid entries. + * + * If the argument is of type string then the list of valid values is the case-sensitive list of string values + * allowed for this argument. If it is an input or output file then the list of valid values is a list of + * case-insentive file extensions identifying the allowed types. + * + * @section Examples + * + * An example of setting allowed values for a string option. + * + * @code{.cpp} + * seqan::ArgParseArgument stringArg(seqan::ArgParseArgument::STRING); + * setValidValues(stringArg, "one two three"); // one of {"one", "two", "three"} + * + * std::vector values; + * values.push_back("four"); + * values.push_back("five"); + * setValidValues(stringArg, values); // one of {"four", "five"} + * @endcode + * + * An example for an input file option. Note that by changing INPUT_FILE to OUTPUT_FILE below, + * the example would be the same for output files. + * + * @code{.cpp} + * seqan::ArgParseArgument fileArg(seqan::ArgParseArgument::INPUT_FILE); + * setValidValues(fileArg, "fq fastq"); // file must end in ".fq" or ".fastq" + * + * std::vector values; + * values.push_back("sam"); + * values.push_back("bam"); + * setValidValues(fileArg, values); // file must end in ".sam" or ".bam" + * @endcode + */ + +inline void setValidValues(ArgParseArgument & me, std::vector const & values) +{ + if (isDoubleArgument(me) || isIntegerArgument(me) || isBooleanArgument(me)) + SEQAN_FAIL("ArgParseArgument does not support setting valid values for numeric or boolean arguments."); + + me.validValues = values; +} + +inline void setValidValues(ArgParseArgument & me, std::string const & valuesString) +{ + if (isDoubleArgument(me) || isIntegerArgument(me) || isBooleanArgument(me)) + SEQAN_FAIL("ArgParseArgument does not support setting valid values for numeric or boolean arguments."); + + // convert array to String + std::vector values; + std::string current_argument; + + for (std::string::const_iterator ch = valuesString.begin(); ch != valuesString.end(); ++ch) + { + if (*ch == ' ') + { + appendValue(values, current_argument); + current_argument = ""; + } + else + { + append(current_argument, *ch); + } + } + if (current_argument != "") + appendValue(values, current_argument); + + setValidValues(me, values); +} + +// ---------------------------------------------------------------------------- +// Function setHelpText() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#setHelpText + * @headerfile + * @brief Set the help text for an ArgParseArgument. + * + * @signature void setHelpText(arg, text); + * + * @param[in,out] arg The ArgParseArgument to set the help text for. + * @param[in] text The text to display as the description of the argument (std::string). + */ + +inline void setHelpText(ArgParseArgument & me, std::string const & text) +{ + me._helpText = text; +} + +// ---------------------------------------------------------------------------- +// Helper Function _isInInterval() +// ---------------------------------------------------------------------------- + +// check if the given value is in the provided interval +template +inline bool _isInInterval(TString value, TString lowerIntervalBound, TString upperIntervalBound) +{ + bool isInInterval = true; + + if (lowerIntervalBound != "") + isInInterval &= (_cast(lowerIntervalBound) <= _cast(value)); + if (upperIntervalBound != "") + isInInterval &= (_cast(value) <= _cast(upperIntervalBound)); + + return isInInterval; +} + +// ---------------------------------------------------------------------------- +// Helper Function _checkNumericArgument() +// ---------------------------------------------------------------------------- + +// test if the values can be assigned to the option and is in the given boundaries +template +inline void _checkNumericArgument(ArgParseArgument const & me, std::string const & value) +{ + if (!_isCastable(value)) + { + std::stringstream what; + what << "the given value '" << value << "' cannot be casted to " << _typeToString(me); + SEQAN_THROW(ParseError(what.str())); + } + + if (!_isInInterval(value, me.minValue, me.maxValue)) + { + std::stringstream what; + what << "the given value '" << value << "' is not in the interval [" + << (me.minValue != "" ? me.minValue : "-inf") << ":" + << (me.maxValue != "" ? me.maxValue : "+inf") << "]"; + + SEQAN_THROW(ParseError(what.str())); + } +} + +// ---------------------------------------------------------------------------- +// Helper Function _compareExtension() +// ---------------------------------------------------------------------------- + +inline bool _compareExtension(std::string const & str, std::string const & ext) +{ + std::string str_ext = str.substr(str.size() - ext.size()); + for (size_t i = 0; i < str_ext.size() && i < ext.size(); ++i) + { + if (tolower(str_ext[i]) != tolower(ext[i])) + return false; + } + return true; +} + +// ---------------------------------------------------------------------------- +// Helper Function _checkStringRestrictions() +// ---------------------------------------------------------------------------- + +// The parameter i gives the index of the value in the argument. + +inline void _checkStringRestrictions(ArgParseArgument const & me, std::string const &value, + unsigned i) +{ + typedef std::vector::const_iterator TVectorIterator; + + // we only check valid values for files and string arguments, but not for prefix arguments + if (!empty(me.validValues) && !(isInputPrefixArgument(me) || isOutputPrefixArgument(me))) + { + // The file name "-" is reserved for stdin or stdout + if ((isInputFileArgument(me) || isOutputFileArgument(me)) && value == "-") + return; + + // Allow the filename to be a pipe (without checking its extension) + if (isInputFileArgument(me) && _isPipe(value.c_str())) + return; + + bool isContained = false; + for (TVectorIterator validValue = me.validValues.begin(); + validValue != me.validValues.end(); + ++validValue) + { + // if it is an input or output file, we only check the file endings + if (isInputFileArgument(me) || isOutputFileArgument(me)) + { + if (length(*validValue) > length(getFileExtension(me, i))) + continue; + else + isContained |= _compareExtension(getFileExtension(me, i), *validValue); + } + else + { + isContained |= (*validValue == value); + } + if (isContained) + break; + } + if (!isContained) + { + std::stringstream what; + if (isInputFileArgument(me) || isOutputFileArgument(me)) + what << "the given path '" << value << "' does not have one of the valid file extensions ["; + else + what << "the given value '" << value << "' is not in the list of allowed values ["; + for (TVectorIterator validValue = me.validValues.begin(); + validValue != me.validValues.end(); + ++validValue) + { + if (validValue != me.validValues.begin()) + what << ", "; + what << ((isInputFileArgument(me) || isOutputFileArgument(me)) ? "*" : "") << *validValue; + } + what << "]"; + if (i < me._fileExtensions.size()) + what << "; the file extension was overridden to be '" << getFileExtension(me, i) << "'"; + SEQAN_THROW(ParseError(what.str())); + } + } +} + +// ---------------------------------------------------------------------------- +// Helper Function _checkBooleanValidValues() +// ---------------------------------------------------------------------------- + +inline void _checkBooleanValidValues(ArgParseArgument const & me, std::string const & value) +{ + SEQAN_ASSERT(isBooleanArgument(me)); + + std::string value_up{value}; + std::transform(value.begin(), value.end(), value_up.begin(), ::toupper); // allow for lowercase letters + bool isContained = (std::find(me.validValues.begin(), me.validValues.end(), value_up) + != me.validValues.end()); + + if (!isContained) + { + std::stringstream what; + what << "the given value '" << value << "' is not in the list of allowed values ["; + + for (auto validValue = me.validValues.begin(); validValue != me.validValues.end(); ++validValue) + { + if (validValue != me.validValues.begin()) + what << ", "; + what << *validValue; + } + what << "]"; + SEQAN_THROW(ParseError(what.str())); + } +} + +// ---------------------------------------------------------------------------- +// Function _checkValue() +// ---------------------------------------------------------------------------- + +// Check value before or after assignment. +// +// The parameter i gives the index of the value to check for overriding the extension in case of file arguments. + +inline void _checkValue(ArgParseArgument const & me, std::string val, unsigned i = 0) +{ + // type checks + if (isIntegerArgument(me)) + _checkNumericArgument(me, val); + + if (isInt64Argument(me)) + _checkNumericArgument(me, val); + + if (isDoubleArgument(me)) + _checkNumericArgument(me, val); + + // check valid values + if (isBooleanArgument(me)) + _checkBooleanValidValues(me, val); + + if (isStringArgument(me)) + _checkStringRestrictions(me, val, i); +} + +inline void _checkValue(ArgParseArgument const & me) +{ + unsigned i = 0; + for (std::vector::const_iterator it = me.value.begin(); it != me.value.end(); ++it, ++i) + _checkValue(me, *it, i); +} + +// ---------------------------------------------------------------------------- +// Function _assignArgumentValue() +// ---------------------------------------------------------------------------- + +inline void _assignArgumentValue(ArgParseArgument & me, std::string const & value) +{ + // assignment + if (isListArgument(me)) // just append + { + appendValue(me.value, value, Exact()); + } + else + { + // check if we already set all expected arguments + if (length(me.value) == me._numberOfValues) + clear(me.value); + appendValue(me.value, value, Exact()); + } +} + +// ---------------------------------------------------------------------------- +// Function getArgumentValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#getArgumentValue + * @headerfile + * @brief Return the value of the argument. + * + * @signature std::string getArgumentValue(arg[, argNo]); + * + * @param[in,out] arg The ArgParseArgument to query. + * @param[in] argNo In case that the ArgParseArgument allowed multiple values, give the index of the argument + * that you want to retrieve (unsigned, starts at 0). + * + * @return std::string Const-reference to the argument value. + */ + +inline std::string const & getArgumentValue(ArgParseArgument const & me, unsigned argNo) +{ + SEQAN_CHECK(argNo < me.value.size() || argNo < me.defaultValue.size(), + "ArgParseArgument: No value set for index %d", argNo); + + if (argNo < me.value.size()) + return me.value[argNo]; + else + return me.defaultValue[argNo]; +} + +inline std::string const & getArgumentValue(ArgParseArgument const & me) +{ + return getArgumentValue(me, 0); +} + +// ---------------------------------------------------------------------------- +// Function getArgumentValues() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#getArgumentValues + * @headerfile + * @brief Return all values of the argument. + * + * @signature std::vector getArgumentValue(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return std::vector Const-reference to the argument values. + */ + +inline std::vector const & getArgumentValues(ArgParseArgument const & me) +{ + if (!me.value.empty()) + return me.value; + else + return me.defaultValue; +} + +// ---------------------------------------------------------------------------- +// Function hasArgumentValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#hasArgumentValue + * @headerfile + * @brief Return whether a value is available. + * + * @signature bool hasValue(arg[, pos]); + * + * @param[in] arg The ArgParseArgument to query. + * @param[in] pos The position of the argument in case of being a list (unsigned, 0-based, default is 0). + * + * @return bool true if pos is less than the size and the argument is non-empty. + */ + +inline bool hasValue(ArgParseArgument const & arg, unsigned position) +{ + return arg.value.size() > position || arg.defaultValue.size() > position; +} + +inline bool hasValue(ArgParseArgument const & arg) +{ + return hasValue(arg, 0); +} + +// ---------------------------------------------------------------------------- +// Function isSet() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#isSet + * @headerfile + * @brief Returns true if a value was assigned to the argument. + * + * @signature bool isSet(arg): + * + * @param[in] arg The ArgParseArgument to query. + * + * @return bool true if a value was assigned, false otherwise. + */ + +inline bool isSet(ArgParseArgument const & me) +{ + return !me.value.empty(); +} + +// ---------------------------------------------------------------------------- +// Function hasDefault() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#hasDefault + * @headerfile + * @brief Returns whether the argument has a default value. + * + * @signature bool hasDefault(arg); + * + * @param[in] arg The argument to query. + * + * @return bool true if the argument has a default value and false if not. + */ + +inline bool hasDefault(ArgParseArgument const & me) +{ + return !me.defaultValue.empty(); +} + +// ---------------------------------------------------------------------------- +// Function numberOfArguments +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#numberOfAllowedValues + * @headerfile + * @brief Returns the number of allowed values for this ArgParseArgument. + * + * @signature unsigned numberOfAllowedValues(arg); + * + * @param[in] arg The ArgParseArgument to query. + * + * @return unsigned The number of allowed values. + */ + +inline unsigned numberOfAllowedValues(ArgParseArgument const & me) +{ + return me._numberOfValues; +} + +// ---------------------------------------------------------------------------- +// Function getFileExtension() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseArgument#getFileExtension + * @headerfile + * @brief Returns the file extension for the given file argument. + * + * Only valid when argument is an INPUT_FILE or OUTPUT_FILE. + * + * Halts the program if not an input or output file argument. + * + * Can be overridden with special hidden options. + * For arguments, you can pass --arg-<num>-file-ext for argument num. + * For parameters, you can pass --<param-name>-file-ext for the option named param-name. + * + * @signature std::string getFileExtension(arg[, pos]); + * + * @param[in] arg The ArgParseArgument to query. + * @param[in] pos The position of the value to retrieve if multiple values (unsigned). + * + * @return std::string The file extension, empty if no extension or not set. + */ + +inline std::string getFileExtension(ArgParseArgument const & me, unsigned pos = 0) +{ + if (!isInputFileArgument(me) && !isOutputFileArgument(me)) + SEQAN_FAIL("Cannot get file extension from non-file argument/option."); + + // Short-circuit to override file extension if set. + if (pos < me._fileExtensions.size()) + { + std::string result = me._fileExtensions[pos]; + if (!result.empty() && result[0] != '.') + result.insert(0, "."); + return result; + } + + // Get argument value and break if empty. + std::string value = getArgumentValue(me, pos); + if (value.empty()) + return ""; + + // If there is a list of valid values then we look for each of these in the path. + if (!me.validValues.empty()) + { + for (unsigned i = 0; i < length(me.validValues); ++i) + { + unsigned len = std::min(me.validValues[i].size(), value.size()); + std::string tmp = value.substr(value.size() - len); + std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower); + if (tmp == me.validValues[i]) + return me.validValues[i]; + } + return ""; + } + + // Fall back to finding position of last dot. Return suffix if found and empty string if not. + size_t dotPos = value.find_last_of('.'); + if (dotPos == std::string::npos) + return ""; + return value.substr(dotPos + 1); +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_ARGUMENT_H_ diff --git a/seqan/arg_parse/arg_parse_ctd_support.h b/seqan/arg_parse/arg_parse_ctd_support.h new file mode 100644 index 0000000..532cddd --- /dev/null +++ b/seqan/arg_parse/arg_parse_ctd_support.h @@ -0,0 +1,594 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Bjoern Kahlert +// Author: Stephan Aiche +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_CTD_SUPPORT_H_ +#define SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_CTD_SUPPORT_H_ + +#include + +#include +#include +#include + +#include + +namespace seqan { + +// ---------------------------------------------------------------------------- +// Function _toText() +// ---------------------------------------------------------------------------- +// Removes formatting (\fI, \fB, and \fP). +template +TSequence _toText(TSequence const & input) +{ + TSequence buffer = xmlEscape(input); + TSequence result; + String openTags; + + typedef typename Iterator::Type TIterator; + TIterator endIt = end(input, Standard()); + for (TIterator it = begin(input, Standard()); it != endIt; goNext(it)) + { + if (*it == '\\') + { + // Handle escape sequence, we interpret only "\-", "\fI", and "\fB". + goNext(it); + SEQAN_ASSERT_NOT(it == endIt); + if (*it == '-') + { + appendValue(result, *it); + } + else if (*it == 'f') + { + goNext(it); + SEQAN_ASSERT_NOT(it == endIt); + if (*it == 'I') + { + appendValue(openTags, "i"); + } + else if (*it == 'B') + { + appendValue(openTags, "b"); + } + else if (*it == 'P') + { + SEQAN_ASSERT_NOT(empty(openTags)); + eraseBack(openTags); + } + else + { + append(result, "\\f"); + appendValue(result, *it); + } + } + else + { + appendValue(result, '\\'); + appendValue(result, *it); + } + } + else + { + appendValue(result, *it); + } + } + + return result; +} + +// ---------------------------------------------------------------------------- +// Function _join() +// ---------------------------------------------------------------------------- + +template +inline std::string +_join(std::vector const & v, std::string const & delimiter) +{ + typedef typename std::vector::const_iterator TStringSetIterator; + + std::stringstream joined; + for (TStringSetIterator it = v.begin(); it != v.end(); ++it) + { + if (it != v.begin()) + joined << delimiter; + joined << *it; + } + return joined.str(); +} + +// ---------------------------------------------------------------------------- +// Function _getPrefixedOptionName() +// ---------------------------------------------------------------------------- + +inline std::string +_getPrefixedOptionName(ArgParseOption const & opt) +{ + std::string optName = ""; + if (!empty(opt.longName)) + optName = "--" + opt.longName; + else + optName = "-" + opt.shortName; + + return optName; +} + +// ---------------------------------------------------------------------------- +// Function _getOptionName() +// ---------------------------------------------------------------------------- + +inline std::string +_getOptionName(ArgParseOption const & opt) +{ + if (!empty(opt.longName)) + return opt.longName; + else + return opt.shortName; +} + +// ---------------------------------------------------------------------------- +// Function _getRestrictions() +// ---------------------------------------------------------------------------- +inline void +_getRestrictions(std::vector & restrictions, ArgParseArgument const & opt) +{ + // we only extract non-file restrictions + if (isOutputFileArgument(opt) || isInputFileArgument(opt) || isInputPrefixArgument(opt) || isOutputPrefixArgument(opt)) + { + return; + } + else if (isBooleanArgument(opt)) + { + appendValue(restrictions, "true,false"); + return; + } + if (length(opt.validValues) != 0) + { + for (std::vector::const_iterator valid = opt.validValues.begin(); + valid != opt.validValues.end(); + ++valid) + { + appendValue(restrictions, *valid); + } + } + else + { + std::string minMaxRestriction = ""; + if (opt.minValue != "") + { + append(minMaxRestriction, opt.minValue); + append(minMaxRestriction, ":"); + } + if (opt.maxValue != "") + { + if (minMaxRestriction == "") + append(minMaxRestriction, ":"); + append(minMaxRestriction, opt.maxValue); + } + + if (minMaxRestriction != "") + appendValue(restrictions, minMaxRestriction); + } +} + +// ---------------------------------------------------------------------------- +// Function _addValidValuesRestrictions() +// ---------------------------------------------------------------------------- + +inline void +_getSupportedFormats(std::vector & supported_formats, ArgParseArgument const & opt) +{ + // we check only file arguments + if (!(isOutputFileArgument(opt) || isInputFileArgument(opt) || isInputPrefixArgument(opt) || isOutputPrefixArgument(opt))) + return; + + if (length(opt.validValues) != 0) + { + std::string filetype; + for (std::vector::const_iterator valid = opt.validValues.begin(); + valid != opt.validValues.end(); + ++valid) + { + SEQAN_ASSERT_NOT(empty(*valid)); + + filetype = "*"; + + // ensure . as separator between * and file-extension + if (value(*valid, 0) != '.') + appendValue(filetype, '.'); + + append(filetype, *valid); + appendValue(supported_formats, filetype); + } + } +} + +// ---------------------------------------------------------------------------- +// Function _includeInCTD() +// ---------------------------------------------------------------------------- + +/* + * returns true if this option should be included in the ctd + */ +inline bool +_includeInCTD(ArgParseOption const & opt) +{ + return !(opt.longName == "help" || opt.longName == "version" || opt.longName == "write-ctd" || opt.longName == "export-help" || (opt.shortName == "" && opt.longName == "")); +} + +// ---------------------------------------------------------------------------- +// Function _indent() +// ---------------------------------------------------------------------------- + +inline std::string _indent(const int currentIndent) +{ + std::string indent = ""; + for (int i = 0; i < currentIndent; ++i) + indent += "\t"; + return indent; +} + +// ---------------------------------------------------------------------------- +// Function _writeCLIElement() +// ---------------------------------------------------------------------------- +inline void _writeCLIElement(std::ostream & ctdfile, int currentIndent, std::string const & optionIdentifier, std::string const & ref_name, bool isList) +{ + ctdfile << _indent(currentIndent) + << "\n"; + + ctdfile << _indent(currentIndent + 1) << "\n"; + + ctdfile << _indent(currentIndent) << "\n"; +} + +// ---------------------------------------------------------------------------- +// Function _getManual() +// ---------------------------------------------------------------------------- +inline std::string _getManual(ArgumentParser const & me) +{ + std::stringstream manual; + for (unsigned i = 0; i < me._description.size(); ++i) + { + manual << _toText(me._description[i]) << std::endl; + } + return manual.str(); +} + +// ---------------------------------------------------------------------------- +// Function _toValidGKNTypeSpecifier() +// ---------------------------------------------------------------------------- +// TODO(dadi): similar to _typeToString() function. Differs only in the case of bool, integer, int64 and types +//. that has underscores in them. hyphens are used instead of underscores. e.g. input-file instead +// of input_file. This should be removed and _typeToString() should be used instead once GKN is +// modified to accept the results of _typeToString() functions directly. + +inline std::string _toValidGKNTypeSpecifier(ArgParseArgument const & me) +{ + switch (me._argumentType) + { + case ArgParseArgument::BOOL: + return "string"; + + case ArgParseArgument::INTEGER: + return "int"; + + case ArgParseArgument::INT64: + return "int"; + + case ArgParseArgument::INPUT_FILE: + return "input-file"; + + case ArgParseArgument::OUTPUT_FILE: + return "output-file"; + + case ArgParseArgument::INPUT_PREFIX: + return "input-prefix"; + + case ArgParseArgument::OUTPUT_PREFIX: + return "output-prefix"; + + case ArgParseArgument::INPUT_DIRECTORY: + return "input-prefix"; + + case ArgParseArgument::OUTPUT_DIRECTORY: + return "output-prefix"; + + default: + return _typeToString(me); + } +} + +// ---------------------------------------------------------------------------- +// Function writeCTD() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Change argument order. + +/*! + * @fn ArgumentParser#writeCTD + * @headerfile \ + * @brief Export the app's interface description to a .ctd file. + * + * @signature bool writeCTD(parser[, stream]); + * + * @param[in] parser The ArgumentParser to write the CTD file for. + * @param[out] stream A std::ostream to write to. If omitted an output file with the name form the + * "write-ctd" parameter of the parser is used. + * + * @return bool true on success, false on failure. + */ + +inline bool +writeCTD(ArgumentParser const & me, std::ostream & ctdfile) +{ + typedef ArgumentParser::TOptionMap::const_iterator TOptionMapIterator; + typedef ArgumentParser::TArgumentMapSize TArgumentMapSize; + + int currentIndent = 1; + + std::string toolname(toCString(xmlEscape(getAppName(me)))); + + // remove "_" in the tool name and make the following letter uppercase + std::string class_name; + bool upcase = true; + for (unsigned i = 0; i < toolname.size(); ++i) + { + if (toolname[i] == '_') + { + upcase = true; + continue; + } + class_name.push_back(toolname[i]); + if (upcase) + class_name[class_name.size() - 1] = toupper(toolname[i]); + upcase = false; + } + + ctdfile << "\n"; + ctdfile << "\n"; + ctdfile << _indent(currentIndent) << "" << toolname << "\n"; + ctdfile << _indent(currentIndent) << "" << xmlEscape(getShortDescription(me)) << "\n"; + ctdfile << _indent(currentIndent) << "" << xmlEscape(_getManual(me)) << "\n"; // TODO(aiche): as soon as we have a more sophisticated documentation embedded into the CmdParser, we should at this here + ctdfile << _indent(currentIndent++) << "\n"; + + // the unix way 1st the options + for (TOptionMapIterator optionMapIterator = me.optionMap.begin(); + optionMapIterator != me.optionMap.end(); + ++optionMapIterator) + { + ArgParseOption const & opt = *optionMapIterator; + + // exclude hidden + if (isHidden(opt)) + continue; + + std::string optionIdentifier = _getPrefixedOptionName(opt); + std::string refName = toolname + "." + _getOptionName(opt); + + if (_includeInCTD(opt)) + { + _writeCLIElement(ctdfile, currentIndent, optionIdentifier, refName, isListArgument(opt)); + } + } + + // add a warning to the CTD that arguments are hard to interpret by the users + if (me.argumentList.size() > 0u) + { + ctdfile << _indent(currentIndent) + << "\n"; + } + // then the arguments + for (TArgumentMapSize argIdx = 0; argIdx != me.argumentList.size(); ++argIdx) + { + // arguments do not have an option identifier + std::string optionIdentifier = ""; + std::stringstream refName; + refName << toolname << "." << "argument-" << argIdx; + _writeCLIElement(ctdfile, currentIndent, optionIdentifier, refName.str(), isListArgument(me.argumentList[argIdx])); + } + + ctdfile << _indent(--currentIndent) << "\n"; + ctdfile << _indent(currentIndent++) << "\n"; + ctdfile << _indent(currentIndent++) << "\n"; + + for (TOptionMapIterator optionMapIterator = me.optionMap.begin(); + optionMapIterator != me.optionMap.end(); + ++optionMapIterator) + { + ArgParseOption const & opt = *optionMapIterator; + + // exclude help, version, etc. + if (!_includeInCTD(opt)) + continue; + + // exclude hidden + if (isHidden(opt)) + continue; + + // prefer short name for options + std::string optionName = _getOptionName(opt); + + std::string type = _toValidGKNTypeSpecifier(opt); + + // set up restrictions + std::vector restrictions; + _getRestrictions(restrictions, opt); + + // set up supported formats + // add *.* to supported_formats if none is specified AND the type of the argument is a + // prefix type. This is important for KNIME nodes as they require similar file types + // to connect one node to the other. In this particular case any file is aproprate + // since we are talking about prefixes. + std::vector supported_formats; + _getSupportedFormats(supported_formats, opt); + if (empty(supported_formats) && (type=="input-prefix" || type=="output-prefix" )) + supported_formats.push_back("*.*"); + + ctdfile << _indent(currentIndent) + << " 0) + ctdfile << ","; + ctdfile << opt.tags[i]; + } + ctdfile << "\" "; + } + + if (isListArgument(opt)) + { + ctdfile << ">\n"; + for (size_t i = 0; i < length(opt.defaultValue); ++i) + { + ctdfile << _indent(currentIndent + 1) << "\n"; + } + ctdfile << _indent(currentIndent) << "\n"; + } + else + { + ctdfile << "/>\n"; + } + } + + for (TArgumentMapSize argIdx = 0; argIdx != me.argumentList.size(); ++argIdx) + { + ArgParseArgument arg = me.argumentList[argIdx]; + + // prefer short name for options + std::stringstream argumentNameStream; + argumentNameStream << "argument-" << argIdx; + std::string optionName = argumentNameStream.str(); + + std::string type = _toValidGKNTypeSpecifier(arg); + + // set up restrictions + std::vector restrictions; + _getRestrictions(restrictions, arg); + + // set up supported formats + // add *.* to supported_formats if none is specified AND the type of the argument is a + // prefix type. This is important for KNIME nodes as they require similar file types + // to connect one node to the other. In this particular case any file is aproprate + // since we are talking about prefixes. + std::vector supported_formats; + _getSupportedFormats(supported_formats, arg); + if (empty(supported_formats) && (type=="input-prefix" || type=="output-prefix" )) + supported_formats.push_back("*.*"); + + + ctdfile << _indent(currentIndent) + << " 0) + ctdfile << ","; + ctdfile << arg.tags[i]; + } + ctdfile << "\" "; + } + + ctdfile << "/>\n"; + } + + ctdfile << _indent(--currentIndent) << "\n"; + ctdfile << _indent(--currentIndent) << "\n"; + ctdfile << "" << std::endl; + + return true; +} + +inline bool +writeCTD(ArgumentParser const & me) +{ + // create file [appname].ctd in working directory + std::string ctdfilename; + getOptionValue(ctdfilename, me, "write-ctd"); + + std::ofstream ctdfile; + ctdfile.open(toCString(ctdfilename)); + + if (!ctdfile.is_open()) + { + std::cerr << getAppName(me) << ": Unable to create ctd file: " << ctdfilename << std::endl; + return false; + } + + writeCTD(me, ctdfile); + + ctdfile.close(); + return true; +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_CTD_SUPPORT_H_ diff --git a/seqan/arg_parse/arg_parse_doc.h b/seqan/arg_parse/arg_parse_doc.h new file mode 100644 index 0000000..528ce81 --- /dev/null +++ b/seqan/arg_parse/arg_parse_doc.h @@ -0,0 +1,1056 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_DOC_H_ +#define SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_DOC_H_ + +#include +#include + +namespace seqan { + +// ============================================================================ +// Functions +// ============================================================================ + +// -------------------------------------------------------------------------- +// Function getAppName() +// -------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getAppName + * @brief Return program name of ArgumentParser. + * + * @signature TCharStringRef getAppName(parser); + * + * @param[in] parser The ArgumentParser to get the app name for. + * + * @return TCharStringRef The app name, const-ref to @link CharString @endlink. + */ + +inline CharString const & getAppName(ArgumentParser const & parser) +{ + return getName(parser._toolDoc); +} + +// ---------------------------------------------------------------------------- +// Helper Function _parseAppName() +// ---------------------------------------------------------------------------- + +inline void _parseAppName(ArgumentParser & parser, std::string const & candidate) +{ + //IOREV _notio_ irrelevant for io-revision + int i = length(candidate) - 1; + + for (; i >= 0; --i) + if (candidate[i] == '\\' || candidate[i] == '/') + break; + + setName(parser._toolDoc, candidate.substr(i + 1)); +} + +// ---------------------------------------------------------------------------- +// Helper Function _addLine() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addLine + * @brief Adds a line of text to the help output of the ArgumentParser. + * + * The line of text will be added to the block of the options. + * + * @signature void addLine(parser, line); + * + * @param[in,out] parser The ArgumentParser to add the line to. + * @param[in] line The line of text to add, @link StringConcept @endlink of char. + */ + +template +inline void addLine(ArgumentParser & me, TString const & line) +{ + addOption(me, ArgParseOption("", "", line)); +} + +// ---------------------------------------------------------------------------- +// Function addSection() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addSection + * @brief Begins a new section of the option block of the ArgumentParser help output. + * + * @signature void addSection(parser, title); + * + * @param[in,out] parser The ArgumentParser to add the line to. + * @param[in] title The title to add, @link StringConcept @endlink of char. + * + * @code{.cpp} + * ArgumentParser parser; + * + * [...] // init parser + * + * addSection(parser, "In-/Output-Options"); + * addOption("i", ... ); + * addOption("o", ... ); + * + * addSection(parser, "Other Options"); + * addOption("x", ... ); + * @endcode + */ + +template +inline void addSection(ArgumentParser & me, TString const & line) +{ + addLine(me, ""); + addLine(me, line); +} + +// ---------------------------------------------------------------------------- +// Function addUsageLine() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addUseLine + * @brief Adds a line of text to the usage output of the ArgumentParser. + * + * @signature void addUsageLine(parser, line); + * + * @param[in,out] parser The ArgumentParser to add the line to. + * @param[in] line The line to add, a std::string. + */ + +inline void addUsageLine(ArgumentParser & me, std::string const & line) +{ + me._usageText.push_back(line); +} + +// ---------------------------------------------------------------------------- +// Helper Function _addUsage() +// ---------------------------------------------------------------------------- + +inline void _addUsage(ToolDoc & toolDoc, ArgumentParser const & me) +{ + for (unsigned i = 0; i < length(me._usageText); ++i) + { + std::string text = "\\fB"; + append(text, getAppName(me)); + append(text, "\\fP "); + append(text, me._usageText[i]); + addText(toolDoc, text, false); + } +} + +// ---------------------------------------------------------------------------- +// Function addDescription() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addDescription + * @brief Appends a description paragraph to the ArgumentParser documentation. + * + * @signature void addDescription(parser, description); + * + * @param[in,out] parser The ArgumentParser to add the line to. + * @param[in] description The description text, a std::string. + */ + +inline void addDescription(ArgumentParser & me, std::string const & description) +{ + me._description.push_back(description); +} + +// ---------------------------------------------------------------------------- +// Function setAppName() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setAppName + * @brief Sets application name of ArgumentParser. + * + * @signature void setAppName(parser, name); + * + * @param[in,out] parser The ArgumentParser to set the name of. + * @param[in] name The application name, std::string. + */ + +inline void setAppName(ArgumentParser & me, std::string const & name) +{ + setName(me._toolDoc, name); +} + +// ---------------------------------------------------------------------------- +// Function setShortDescription() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setShortDescription + * @brief Sets shortDescription of ArgumentParser. + * + * @signature void setShortDescription(parser, desc); + * + * @param[in,out] parser The ArgumentParser to set the short description of. + * @param[in] desc The short description, std::string. + */ + +inline void setShortDescription(ArgumentParser & me, std::string const & description) +{ + setShortDescription(me._toolDoc, description); +} + +// ---------------------------------------------------------------------------- +// Function getShortDescription() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getShortDescription + * @brief Returns the short description. + * + * @signature CharString getShortDescription(parser); + * + * @param[in,out] parser The ArgumentParser to get short description for. + * + * @return CharString A @link CharString @endlink with the short description. + */ + +inline CharString getShortDescription(ArgumentParser const & me) +{ + return getShortDescription(me._toolDoc); +} + +// ---------------------------------------------------------------------------- +// Function setUrl() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setUrl + * @brief Sets url of ArgumentParser. + * + * @signature void setUrl(parser, url); + * + * @param[in,out] parser The ArgumentParser to set the url of. + * @param[in] url The url string to set, @link CharString @endlink. + */ + +inline void setUrl(ArgumentParser & me, CharString const & urlString) +{ + setUrl(me._toolDoc, urlString); +} + +// -------------------------------------------------------------------------- +// Function getUrl() +// -------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getUrl + * @brief Returns the url string. + * + * @signature TCharStringRef getUrl(parser); + * + * @param[in,out] parser The ArgumentParser to get the url string from. + * + * @return TCharString A const-ref to a @link CharString @endlink with the url string. + */ + +inline CharString const & getUrl(ArgumentParser const & me) +{ + return getUrl(me._toolDoc); +} + +// ---------------------------------------------------------------------------- +// Function setVersion() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setVersion + * @brief Sets version of ArgumentParser. + * + * @signature void setVersion(parser, version); + * + * @param[in,out] parser The ArgumentParser to set the version of. + * @param[in] version The version string to set, std::string. + */ + +inline void setVersion(ArgumentParser & me, std::string const & versionString) +{ + setVersion(me._toolDoc, versionString); + if (!hasOption(me, "version")) + addOption(me, ArgParseOption("", "version", "Display version information.")); +} + +// -------------------------------------------------------------------------- +// Function getVersion() +// -------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getVersion + * @brief Returns the version string. + * + * @signature TCharStringRef getVersion(parser); + * + * @param[in,out] parser The ArgumentParser to get the version string from. + * + * @return TCharString A const-ref to a @link CharString @endlink with the version string. + */ + +inline CharString const & getVersion(ArgumentParser const & me) +{ + return getVersion(me._toolDoc); +} + +// ---------------------------------------------------------------------------- +// Function setShortCopyright() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setShortCopyright + * @brief Sets short copyright of ArgumentParser. + * + * @signature void setShortCopyright(parser, short copyright); + * + * @param[in,out] parser The ArgumentParser to set the short copyright of. + * @param[in] short copyright The short copyright string to set, std::string. + */ + +inline void setShortCopyright(ArgumentParser & me, CharString const & shortCopyrightString) +{ + setShortCopyright(me._toolDoc, shortCopyrightString); +} + +// -------------------------------------------------------------------------- +// Function getShortCopyright() +// -------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getShortCopyright + * @brief Returns the short copyright string. + * + * @signature TCharStringRef getShortCopyright(parser); + * + * @param[in,out] parser The ArgumentParser to get the short copyright string from. + * + * @return TCharString A const-ref to a @link CharString @endlink with the short copyright string. + */ + +inline CharString const & getShortCopyright(ArgumentParser const & me) +{ + return getShortCopyright(me._toolDoc); +} + +// ---------------------------------------------------------------------------- +// Function setLongCopyright() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setLongCopyright + * @brief Sets long copyright of ArgumentParser. + * + * @signature void setLongCopyright(parser, long copyright); + * + * @param[in,out] parser The ArgumentParser to set the long copyright of. + * @param[in] long copyright The long copyright string to set, std::string. + */ + +inline void setLongCopyright(ArgumentParser & me, CharString const & longCopyrightString) +{ + setLongCopyright(me._toolDoc, longCopyrightString); + if (!hasOption(me, "copyright")) + addOption(me, ArgParseOption("", "copyright", "Display long copyright information.")); +} + +// -------------------------------------------------------------------------- +// Function getLongCopyright() +// -------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getLongCopyright + * @brief Returns the long copyright string. + * + * @signature TCharStringRef getLongCopyright(parser); + * + * @param[in,out] parser The ArgumentParser to get the long copyright string from. + * + * @return TCharString A const-ref to a @link CharString @endlink with the long copyright string. + */ + +inline CharString const & getLongCopyright(ArgumentParser const & me) +{ + return getLongCopyright(me._toolDoc); +} + + +// ---------------------------------------------------------------------------- +// Function setCitation() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setCitation + * @brief Sets citation of ArgumentParser. + * + * @signature void setCitation(parser, citation); + * + * @param[in,out] parser The ArgumentParser to set the citation of. + * @param[in] citation The citation string to set, std::string. + */ + +inline void setCitation(ArgumentParser & me, CharString const & citationString) +{ + setCitation(me._toolDoc, citationString); +} + +// -------------------------------------------------------------------------- +// Function getCitation() +// -------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getCitation + * @brief Returns the citation string. + * + * @signature TCharStringRef getCitation(parser); + * + * @param[in,out] parser The ArgumentParser to get the citation string from. + * + * @return TCharString A const-ref to a @link CharString @endlink with the citation string. + */ + +inline CharString const & getCitation(ArgumentParser const & me) +{ + return getCitation(me._toolDoc); +} + +// -------------------------------------------------------------------------- +// Function setCategory() +// -------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setCategory + * @brief Sets category of ArgumentParser. + * + * @signature void setCategory(parser, category); + * + * @param[in,out] parser The ArgumentParser to set the category of. + * @param[in] category The category to set, std::string. + */ + +inline void setCategory(ArgumentParser & parser, CharString const & category) +{ + setCategory(parser._toolDoc, category); +} + +// -------------------------------------------------------------------------- +// Function getCategory() +// -------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getCategory + * @brief Returns the category. + * + * @signature TCharStringRef getCategory(parser); + * + * @param[in,out] parser The ArgumentParser to get the category from. + * + * @return TCharString A const-ref to a @link CharString @endlink with the category. + */ + +inline CharString const & getCategory(ArgumentParser const & parser) +{ + return getCategory(parser._toolDoc); +} + +// ---------------------------------------------------------------------------- +// Function setDate() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setDate + * @brief Sets date string of ArgumentParser. + * + * @signature void setDate(parser, date); + * + * @param[in,out] parser The ArgumentParser to set the date string of. + * @param[in] date The date string to set, std::string. + */ + +inline void setDate(ArgumentParser & me, std::string const & date) +{ + setDate(me._toolDoc, date); +} + +// ---------------------------------------------------------------------------- +// Function addTextSection() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addTextSection + * @brief Add a text section to the ArgumentParser. + * + * @signature void addTextSection(parser, title); + * + * @param[in,out] parser The ArgumentParser to add the text section title to. + * @param[in] title The section title to add, std::string. + */ + +inline void addTextSection(ArgumentParser & me, std::string const & title) +{ + addSection(me._toolDoc, title); +} + +// ---------------------------------------------------------------------------- +// Function addTextSubSection() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addTextSubSection + * @brief Add a text sub section to the ArgumentParser. + * + * @signature void addTextSubSection(parser, title); + * + * @param[in,out] parser The ArgumentParser add the subsection title to of. + * @param[in] title The sub section title to add, std::string. + */ + +inline void addTextSubSection(ArgumentParser & me, std::string const & title) +{ + addSubSection(me._toolDoc, title); +} + +// ---------------------------------------------------------------------------- +// Function addText() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addText + * @brief Add text to an ArgumentParser. + * + * @signature void addText(parser, text); + * + * @param[in,out] parser ArgumentParser to add text to. + * @param[in] text The std::string to add to the parser. + */ + +inline void addText(ArgumentParser & me, std::string const & text) +{ + addText(me._toolDoc, text); +} + +// ---------------------------------------------------------------------------- +// Function addListItem() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addListItem + * @brief Appends a list item to the ArgumentParser + * + * @signature void addListItem(parser, item, description); + * + * @param[in,out] parser The ArgumentParser to add the list item to. + * @param[in] item The item to add, std::string. + * @param[in] description The item to add, std::string. + */ + +inline void addListItem(ArgumentParser & me, std::string const & item, std::string const & description) +{ + addListItem(me._toolDoc, item, description); +} + +// ---------------------------------------------------------------------------- +// Function printShortHelp() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#printShortHelp + * @brief Prints a short help message for the parser to a stream. + * + * @signature void printShortHelp(parser, out); + * + * @param[in,out] parser The ArgumentParser to print help for. + * @param[in,out] out The std::ostream to print help to. + */ + +inline void printShortHelp(ArgumentParser const & me, std::ostream & stream) +{ + // TODO: maybe we can get this a bit prettier + ToolDoc shortDoc(me._toolDoc); + clearEntries(shortDoc); + + _addUsage(shortDoc, me); + + std::stringstream shortHelp; + shortHelp << "Try '" << getAppName(me) << " --help' for more information.\n"; + addText(shortDoc, shortHelp.str()); + + print(stream, shortDoc, "txt"); +} + +inline void printShortHelp(ArgumentParser const & me) +{ + printShortHelp(me, std::cerr); +} + +// ---------------------------------------------------------------------------- +// Function printVersion() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#printVersion + * @brief Prints the version information of the parser to a stream. + * + * @signature void printVersion(parser, stream); + * + * @param[in,out] parser The ArgumenParser to print for. + * @param[in,out] stream The std::ostream to print to. + */ + +inline void printVersion(ArgumentParser const & me, std::ostream & stream) +{ + stream << getAppName(me) << " version: " << getVersion(me) << std::endl; + stream << "SeqAn version: " << SEQAN_VERSION_MAJOR << '.' << SEQAN_VERSION_MINOR << '.' + << SEQAN_VERSION_PATCH; + if (SEQAN_VERSION_PRE_RELEASE != 0) + stream << "-pre" << SEQAN_VERSION_PRE_RELEASE; + stream << "\n"; +} + +inline void printVersion(ArgumentParser const & me) +{ + printVersion(me, std::cerr); +} + +// ---------------------------------------------------------------------------- +// Function printLongCopyright() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#printLongCopyright + * @brief Prints the long copyright information of the parser to a stream. + * + * @signature void printLongCopyright(parser, stream); + * + * @param[in,out] parser The ArgumenParser to print for. + * @param[in,out] stream The std::ostream to print to. + */ + +inline void printLongCopyright(ArgumentParser const & me, std::ostream & stream) +{ + stream << "=============================================================================" << std::endl + << "Copyright information for " << getAppName(me) << ":" << std::endl + << "-----------------------------------------------------------------------------" << std::endl + << me._toolDoc._longCopyright << std::endl << std::endl + << "=============================================================================" << std::endl + << "This program contains SeqAn code licensed under the following terms:" << std::endl + << "-----------------------------------------------------------------------------" << std::endl + << " Copyright (c) 2006-2015, Knut Reinert, FU Berlin" << std::endl + << " All rights reserved." << std::endl + << "" << std::endl + << " Redistribution and use in source and binary forms, with or without" << std::endl + << " modification, are permitted provided that the following conditions are met:" << std::endl + << "" << std::endl + << " * Redistributions of source code must retain the above copyright" << std::endl + << " notice, this list of conditions and the following disclaimer." << std::endl + << " * Redistributions in binary form must reproduce the above copyright" << std::endl + << " notice, this list of conditions and the following disclaimer in the" << std::endl + << " documentation and/or other materials provided with the distribution." << std::endl + << " * Neither the name of Knut Reinert or the FU Berlin nor the names of" << std::endl + << " its contributors may be used to endorse or promote products derived" << std::endl + << " from this software without specific prior written permission." << std::endl + << "" << std::endl + << " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"" << std::endl + << " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE" << std::endl + << " IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE" << std::endl + << " ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE" << std::endl + << " FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL" << std::endl + << " DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR" << std::endl + << " SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER" << std::endl + << " CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT" << std::endl + << " LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY" << std::endl + << " OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH" << std::endl + << " DAMAGE." << std::endl; +} + +inline void printLongCopyright(ArgumentParser const & me) +{ + printLongCopyright(me, std::cerr); +} + +// ---------------------------------------------------------------------------- +// Function _addNumericalRestriction() +// ---------------------------------------------------------------------------- + +inline void _addNumericalRestriction(std::string & text, ArgParseArgument const & arg) +{ + // expand min/max restrictions + if (!empty(arg.minValue) || !empty(arg.maxValue)) + { + append(text, " In range ["); + + if (!empty(arg.minValue)) + append(text, arg.minValue); + else + append(text, "-inf"); + + append(text, ".."); + + if (!empty(arg.maxValue)) + append(text, arg.maxValue); + else + append(text, "inf"); + + append(text, "]."); + } +} + +// ---------------------------------------------------------------------------- +// Function _expandList() +// ---------------------------------------------------------------------------- + +// expands the given vector as text in the form v1, v2, and v3, while respecting +// the size with respect to the used commas and "and"s +inline void _expandList(std::string & text, std::vector const & list) +{ + for (std::vector::size_type i = 0; i < list.size(); ++i) + { + if (i + 1 == list.size() && list.size() == 2u) + append(text, " and "); + else if (i + 1 == list.size() && list.size() > 2u) + append(text, ", and "); + else if (i != 0) + append(text, ", "); + + append(text, "\\fI"); + append(text, list[i]); + append(text, "\\fP"); + + } +} + +// ---------------------------------------------------------------------------- +// Function _addDefaultValues() +// ---------------------------------------------------------------------------- + +inline void _addDefaultValues(std::string & text, ArgParseArgument const & arg) +{ + if (!empty(arg.defaultValue)) + { + append(text, " Default: "); + _expandList(text, arg.defaultValue); + append(text, "."); + } +} + +inline void _addDefaultValues(std::string & text, ArgParseOption const & arg) +{ + if (!isFlagOption(arg)) + _addDefaultValues(text, static_cast(arg)); +} + +// ---------------------------------------------------------------------------- +// Function _seperateExtensionsForPrettyPrinting() +// ---------------------------------------------------------------------------- + +inline void _seperateExtensionsForPrettyPrinting(std::vector & file_ext, + std::vector & comp_ext, + std::vector const & validValues) +{ + // seperate file extensions and compression extensions + for (std::vector::size_type i = 0; i < validValues.size(); ++i) + { + std::regex rgx("^(\\.)?([A-z0-9]+)(\\.)?([A-z0-9]+)?"); + std::smatch result; + + std::regex_search(validValues[i], result, rgx); + + if (!result[4].str().empty()) + { + comp_ext.push_back(result[4].str()); + file_ext.push_back("." + result[2].str() + "[.*]"); + } + else + { + file_ext.push_back("." + result[2].str()); + } + } + + std::sort(file_ext.rbegin(), file_ext.rend()); // sort extensions in reverse order such that '.fa[.x]' + std::sort(comp_ext.rbegin(), comp_ext.rend()); // comes before '.fa' and will be chosen by std::unique() + + comp_ext.erase(std::unique(comp_ext.begin(), comp_ext.end()), comp_ext.end()); // remove duplicates + file_ext.erase(std::unique(file_ext.begin(), file_ext.end(), + [&](auto& lhs, auto& rhs) + { + return lhs.substr(0, lhs.find('[')) == rhs.substr(0, rhs.find('[')); + }), file_ext.end()); +} + +// ---------------------------------------------------------------------------- +// Function _addValidValuesRestrictions() +// ---------------------------------------------------------------------------- + +inline void _addValidValuesRestrictions(std::string & text, ArgParseArgument const & arg) +{ + if (!empty(arg.validValues)) + { + if (isInputFileArgument(arg) || isOutputFileArgument(arg)) + { + std::vector file_extensions; + std::vector compresssion_extensions; + + _seperateExtensionsForPrettyPrinting(file_extensions, compresssion_extensions, arg.validValues); + + append(text, " Valid filetype"); + + if (file_extensions.size() > 1) + append(text, "s are: "); + else + append(text, " is: "); + + _expandList(text, file_extensions); + + if (compresssion_extensions.size() != 0) + { + append(text, ", where * is any of the following extensions: "); + _expandList(text, compresssion_extensions); + append(text, " for transparent (de)compression"); + } + } + else + { + append(text, " One of "); + _expandList(text, arg.validValues); + } + + append(text, "."); + } +} + +inline void _addValidValuesRestrictions(std::string & text, ArgParseOption const & opt) +{ + if (!isFlagOption(opt)) + _addValidValuesRestrictions(text, static_cast(opt)); +} + +// ---------------------------------------------------------------------------- +// Function _addTypeAndListInfo() +// ---------------------------------------------------------------------------- + +inline void _addTypeAndListInfo(std::string & text, ArgParseArgument const & arg) +{ + std::string type = getArgumentTypeAsString(arg); + for (auto & c: type) + c = toupper(c); + + // Write arguments to term line -> only exception, boolean flags + if (!empty(type)) + { + append(text, " "); + + if (isListArgument(arg)) + append(text, "List of "); + + if (arg._numberOfValues != 1) + append(text, std::to_string(arg._numberOfValues) + " "); + + append(text, "\\fI"); + append(text, type); + append(text, "\\fP"); + + if (isListArgument(arg) || arg._numberOfValues != 1) + append(text, "'s"); + } +} + +// ---------------------------------------------------------------------------- +// Function printHelp() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Parameter order. + +/*! + * @fn ArgumentParser#printHelp + * @brief Prints the help message for the parser. + * + * @signature void printHelp(parser, out, format, showAdvancedOptions); + * + * @param[in,out] parser The ArgumentParser print the help for. + * @param[out] out The output stream to print to (std::ostream). + * @param[in] format The format to print, one of "html", "man", and "txt". + * @param[in] showAdvancedOptions Also show advanced options to user (default = false). + */ + +inline void printHelp(ArgumentParser const & me, + std::ostream & stream, + CharString const & format, + bool const showAdvancedOptions) +{ + ToolDoc toolDoc(me._toolDoc); + clearEntries(toolDoc); // We will append me._toolDoc later. + + // Build synopsis section. + addSection(toolDoc, "Synopsis"); + _addUsage(toolDoc, me); + + // Add description to tool documentation. + addSection(toolDoc, "Description"); + for (unsigned i = 0; i < me._description.size(); ++i) + addText(toolDoc, me._description[i]); + + // Add arguments to arguments section + if (length(me.argumentList) != 0) + addSection(toolDoc, "Required Arguments"); + + for (unsigned i = 0; i < length(me.argumentList); ++i) + { + ArgParseArgument const & arg = me.argumentList[i]; + + // Build list item term. + std::string term; + if (!empty(arg._argumentLabel)) + { + std::regex space(" "); + term = "\\fB"; + append(term, std::regex_replace(arg._argumentLabel, space,"_")); + append(term, "\\fP"); + } + else + { + term = "\\fBARGUMENT "; + append(term, std::to_string(i)); + append(term, "\\fP"); + } + + // expand type, list and numValues information + _addTypeAndListInfo(term, arg); + + std::string helpText = arg._helpText; + + // expand min/max restrictions + _addNumericalRestriction(helpText, arg); + + // expand validValues restrictions + _addValidValuesRestrictions(helpText, arg); + + // expand defaultValue + _addDefaultValues(helpText, arg); + + // Add list item. + addListItem(toolDoc, term, helpText); + } + + // Add options to options section. + if (length(me.optionMap) != 0) + addSection(toolDoc, "Options"); + + for (unsigned i = 0; i < length(me.optionMap); ++i) + { + ArgParseOption const & opt = me.optionMap[i]; + if (empty(opt.shortName) && empty(opt.longName)) // this is not an option but a text line + { + if (empty(opt._helpText)) // TODO(holtgrew): Should go away in future. + continue; // Skip empty lines. + + // Is command line parser section, maps to ToolDoc subsection. + for (unsigned j = i + 1; j < length(me.optionMap); ++j) + { + ArgParseOption const & nextopt = me.optionMap[j]; + if (empty(nextopt.shortName) && empty(nextopt.longName)) + break; + // has visible children + if (!isHidden(nextopt) && (!isAdvanced(nextopt) || showAdvancedOptions)) + { + std::string title = opt._helpText; + append(title, ":"); + addSubSection(toolDoc, title); + break; + } + } + } + else if (!isHidden(opt) && (!isAdvanced(opt) || showAdvancedOptions)) + { + // Build list item term. + std::string term; + if (!empty(opt.shortName)) + { + term = "\\fB-"; + append(term, opt.shortName); + append(term, "\\fP"); + } + if (!empty(opt.shortName) && !empty(opt.longName)) + append(term, ", "); + if (!empty(opt.longName)) + { + append(term, "\\fB--"); + append(term, opt.longName); + append(term, "\\fP"); + } + + // expand type, list and numValues information + if (!opt._isFlag) + _addTypeAndListInfo(term, opt); + + std::string helpText = opt._helpText; + + // expand min/max restrictions + _addNumericalRestriction(helpText, opt); + + // expand validValues restrictions + _addValidValuesRestrictions(helpText, opt); + + // expand defaultValue + _addDefaultValues(helpText, opt); + + // Add list item. + addListItem(toolDoc, term, helpText); + } + } + + append(toolDoc, me._toolDoc); + print(stream, toolDoc, format); +} + +inline void printHelp(ArgumentParser const & me, std::ostream & stream, CharString const & format) +{ + printHelp(me, stream, format, false); +} + +inline void printHelp(ArgumentParser const & me, std::ostream & stream) +{ + printHelp(me, stream, "txt", false); +} + +inline void printHelp(ArgumentParser const & me) +{ + printHelp(me, std::cerr, "txt", false); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_DOC_H_ diff --git a/seqan/arg_parse/arg_parse_exceptions.h b/seqan/arg_parse/arg_parse_exceptions.h new file mode 100644 index 0000000..5c6ffe1 --- /dev/null +++ b/seqan/arg_parse/arg_parse_exceptions.h @@ -0,0 +1,89 @@ +// ========================================================================== +// arg_parse_exceptions.h +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_EXCEPTIONS_H_ +#define SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_EXCEPTIONS_H_ + +namespace seqan { + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class ParseError +// ---------------------------------------------------------------------------- + +// Defined in include/seqan/stream/tokenization.h +struct ParseError; + +// ---------------------------------------------------------------------------- +// Class InvalidOption +// ---------------------------------------------------------------------------- + +class InvalidOption : public ParseError +{ +public: + InvalidOption(std::string const & option) : + ParseError("illegal option -- " + option) + {} +}; + +// ---------------------------------------------------------------------------- +// Class MissingArgument +// ---------------------------------------------------------------------------- + +class MissingArgument : public ParseError +{ +public: + MissingArgument(std::string const & option) : + ParseError("option requires an argument -- " + option) + {} +}; + +// ---------------------------------------------------------------------------- +// Class NotEnoughArguments +// ---------------------------------------------------------------------------- + +class NotEnoughArguments : public ParseError +{ +public: + NotEnoughArguments(std::string const & option) : + ParseError("option requires more arguments -- " + option) + {} +}; + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_EXCEPTIONS_H_ diff --git a/seqan/arg_parse/arg_parse_option.h b/seqan/arg_parse/arg_parse_option.h new file mode 100644 index 0000000..7b6d8bd --- /dev/null +++ b/seqan/arg_parse/arg_parse_option.h @@ -0,0 +1,492 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_OPTION_H_ +#define SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_OPTION_H_ + +#include +#include +#include +#include + +namespace seqan { + +// ---------------------------------------------------------------------------- +// Class ArgParseOption +// ---------------------------------------------------------------------------- + +/*! + * @class ArgParseOption + * @extends ArgParseArgument + * @headerfile + * @brief Store information for a specific command line option. + * + * @signature class ArgParseOption : ArgParseArgument; + * + * You can use the shortcut @link ArgumentParser#addOption @endlink for adding options to @link ArgumentParser @endlink + * object. + */ + +/*! + * @fn ArgParseOption::ArgParseOption + * @brief Constructor. + * + * @signature ArgParseOption::ArgParseOption(shortName, longName, helpText, argumentType[, argumentLabel[, isList[, numValues]]]); + * + * @param[in] shortName The short name of the argument. + * @param[in] longName The long name of the argument (std::string). + * @param[in] helpText The text to display as help (std::string). + * @param[in] argumentType The type of the argument (@link ArgParseArgument::ArgumentType @endlink). + * @param[in] argumentLabel The label for the value to use in the help display, e.g. 'INT' in '--value INT' + * (std::string). + * @param[in] isList Flag for whether this option can be given multiple times (bool, true for + * allowing multiple values). + * @param[in] numValues Number of command line arguments that each option should bind (unsigned). + * + * @section Short and Long Option Names + * + * Short option names are passed to the program following one dash (e.g. '-i', '-e'). Long optiongs are passed + * following two dashes (e.g. '--num-threads', '--error-rate'). The leading one or two dashes are not passed to the + * constructor of ArgParseOption, however. + * + * @section Naming Conventions + * + *
    + *
  • Keep the short name short, ideally to one character.
  • + *
  • Only use lower-case characters in the long name, use dashes to separate words, only use alphanumeric characters + * and dashes, no underline characters
  • . + *
+ */ + +class ArgParseOption : + public ArgParseArgument +{ +public: + // ---------------------------------------------------------------------------- + // Members to specify the names of the ArgParseOption + // ---------------------------------------------------------------------------- + std::string shortName; // short option name + std::string longName; // long option name + + // ---------------------------------------------------------------------------- + // Members representing type, content and restrictions of the ArgParseOption + // ---------------------------------------------------------------------------- + bool _isFlag; // true if this a bool option, that has no + // argument we will internally represent it as a + // string option set to either "true" or "false" + bool _isRequired; // true if this ArgParseOption must be set + bool _isHidden; // true if this ArgParseOption should not be + // shown on the command line + bool _isAdvanced; // true if this ArgParseOption should only + // be shown in the full help + + // ---------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------- + ArgParseOption(std::string const & _shortName, + std::string const & _longName, + std::string const & _help, + ArgumentType argumentType, + std::string const & argumentLabel = "", + bool isListArgument = false, + unsigned numberOfValues = 1) : + ArgParseArgument(argumentType, argumentLabel, isListArgument, numberOfValues), + shortName(_shortName), + longName(_longName), + _isFlag(false), + _isRequired(false), + _isHidden(false), + _isAdvanced(false) + { + _helpText = _help; + } + + ArgParseOption(std::string const & _shortName, + std::string const & _longName, + std::string const & _help) : + ArgParseArgument(ArgParseArgument::STRING), + shortName(_shortName), + longName(_longName), + _isFlag(true), + _isRequired(false), + _isHidden(false), + _isAdvanced(false) + { + defaultValue.push_back("false"); + setValidValues(*this, "true false"); + _helpText = _help; + } + +}; + +// ---------------------------------------------------------------------------- +// Function isStringArgument() +// ---------------------------------------------------------------------------- + +inline bool isStringArgument(ArgParseOption const & me) +{ + return isStringArgument(static_cast(me)) && !me._isFlag; +} + +// ---------------------------------------------------------------------------- +// Function isFlagOption() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#isFlagOption + * @headerfile + * @brief Returns whether an option is a flag. + * + * @signature bool isFlagOption(option); + * + * @param[in] option The ArgParseOption object to query. + * + * @return bool true if option is a flag/switch and false otherwise. + * + * Flags are given without arguments, e.g. the -l flag in the Unix ls command. + */ + +inline bool isFlagOption(ArgParseOption const & me) +{ + return me._isFlag; +} + +// ---------------------------------------------------------------------------- +// Function isHidden() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#isHidden + * @headerfile + * @brief Return whether an option is hidden on the help screen. + * + * @signature bool isHidden(option); + * + * @param[in] option The ArgParseOption object to query. + * + * @return bool true if it is hidden, false otherwise. + * + * By default, options are not hidden. + */ + +inline bool isHidden(ArgParseOption const & me) +{ + return me._isHidden; +} + +// ---------------------------------------------------------------------------- +// Function hideOption() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#hideOption + * @headerfile + * @brief Hides the ArgParseOption from the help screen (or shows it again). + * + * @signature void hideOption(option[, hide]); + * + * @param[in,out] option The ArgParseOption object to set the hidden flag of. + * @param[in] hide bool that indicates whether to hide the flag (default: true) + */ + +inline void hideOption(ArgParseOption & me, bool hide = true) +{ + me._isHidden = hide; +} + +// ---------------------------------------------------------------------------- +// Function isHidden() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#isAdvanced + * @headerfile + * @brief Return whether an option is only shown in the full help screen. + * + * @signature bool isAdvanced(option); + * + * @param[in] option The ArgParseOption object to query. + * + * @return bool true if it is hidden, false otherwise. + * + * By default, options are not marked as advanced. + */ + +inline bool isAdvanced(ArgParseOption const & me) +{ + return me._isAdvanced; +} + +// ---------------------------------------------------------------------------- +// Function hideOption() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#setAdvanced + * @headerfile + * @brief Shows the ArgParseOption only on the full help screen. + * + * @signature void setAdvanced(option[, advanced]); + * + * @param[in,out] option The ArgParseOption object to set the advanced flag of. + * @param[in] advanced bool that indicates whether to hide the flag (default: true) + */ + +inline void setAdvanced(ArgParseOption & me, bool advanced = true) +{ + me._isAdvanced = advanced; +} + +// ---------------------------------------------------------------------------- +// Function isRequired() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#isRequired + * @headerfile + * @brief Returns whether the option is mandatory. + * + * @signature bool isRequired(option); + * + * @param[in] option The ArgParseOption object to query. + * + * @return bool true if the option is mandatory and false if it not. + * + * By default, options are not mandatory. + */ + +inline bool isRequired(ArgParseOption const & me) +{ + return me._isRequired; +} + +// ---------------------------------------------------------------------------- +// Function setDefaultValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#setDefaultValue + * @headerfile + * @brief Set the default value for the given option. + * + * @signature void setDefaultValue(option, v); + * + * @param[in,out] option The ArgParseOption to set the default value for. + * @param[in] v The value to set, (any type that can be streamed into an std::stringstream). + */ + +// TODO(holtgrew): Deprecate in favour of string-only variant? + +template +inline void setDefaultValue(ArgParseOption & me, const TValue & value) +{ + SEQAN_TRY + { + std::stringstream strm; + strm << value; + + // clear old values + me.defaultValue.clear(); + + // add defaultValue + me.defaultValue.push_back(strm.str()); + + // check if all constraints are satisfied + _checkValue(me, strm.str()); + } + SEQAN_CATCH(ParseError & ex) + { + SEQAN_FAIL("Default value does not satisfy the restrictions:\n %s", ex.what()); + } +} + +// ---------------------------------------------------------------------------- +// Function addDefaultValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#addDefaultValue + * @headerfile + * @brief Adds/appends a new value to the list of default values. + * + * @signature void setDefaultValue(option, v); + * + * @param[in,out] option The ArgParseOption to appen the default value for. + * @param[in] v The value to append, (any type that can be streamed into an std::stringstream). + * + * @section Remarks + * + * This function does not check any length restrictions for this value. + */ + + +template +inline void addDefaultValue(ArgParseOption & me, const TValue & value) +{ + SEQAN_TRY + { + std::stringstream strm; + strm << value; + + // add defaultValue + me.defaultValue.push_back(strm.str()); + + // check if all constraints are satisfied + _checkValue(me, strm.str(), me.defaultValue.size() - 1); + } + SEQAN_CATCH(ParseError & ex) + { + SEQAN_FAIL("Default value does not satisfy the restrictions:\n %s", ex.what()); + } +} + +// ---------------------------------------------------------------------------- +// Function setRequired() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#setRequired + * @headerfile + * @brief Sets whether or not the option is mandatory. + * + * @signature void setRequired(option, required); + * + * @param[in,out] option The ArgParseOption to modify. + * @param[in] required Flag whether the option is mandatory (bool). + * + * By default, options are not mandatory. + */ + +inline void setRequired(ArgParseOption & me, bool required) +{ + me._isRequired = required; +} + +// ---------------------------------------------------------------------------- +// Function getArgumentLabel() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#getArgumentLabel + * @headerfile + * @brief Returns the argument label. + * + * @signature std::string getArgumentLabel(option); + * + * @param[in] option The ArgParseOption object to query. + * + * @return std::string The argument label string. + */ + +inline std::string const getArgumentLabel(ArgParseOption const & me) +{ + if (isFlagOption(me)) + return ""; + else + return getArgumentLabel(static_cast(me)); +} + +// ---------------------------------------------------------------------------- +// Function getOptionName() [ArgParseOption] +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#getOptionName + * @headerfile + * @brief Returns the name of the ArgParseOption in a well-formatted way. + * + * @signature std::string getOptionName(option); + * + * @param[in] option The ArgParseOption object to query. + * + * @return std::string The option name string. + */ + +inline std::string getOptionName(ArgParseOption const & me) +{ + std::stringstream stream; + + stream << (empty(me.shortName) ? "" : "-"); + stream << me.shortName; + stream << ((empty(me.shortName) || empty(me.longName) ? "" : ", ")); + if (!empty(me.longName)) + { + stream << "--"; + stream << me.longName; + } + return stream.str(); +} + +// ---------------------------------------------------------------------------- +// Function write() [ArgParseOption] +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgParseOption#write + * @headerfile + * @brief Writes the basic informationa bout the ArgParseOption to the provided stream. + * + * @signature void write(stream, option); + * + * @param[in,out] stream The @link StreamConcept stream @endlink to write to. + * @param[out] option The ArgParseOption object to write to stream. + */ + +template +inline void write(TStream & target, ArgParseOption const & me) +{ + writeValue(target, '\t'); + write(target, getOptionName(me)); + writeValue(target, '\t'); + writeValue(target, '\t'); + write(target, me._helpText); +} + +// ---------------------------------------------------------------------------- +// operator<<() [ArgParseOption] +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): We need to work out a consistent scheme with operator<<(). + +template +inline TStream & operator<<(TStream & target, ArgParseOption const & source) +{ + typename DirectionIterator::Type it = directionIterator(target, Output()); + write(it, source); + return target; +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_OPTION_H_ diff --git a/seqan/arg_parse/arg_parse_parse.h b/seqan/arg_parse/arg_parse_parse.h new file mode 100644 index 0000000..5afe27a --- /dev/null +++ b/seqan/arg_parse/arg_parse_parse.h @@ -0,0 +1,395 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_PARSE_H_ +#define SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_PARSE_H_ + +#include +#include +#include +#include + +namespace seqan { + +// ---------------------------------------------------------------------------- +// Function parse() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#parse + * @headerfile + * @brief Parse command line parameters. + * + * @signature TResult parse(parser, argc, argv[, outStream[, errStream]]); + * + * @param[in,out] parser The ArgumentParser to use for parsing and for storing parse results. + * @param[in] argc The number of arguments (int). + * @param[in] argv The arguments (const char * argv[]). + * @param[in,out] outStream The std::ostream to use for output. + * @param[in,out] errStream The std::ostream to use for error output. + * + * @return TResult The parse result, of type @link ArgumentParser::ParseResult @endlink. + * + * This function must be called before retrieving any options or arguments from the parser. + */ + +// Helper class for parsing command line arguments. +// +// Putting things into its a class allows us to structure the parsing in a fine way. + +template +class ArgumentParserHelper_ +{ +public: + typedef ArgumentParser::TArgumentMapSize TArgumentPosition; + + // Reference to the ArgumentParser to parse for. + ArgumentParser & parser; + // The argc and argv from the main() method. + int argc; + TChar ** argv; + + // The parser's state is stored in the following variables. + + // The special argument "--" is ignored as an option and only arguments can follow. The following flag holds the + // state that this token was seen. + bool seenDashDash; + // The index of the current positional argument. + TArgumentPosition currentArgument; + + ArgumentParserHelper_(ArgumentParser & parser, int argc, TChar * argv[]) + : parser(parser), argc(argc), argv(argv), seenDashDash(false), currentArgument(0) + {} + + void reset() + { + seenDashDash = false; + currentArgument = 0; + } + + // Perform the argument parsing. + void parseArgs() + { + reset(); // reset state + + // Parse binary name from command line if it was not set. + if (empty(getAppName(parser))) + _parseAppName(parser, argv[0]); + + for (int argi = 1; argi < argc; ++argi) + { + // after "--" ever arg is treated as argument (not as option), e.g. "rm -rf -- --file-name" + // "-" is a treated as argument as for a filename arguments it represents stdin + // everything else that begins with "-" is an option + + size_t argLen = strlen(argv[argi]); + if (seenDashDash || argLen == 0 || ((argv[argi][0] != '-') || (argLen == 1))) // + // Handle as position argument if we have seen "--" or does not start with dash. + handleArgument(argv[argi]); + else if (strcmp(argv[argi], "--") == 0) + // If this is "--" then ignore the argument itself but set the seen flag for it. + seenDashDash = true; + else + // This is an option. + handleOption(argi, argv[argi]); + } + } + +private: + + // Handle the given string as an argument. + // + // Throw ParseError in case of too many arguments. + void handleArgument(char const * argStr) + { + // Check whether we have the largest number of allowed arguments already. + if (parser.argumentList.size() <= currentArgument) + SEQAN_THROW(ParseError("Too many arguments!")); + + ArgParseArgument & argument = getArgument(parser, currentArgument); + _assignArgumentValue(argument, argStr); + + if (!isListArgument(argument)) + ++currentArgument; + } + + // Handle the given string as an option. + // + // Throw InvalidOption if there is a formal error (== "-") or invalid option naparser. + // + // Throw MissingArgument in case of --key=value option but the option requires multiple values. + void handleOption(int & argi, std::string arg) + { + if (arg == "-") + SEQAN_THROW(InvalidOption("-")); + + if (arg[1] == '-') + handleLongOption(argi, arg); + else + handleShortOption(argi, arg); + } + + // Handle the given string as a long option. + void handleLongOption(int & argi, std::string const & arg) + { + // We will store the option name and the value in these variables. + std::string longOpt = arg; + std::string val; + + // Split option in case of --key=value format. + size_t t = arg.find('='); + if (t != std::string::npos) // is --key=value option + { + val = arg.substr(t + 1); + longOpt = arg.substr(0, t); + } + longOpt.erase(0, 2); + + // Guard against invalid option names. + if (!hasOption(parser, longOpt)) + SEQAN_THROW(InvalidOption(longOpt)); + + // Parse out the values for the option from the command line arguments. + ArgParseOption & opt = getOption(parser, longOpt); + if (t != std::string::npos) // was --key=value option + { + // We can only assign one value in this case. If the option expected more than one value then this is an + // error. + if (numberOfAllowedValues(opt) != 1) + SEQAN_THROW(MissingArgument(longOpt)); + // If everything is fine then we can assign the value to the option. + _assignArgumentValue(opt, val); + } + else if (isFlagOption(opt)) + { + // Handling flag options is simple. + _assignArgumentValue(opt, "true"); + } + else + { + // If we reach here, we have a --key value option and might require multiple values. + + // Guard against missing values. + if (argi + (int)numberOfAllowedValues(opt) >= argc) + SEQAN_THROW(MissingArgument(longOpt)); + // We have sufficient values, get them from argv and assign them to the option. + for (int t = 0; t < (int)numberOfAllowedValues(opt); ++t) + _assignArgumentValue(opt, argv[++argi]); + } + } + + // Handle the given string as a short option. + void handleShortOption(int & argi, std::string const & arg) + { + // Parse out the short option. This is made complicated because the user can concatenate multiple short options + // into one. NB: we do not check for and warn about possible ambiguities. + // + // We enumerate the possible option names starting from left to right, then sorted descendingly by length. + // Boolean options can be squished together in this way without further restrictions. If the option requires + // additional arguments then it has to be the last in the short options. + + for (unsigned s = 1; s < arg.size(); ++s) + { + unsigned e = arg.size(); + for (; s < e; --e) + { + if (hasOption(parser, arg.substr(s, e - s))) + { + ArgParseOption & opt = getOption(parser, arg.substr(s, e - s)); + s = --e; // advance in squished options; s > e if at end + + // Flag options are easy to handle. + if (isFlagOption(opt)) + { + _assignArgumentValue(opt, "true"); + continue; + } + + // Handle option with values. + if (e < arg.size() - 1) + { + std::stringstream what; + what << "invalid combination of arguments -- " << arg << std::endl; + SEQAN_THROW(ParseError(what.str())); + } + + // Handle the case of too few options. + if (argi + (int)numberOfAllowedValues(opt) >= argc) + SEQAN_THROW(MissingArgument(opt.shortName)); + + // Assign the required option value.s + for (int t = 0; t < (int)numberOfAllowedValues(opt); ++t) + _assignArgumentValue(opt, argv[++argi]); + } + } + + // No option was found. + if (s == e) + SEQAN_THROW(InvalidOption(arg.substr(s))); + } + } +}; + +// Parser driver function. +template +ArgumentParser::ParseResult parse(ArgumentParser & me, + int argc, + TChar * argv[], + std::ostream & outputStream, + std::ostream & errorStream) +{ + SEQAN_TRY + { + // Perform the parsing without any valid value checking on the argument values. + ArgumentParserHelper_ parserHelper(me, argc, argv); + parserHelper.parseArgs(); + + // Copy the file extensions from the "--${NAME}-file-ext" options to "--${NAME}". + for (unsigned i = 0; i < me.optionMap.size(); ++i) + { + ArgParseOption & opt = me.optionMap[i]; + std::string longExtName = opt.longName + "-file-ext"; + std::string shortExtName = opt.shortName + "-file-ext"; + if (!opt.longName.empty() && hasOption(me, longExtName)) + opt._fileExtensions = getArgumentValues(getOption(me, longExtName)); + else if (!opt.shortName.empty() && hasOption(me, shortExtName)) + opt._fileExtensions = getArgumentValues(getOption(me, longExtName)); + } + // Copy the file extensions from the "--arg-${NUM}-file-ext" options to the argument. + for (unsigned i = 0; i < me.argumentList.size(); ++i) + { + ArgParseArgument & arg = me.argumentList[i]; + std::stringstream ss; + ss << "arg-" << (i + 1) << "-file-ext"; + if (hasOption(me, ss.str())) + arg._fileExtensions = getArgumentValues(getOption(me, ss.str())); + } + + // Check all arguments for their values. + for (unsigned i = 0; i < me.optionMap.size(); ++i) + _checkValue(me.optionMap[i]); + for (unsigned i = 0; i < me.argumentList.size(); ++i) + _checkValue(me.argumentList[i]); + } + SEQAN_CATCH(ParseError & ex) + { + errorStream << getAppName(me) << ": " << ex.what() << std::endl; + return ArgumentParser::PARSE_ERROR; + } + +#ifndef SEQAN_DISABLE_VERSION_CHECK + // do version check if not turned off by the user + bool check_version = false; + getOptionValue(check_version, me, "version-check"); + + if (check_version) + { + VersionCheck app_version(toCString(me._toolDoc._name), + toCString(me._toolDoc._version), + errorStream); + std::promise appVersionProm; + me.appVersionCheckFuture = appVersionProm.get_future(); + app_version(std::move(appVersionProm)); + } +#endif // !SEQAN_DISABLE_VERSION_CHECK + + // Handle the special options. + if (hasOption(me, "version") && isSet(me, "version")) + { + printVersion(me, outputStream); + return ArgumentParser::PARSE_VERSION; + } + else if (hasOption(me, "copyright") && isSet(me, "copyright")) + { + printLongCopyright(me, outputStream); + return ArgumentParser::PARSE_COPYRIGHT; + } + else if (hasOption(me, "write-ctd") && isSet(me, "write-ctd")) + { + if (writeCTD(me)) + return ArgumentParser::PARSE_WRITE_CTD; + else + return ArgumentParser::PARSE_ERROR; + } + else if (isSet(me, "help")) + { + printHelp(me, outputStream); + return ArgumentParser::PARSE_HELP; + } + else if (isSet(me, "full-help")) + { + printHelp(me, outputStream, "txt", true); + return ArgumentParser::PARSE_HELP; + } + else if (isSet(me, "export-help")) + { + std::string format; + getOptionValue(format, me, "export-help"); + printHelp(me, outputStream, format, true); + return ArgumentParser::PARSE_EXPORT_HELP; + } + else if (argc == 1 && !(_allRequiredSet(me) && _allArgumentsSet(me))) + { + // print short help and exit + printShortHelp(me, errorStream); + return ArgumentParser::PARSE_HELP; + } + + // In case that everything is fine, we can now return OK. + if (_allRequiredSet(me) && _allArgumentsSet(me)) + return ArgumentParser::PARSE_OK; + + // Otherwise, we check which options missed values. + if (!_allRequiredSet(me)) + for (unsigned o = 0; o < length(me.optionMap); ++o) + if (!isSet(me.optionMap[o]) && isRequired(me.optionMap[o])) + errorStream << getAppName(me) << ": Missing value for option: " << getOptionName(me.optionMap[o]) << std::endl; + // and arguments + if (!_allArgumentsSet(me)) + errorStream << getAppName(me) << ": Not enough arguments were provided." << std::endl; + errorStream << "Try '" << getAppName(me) << " --help' for more information.\n"; + return ArgumentParser::PARSE_ERROR; +} + +template +ArgumentParser::ParseResult parse(ArgumentParser & me, + int argc, + TChar * argv[]) +{ + return parse(me, argc, argv, std::cout, std::cerr); +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_ARG_PARSE_ARG_PARSE_PARSE_H_ diff --git a/seqan/arg_parse/arg_parse_type_support.h b/seqan/arg_parse/arg_parse_type_support.h new file mode 100644 index 0000000..9b1192d --- /dev/null +++ b/seqan/arg_parse/arg_parse_type_support.h @@ -0,0 +1,236 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== + +// TODO(aiche): check if parts of the functionality could be merged with lexicalCast in stream module + +#ifndef SEQAN_INCLUDE_ARG_PARSE_ARG_PARSE_TYPE_SUPPRT_H_ +#define SEQAN_INCLUDE_ARG_PARSE_ARG_PARSE_TYPE_SUPPRT_H_ + +#include +#include + +#include + +namespace seqan { + + +// ========================================================================== +// Tags, Classes, Enums +// ========================================================================== + +template +struct BooleanArgumentValues_ +{ + static constexpr std::array LIST_TRUE{{"1", "ON", "TRUE", "T", "YES"}}; + static constexpr std::array LIST_FALSE{{"0", "OFF", "FALSE", "F", "NO"}}; +}; + +template +constexpr std::array BooleanArgumentValues_::LIST_TRUE; + +template +constexpr std::array BooleanArgumentValues_::LIST_FALSE; + +// ========================================================================== +// Functions +// ========================================================================== + +// ---------------------------------------------------------------------------- +// Function _tryCast() +// ---------------------------------------------------------------------------- +template +inline bool _tryCast(TTarget & dest, TString const source) +{ + std::istringstream stream(toCString(source)); + bool result = (!(stream >> dest).fail()) && (stream.rdbuf()->in_avail() == 0); + return result; +} + +template +inline bool _tryCast(bool & dst, TString const & s) +{ + // since the validValue check already verifies that the value is one of + // BooleanArgumentValues_<>::LIST_TRUE and BooleanArgumentValues_<>::LIST_FALSE, + // one only needs to check one equivalent class + std::string s_uppercase{s}; + std::transform(s.begin(), s.end(), s_uppercase.begin(), ::toupper); // allow for lowercase letters + dst = (std::find(BooleanArgumentValues_<>::LIST_TRUE.begin(), + BooleanArgumentValues_<>::LIST_TRUE.end(), + s_uppercase) + != BooleanArgumentValues_<>::LIST_TRUE.end()); + return true; +} + +// ---------------------------------------------------------------------------- +// Function _cast() +// ---------------------------------------------------------------------------- +template +inline TTarget _cast(TString const s) +{ + // We are sing additional braces here for "most vexing parse" resolution + // when enforcing default initialization also for built-in types. + TTarget dst((TTarget())); + std::istringstream stream(toCString(s)); + bool result = (!(stream >> dst).fail()) && (stream.rdbuf()->in_avail() == 0); + SEQAN_CHECK(result, "could not cast %s", toCString(s)); + return dst; +} + +// ---------------------------------------------------------------------------- +// Function _isCastable() +// ---------------------------------------------------------------------------- +template +inline bool _isCastable(TString const s) +{ + TTarget dst; + std::istringstream stream(toCString(s)); + return (!(stream >> dst).fail()) && (stream.rdbuf()->in_avail() == 0); +} + +// ---------------------------------------------------------------------------- +// Function _isDouble() +// ---------------------------------------------------------------------------- + +template +inline bool _isDouble(TString const s) +{ + return _isCastable(s); +} + +// ---------------------------------------------------------------------------- +// Function _isInt() +// ---------------------------------------------------------------------------- + +template +inline bool _isInt(TString const s) +{ + return _isCastable(s); +} + +// ---------------------------------------------------------------------------- +// Function _convertFlagValue() +// ---------------------------------------------------------------------------- + +inline bool _convertFlagValue(bool & dst, std::string const & src) +{ + dst = !empty(src) && (src != "false"); + return true; +} + +template +inline bool _convertFlagValue(TObject & /*dst*/, std::string const & /*s*/) +{ + return false; +} + +// ---------------------------------------------------------------------------- +// Function _convertArgumentValue() +// ---------------------------------------------------------------------------- + +class ArgParseArgument; +inline bool isIntegerArgument(ArgParseArgument const & me); +inline bool isInt64Argument(ArgParseArgument const & me); +inline bool isDoubleArgument(ArgParseArgument const & me); +inline bool isStringArgument(ArgParseArgument const & me); +inline bool isBooleanArgument(ArgParseArgument const & me); + +inline bool _convertArgumentValue(bool & dst, ArgParseArgument const & opt, std::string const & src) +{ + if (!isBooleanArgument(opt)) + return false; + + return _tryCast(dst, src); +} + +inline bool _convertArgumentValue(int & dst, ArgParseArgument const & opt, std::string const & src) +{ + if (!isIntegerArgument(opt)) + return false; + + return _tryCast(dst, src); +} + +inline bool _convertArgumentValue(unsigned int & dst, ArgParseArgument const & opt, std::string const & src) +{ + if (!isIntegerArgument(opt)) + return false; + + return _tryCast(dst, src); +} + +inline bool _convertArgumentValue(int64_t & dst, ArgParseArgument const & opt, std::string const & src) +{ + if (!isIntegerArgument(opt) && !isInt64Argument(opt)) + return false; + + return _tryCast(dst, src); +} + +inline bool _convertArgumentValue(uint64_t & dst, ArgParseArgument const & opt, std::string const & src) +{ + if (!isIntegerArgument(opt) && !isInt64Argument(opt)) + return false; + + return _tryCast(dst, src); +} + +inline bool _convertArgumentValue(float & dst, ArgParseArgument const & opt, std::string const & src) +{ + if (!isDoubleArgument(opt)) + return false; + + return _tryCast(dst, src); +} + +inline bool _convertArgumentValue(double & dst, ArgParseArgument const & opt, std::string const & src) +{ + if (!isDoubleArgument(opt)) + return false; + + return _tryCast(dst, src); +} + +template +inline bool _convertArgumentValue(TObject & dst, ArgParseArgument const & opt, std::string const & src) +{ + if (!isStringArgument(opt)) + return false; + + assign(dst, src); + return true; +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_ARG_PARSE_ARG_PARSE_TYPE_SUPPRT_H_ diff --git a/seqan/arg_parse/arg_parse_version_check.h b/seqan/arg_parse/arg_parse_version_check.h new file mode 100644 index 0000000..bb10cc8 --- /dev/null +++ b/seqan/arg_parse/arg_parse_version_check.h @@ -0,0 +1,480 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Svenja Mehringer +// ========================================================================== + +#ifndef SEQAN_INCLUDE_ARG_PARSE_VERSION_CHECK_H_ +#define SEQAN_INCLUDE_ARG_PARSE_VERSION_CHECK_H_ + +#include + +#include +#include +#include +#include +#include + +namespace seqan +{ + +// ========================================================================== +// Forwards +// ========================================================================== + +// NOTE(rrahn): In-file forward for function call operator. +struct VersionCheck; +inline void _checkForNewerVersion(VersionCheck &, std::promise); +inline std::string _getPath(); +constexpr const char * _getOS(); +constexpr const char * _getBitSys(); + +// ========================================================================== +// Tags, Classes, Enums +// ========================================================================== + +template +struct VersionControlTags_ +{ + static constexpr char const * const SEQAN_NAME = "seqan"; + static constexpr char const * const UNREGISTERED_APP = "UNREGISTERED_APP"; + + static constexpr char const * const MESSAGE_SEQAN_UPDATE = + "[SEQAN INFO] :: There is a newer SeqAn version available!\n" + "[SEQAN INFO] :: Please visit www.seqan.de for an update or inform the developer of this app.\n" + "[SEQAN INFO] :: If you don't want to recieve this message again set --version-check OFF\n\n"; + static constexpr char const * const MESSAGE_APP_UPDATE = + "[APP INFO] :: There is a newer version of this application available.\n" + "[APP INFO] :: If this app is developed by SeqAn, visit www.seqan.de for updates.\n" + "[APP INFO] :: If you don't want to recieve this message again set --version_check OFF\n\n"; + static constexpr char const * const MESSAGE_UNREGISTERED_APP = + "[SEQAN INFO] :: Thank you for using SeqAn!\n" + "[SEQAN INFO] :: You might want to regsiter you app for support and version check features?\n" + "[SEQAN INFO] :: Just send us an email to seqan@team.fu-berlin.de with your app name and version number.\n" + "[SEQAN INFO] :: If you don't want to recieve this message anymore set --version_check OFF\n\n"; + static constexpr char const * const MESSAGE_REGISTERED_APP_UPDATE = + "[APP INFO] :: We noticed the app version you use is newer than the one registered with us.\n" + "[APP INFO] :: Please send us an email with the new version so we can correct it (support@seqan.de)\n\n"; +}; + +template +constexpr char const * const VersionControlTags_::SEQAN_NAME; +template +constexpr char const * const VersionControlTags_::UNREGISTERED_APP; +template +constexpr char const * const VersionControlTags_::MESSAGE_SEQAN_UPDATE; +template +constexpr char const * const VersionControlTags_::MESSAGE_APP_UPDATE; +template +constexpr char const * const VersionControlTags_::MESSAGE_UNREGISTERED_APP; +template +constexpr char const * const VersionControlTags_::MESSAGE_REGISTERED_APP_UPDATE; + +struct VersionCheck +{ + // ---------------------------------------------------------------------------- + // Member Variables + // ---------------------------------------------------------------------------- + std::string _url; + std::string _name; + std::string _version = "0.0.0"; + std::string _program; + std::string _command; + std::string _path = _getPath(); + std::string _timestamp_filename; + std::ostream & errorStream; + + // ---------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------- + + VersionCheck(std::string name, + std::string const & version, + std::ostream & errorStream) : + _name{std::move(name)}, + errorStream(errorStream) + { + std::smatch versionMatch; +#if defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_) + _timestamp_filename = _path + "/" + _name + "_usr.timestamp"; +#else + _timestamp_filename = _path + "/" + _name + "_dev.timestamp"; +#endif + if (!version.empty() && + std::regex_search(version, versionMatch, std::regex("^([[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+).*"))) + { + _version = versionMatch.str(1); // in case the git revision number is given take only version number + } + _url = static_cast("http://seqan-update.informatik.uni-tuebingen.de/check/SeqAn_") + _getOS() + _getBitSys() + _name + "_" + _version; + _getProgram(); + _updateCommand(); + } + + // ---------------------------------------------------------------------------- + // Member Functions + // ---------------------------------------------------------------------------- + +#if defined(STDLIB_VS) + void _getProgram() + { + _program = "powershell.exe -NoLogo -NonInteractive -Command \"& {Invoke-WebRequest -erroraction 'silentlycontinue' -OutFile"; + } +#else // Unix based platforms. + void _getProgram() + { + // ask if system call for version or help is successfull + if (!system("wget --version > /dev/null 2>&1")) + _program = "wget -q -O"; + else if (!system("curl --version > /dev/null 2>&1")) + _program = "curl -o"; +#ifndef __linux // ftp call does not work on linux + else if (!system("which ftp > /dev/null 2>&1")) + _program = "ftp -Vo"; +#endif + else + _program.clear(); + } +#endif // defined(STDLIB_VS) + + void _updateCommand() + { + if (!_program.empty()) + { + _command = _program + " " + _path + "/" + _name + ".version " + _url; +#if defined(STDLIB_VS) + _command = _command + "; exit [int] -not $?}\" > nul 2>&1"; +#else + _command = _command + " > /dev/null 2>&1"; +#endif + } + } + + inline void operator()(std::promise versionCheckProm) + { + _checkForNewerVersion(*this, std::move(versionCheckProm)); + } +}; + +// ========================================================================== +// Metafunctions +// ========================================================================== + +// ========================================================================== +// Functions +// ========================================================================== + +// ---------------------------------------------------------------------------- +// Function setURL() +// ---------------------------------------------------------------------------- + +inline void setURL(VersionCheck & me, std::string url) +{ + std::swap(me._url, url); + me._updateCommand(); +} + +// ---------------------------------------------------------------------------- +// Function _getOS() +// ---------------------------------------------------------------------------- + +constexpr const char * _getOS() +{ + //get system information +#ifdef __linux + return "Linux"; +#elif __APPLE__ + return "MacOS"; +#elif defined(STDLIB_VS) + return "Windows"; +#elif __FreeBSD__ + return "FreeBSD"; +#elif __OpenBSD__ + return "OpenBSD"; +#else + return "unknown"; +#endif +} + +// ---------------------------------------------------------------------------- +// Function _getBitSys() +// ---------------------------------------------------------------------------- + +constexpr const char * _getBitSys() +{ +#if SEQAN_IS_32_BIT + return "_32_"; +#else + return "_64_"; +#endif +} + +// ---------------------------------------------------------------------------- +// Function _checkWritability() +// ---------------------------------------------------------------------------- + +#if defined(STDLIB_VS) +inline bool _checkWritability(std::string const & path) +{ + DWORD ftyp = GetFileAttributesA(path.c_str()); + if (ftyp == INVALID_FILE_ATTRIBUTES || !(ftyp & FILE_ATTRIBUTE_DIRECTORY)) + { + if (!CreateDirectory(path.c_str(), NULL)) + return false; + } + + HANDLE dummyFile; // check writablity by trying to create a file in GENERIC_WRITE mode + std::string fileName(path + "/dummy.txt"); + dummyFile = CreateFile(fileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if (dummyFile == INVALID_HANDLE_VALUE) + return false; + + CloseHandle(dummyFile); + bool successful_deletion = DeleteFile(fileName.c_str()); + SEQAN_ASSERT(successful_deletion); + if (!successful_deletion) + return false; + + return true; +} +#else +inline bool _checkWritability(std::string const & path) +{ + struct stat d_stat; + if (stat(path.c_str(), &d_stat) < 0) + { + // try to make dir + std::string makeDir("mkdir -p " + path); + if (system(makeDir.c_str())) + return false; // could not create home dir + + if (stat(path.c_str(), &d_stat) < 0) // repeat stat + return false; + } + + if (!(d_stat.st_mode & S_IWUSR)) + return false; // dir not writable + + return true; +} +#endif + +// ---------------------------------------------------------------------------- +// Function _getPath() +// ---------------------------------------------------------------------------- + +inline std::string _getPath() +{ + std::string path; +#if defined(STDLIB_VS) + path = std::string(getenv("UserProfile")) + "/.config/seqan"; +#else + path = std::string(getenv("HOME")) + "/.config/seqan"; +#endif + + // check if user has permission to write to home path + if (!_checkWritability(path)) + { +#if defined(STDLIB_VS) + TCHAR tmp_path [MAX_PATH]; + if (GetTempPath(MAX_PATH, tmp_path) != 0) + { + path = tmp_path; + } + else + { //GetTempPath() returns 0 on failure + path.clear(); + } +# else // unix + path = "/tmp"; +#endif + } + return path; +} + +// ---------------------------------------------------------------------------- +// Function _getFileTimeDiff() +// ---------------------------------------------------------------------------- + +inline double _getFileTimeDiff(VersionCheck const & me) +{ + double curr = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + std::ifstream timestamp_file; + timestamp_file.open(me._timestamp_filename.c_str()); + + if (timestamp_file.is_open()) + { + std::string str_time; + std::getline(timestamp_file, str_time); + timestamp_file.close(); + double d_time; + lexicalCast(d_time, str_time); + return curr - d_time; + } + return curr; +} + +// ---------------------------------------------------------------------------- +// Function _getNumbersFromString() +// ---------------------------------------------------------------------------- + +inline String _getNumbersFromString(std::string const & str) +{ + String numbers; + StringSet set; + strSplit(set, str, EqualsChar<'.'>(), false); + for (auto & num : set) + { + appendValue(numbers, lexicalCast(num)); + } + return numbers; +} + +// ---------------------------------------------------------------------------- +// Function _readVersionString() +// ---------------------------------------------------------------------------- + +inline void _readVersionStrings(std::vector & versions, std::string const & version_file) +{ + std::ifstream myfile; + myfile.open(version_file.c_str()); + std::string app_version; + std::string seqan_version; + if (myfile.is_open()) + { + std::getline(myfile, app_version); // get first line which should only contain the version number of the app + +#if !defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_) + if (app_version == VersionControlTags_<>::UNREGISTERED_APP) + versions[0] = app_version; +#endif // !defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_) + + if (std::regex_match(app_version, std::regex("^[[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+$"))) + versions[0] = app_version; + + std::getline(myfile, seqan_version); // get second line which should only contain the version number of seqan + + if (std::regex_match(seqan_version, std::regex("^[[:digit:]]+\\.[[:digit:]]+\\.[[:digit:]]+$"))) + versions[1] = seqan_version; + + myfile.close(); + } +} + +// ---------------------------------------------------------------------------- +// Function _callServer() +// ---------------------------------------------------------------------------- + +inline void _callServer(VersionCheck const me, std::promise prom) +{ + // update timestamp + std::ofstream timestamp_file(me._timestamp_filename.c_str()); + if (timestamp_file.is_open()) + { + timestamp_file << std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + timestamp_file.close(); + } + + // system call + // http response is stored in a file '.config/seqan/{app_name}_version' + if (system(me._command.c_str())) + prom.set_value(false); + else + prom.set_value(true); +} + +// ---------------------------------------------------------------------------- +// Function checkForNewerVersion() +// ---------------------------------------------------------------------------- + +inline void _checkForNewerVersion(VersionCheck & me, std::promise prom) +{ + if (me._path.empty()) // neither home dir nor temp dir are writable + { + prom.set_value(false); + return; + } + + std::string version_filename(me._path + "/" + me._name + ".version"); + double min_time_diff(86400); // one day = 86400 seonds + double file_time_diff(_getFileTimeDiff(me)); // time difference in seconds + + if (file_time_diff < min_time_diff) + { + prom.set_value(false); // only check for newer version once a day + return; + } + + std::vector str_server_versions{"", ""}; + _readVersionStrings(str_server_versions, version_filename); + +#if !defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_) // only check seqan version in debug or testing mode + if (!str_server_versions[1].empty()) // seqan version + { + std::string seqan_version = std::to_string(SEQAN_VERSION_MAJOR) + "." + + std::to_string(SEQAN_VERSION_MINOR) + "." + + std::to_string(SEQAN_VERSION_PATCH); + Lexical<> version_comp(_getNumbersFromString(seqan_version), _getNumbersFromString(str_server_versions[1])); + + if (isLess(version_comp)) + me.errorStream << VersionControlTags_<>::MESSAGE_SEQAN_UPDATE; + } + if (str_server_versions[0] == VersionControlTags_<>::UNREGISTERED_APP) + me.errorStream << VersionControlTags_<>::MESSAGE_UNREGISTERED_APP; +#endif + + if (!str_server_versions[0].empty() & !(str_server_versions[0] == VersionControlTags_<>::UNREGISTERED_APP)) // app version + { + Lexical<> version_comp(_getNumbersFromString(me._version), _getNumbersFromString(str_server_versions[0])); + +#if defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_) // only check app version in release or testing mode + if (isLess(version_comp)) + me.errorStream << VersionControlTags_<>::MESSAGE_APP_UPDATE; +#endif // defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_) + +#if !defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_) // only notify developer that app version should be updated on server + if (isGreater(version_comp)) + me.errorStream << VersionControlTags_<>::MESSAGE_REGISTERED_APP_UPDATE; +#endif // !defined(NDEBUG) || defined(SEQAN_TEST_VERSION_CHECK_) + } + + if (me._program.empty()) + { + prom.set_value(false); + return; + } + + // launch a seperate thread to not defer runtime. + std::thread(_callServer, me, std::move(prom)).detach(); +} + +} // namespace seqan +#endif //SEQAN_INCLUDE_ARG_PARSE_VERSION_CHECK_H_ diff --git a/seqan/arg_parse/argument_parser.h b/seqan/arg_parse/argument_parser.h new file mode 100644 index 0000000..92467a3 --- /dev/null +++ b/seqan/arg_parse/argument_parser.h @@ -0,0 +1,1192 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== + +#ifndef SEQAN_INCLUDE_ARG_PARSE_ARGUMENT_PARSER_H_ +#define SEQAN_INCLUDE_ARG_PARSE_ARGUMENT_PARSER_H_ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace seqan { + +// ========================================================================== +// Forwards +// ========================================================================== + +// friend declaration to make addOption() and hideOption() available +// in ArgumentParser::init() +class ArgumentParser; +class ArgParseOption; +void addOption(ArgumentParser & me, ArgParseOption const & opt); +void hideOption(ArgumentParser & me, std::string const & name, bool hide); +void setValidValues(ArgumentParser & me, std::string const & name, std::string const & values); +template +void setDefaultValue(ArgumentParser & me, std::string const & name, const TValue & value); + +// Required in addOption() and addArgument(). +inline void hideOption(ArgumentParser & me, std::string const & name, bool hide = true); +inline ArgParseOption & getOption(ArgumentParser & me, std::string const & name); +inline void setValidValues(ArgumentParser & me, std::string const & name, std::vector const & values); +inline ArgParseArgument & getArgument(ArgumentParser & me, unsigned position); + +// ========================================================================== +// Tags, Classes, Enums +// ========================================================================== + +/*! + * @class ArgumentParser + * @headerfile + * @brief Parse the command line. + * + * @signature class ArgumentParser; + * + * Options are stored as @link ArgParseOption @endlink and @link ArgParseArgument @endlink objects. + * + * @section Remarks + * + * See the documentation of @link ToolDoc @endlink on how to format text. Wherever possible, formatting is added + * automatically for you. You have to use formatting in the following places: (1) usage lines, (2) option help texts, + * (3) description and additional text sections. + * + * @section Examples + * + * The following gives a simple example of how to use the ArgumentParser class. + * + * @include demos/dox/arg_parse/argument_parser.cpp + * + * @code{.console} + * $ demo_arg_parse_argument_parser in.fa out.txt --id 0 + * Built target seqan_core + * Built target demo_arg_parse + * Verbose: off + * Identity: 0 + * Input-File: in.fa + * Output-File: out.txt + * @endcode + * + * @see ArgParseArgument + * @see ArgParseOption + * @see ToolDoc + */ + +/*! + * @fn ArgumentParser::ArgumentParser + * @brief Constructor + * + * @signature ArgumentParser::ArgumentParser([appName]); + * + * @param[in] appName The name of the application (std::string), defaults to argv[0]. + */ + +/*! + * @enum ArgumentParser::ParseResult + * @brief Argument parsing result. + * + * @signature enum ArgumentParser::ParseResult; + * + * @val ArgumentParser::ParseResult ArgumentParser::PARSE_OK; + * @brief Parsing the program's arguments was successful and no builtin command was triggered. + * + * @val ArgumentParser::ParseResult ArgumentParser::PARSE_ERROR; + * @brief There were errors parsing the arguments. + * + * @val ArgumentParser::ParseResult ArgumentParser::PARSE_HELP; + * @brief Parsing was successful, built-in --help or --full-help option was used. + * + * @val ArgumentParser::ParseResult ArgumentParser::PARSE_VERSION; + * @brief Parsing was successful, built-in --version option was used. + * + * @val ArgumentParser::ParseResult ArgumentParser::PARSE_COPYRIGHT; + * @brief Parsing was successful, built-in --copyright option was used. + * + * @val ArgumentParser::ParseResult ArgumentParser::PARSE_WRITE_CTD; + * @brief Parsing was successful, built-in --write-ctd option was used. + * + * @val ArgumentParser::ParseResult ArgumentParser::PARSE_EXPORT_HELP; + * @brief Parsing was successful, built-in --export-help option was used. + */ + +class ArgumentParser +{ +public: + + // ---------------------------------------------------------------------------- + // Enum ParseResult + // ---------------------------------------------------------------------------- + + // will be used as return value of parse(..) to indicate whether parsing worked + enum ParseResult + { + PARSE_OK, + PARSE_ERROR, + PARSE_HELP, + PARSE_VERSION, + PARSE_COPYRIGHT, + PARSE_WRITE_CTD, + PARSE_EXPORT_HELP + }; + + // ---------------------------------------------------------------------------- + // Class Typedefs + // ---------------------------------------------------------------------------- + + typedef std::vector TOptionMap; + typedef std::vector TArgumentMap; + typedef Size::Type TOptionMapSize; + typedef Size::Type TArgumentMapSize; + + typedef std::map TStringMap; + typedef std::vector TValueMap; + + // ---------------------------------------------------------------------------- + // Mapping of option names to options + // ---------------------------------------------------------------------------- + + TStringMap shortNameMap; + TStringMap longNameMap; + TOptionMap optionMap; + TArgumentMap argumentList; + + // ---------------------------------------------------------------------------- + // Documentation Members + // ---------------------------------------------------------------------------- + + ToolDoc _toolDoc; // the tool doc for all user specified + // text + std::vector _description; // the description which we need to + // separate to put it on top of the rest + std::vector _usageText; // the usage lines as strings, to avoid + // interference with the rest of the doc + + std::future appVersionCheckFuture; + // ---------------------------------------------------------------------------- + // Function init() + // ---------------------------------------------------------------------------- + + void init() + { + addOption(*this, ArgParseOption("h", "help", "Display the help message.")); + addOption(*this, ArgParseOption("hh", "full-help", "Display the help message with advanced options.")); + hideOption(*this, "full-help", true); // hidden by default + + // hidden flags used for export of man pages and ctd formats + addOption(*this, ArgParseOption("", + "write-ctd", + "Exports the app's interface description to a .ctd file.", + ArgParseArgument::OUTPUT_FILE)); + hideOption(*this, "write-ctd", true); + + addOption(*this, ArgParseOption("", + "export-help", + "Export help to a format. One of {'html', 'man', 'txt'}.", + ArgParseArgument::STRING, + "FORMAT")); + hideOption(*this, "export-help", true); + setValidValues(*this, "export-help", "html man txt"); + +#ifndef SEQAN_DISABLE_VERSION_CHECK + addOption(*this, ArgParseOption("", + "version-check", + "Turn this option off to disable version update notifications of the application. ", + ArgParseArgument::BOOL)); +#ifdef SEQAN_VERSION_CHECK_OPT_IN + setDefaultValue(*this, "version-check", false); +#else // Make version update opt out. + setDefaultValue(*this, "version-check", true); +#endif // SEQAN_VERSION_CHECK_OPT_IN +#endif // !SEQAN_DISABLE_VERSION_CHECK + } + + // ---------------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------------- + + ArgumentParser() + { + init(); + } + + ArgumentParser(std::string const & _appName) + { + setName(_toolDoc, _appName); + init(); + } + + ~ArgumentParser() + { + // wait for another 3 seconds + if (appVersionCheckFuture.valid()) + appVersionCheckFuture.wait_for(std::chrono::seconds(3)); + } + +}; + +// ========================================================================== +// Metafunctions +// ========================================================================== + +// ========================================================================== +// Functions +// ========================================================================== + +// ---------------------------------------------------------------------------- +// Function hasOption() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#hasOption + * @headerfile + * @brief Query whether a certain option is registered in the parser. + * + * @signature bool hasOption(parser, name); + * + * @param[in] parser The ArgumentParser to query. + * @param[in] name The name to query for (std::string). + * + * @return bool true if there is such an option, false otherwise. + */ + +inline bool hasOption(ArgumentParser const & me, std::string const & name) +{ + return hasKey(me.shortNameMap, name) || hasKey(me.longNameMap, name); +} + +// ---------------------------------------------------------------------------- +// Function addOption() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addOption + * @headerfile + * @brief Adds an @link ArgParseOption @endlink to an ArgumentParser. + * + * @signature void addOption(parser, option); + * + * @param[in,out] parser The ArgumentParser to add the option to. + * @param[in] option The ArgParseOption to add to parser. + */ + +inline void _copyValidValuesToFileExt(ArgumentParser & me, std::string const & name) +{ + // Copy valid values, remove leading dots. + ArgParseOption & option = getOption(me, name); + if (isInputFileArgument(option) || isOutputFileArgument(option)) + { + std::string longName = option.longName.empty() ? option.shortName : option.longName; + longName += "-file-ext"; + std::vector validValues = option.validValues; + for (unsigned i = 0; i < length(validValues); ++i) + if (!validValues[i].empty() && validValues[i][0] == '.') + validValues[i].erase(0, 1); + setValidValues(me, longName, validValues); + } +} + +inline void addOption(ArgumentParser & me, ArgParseOption const & opt) +{ + // check if an option with the same identifiers was already registered + SEQAN_CHECK(!hasOption(me, opt.shortName), "There already is an option with the name %s!", toCString(opt.shortName)); + SEQAN_CHECK(!hasOption(me, opt.longName), "There already is an option with the name %s!", toCString(opt.longName)); + + // finally append the option + appendValue(me.optionMap, opt); + + if (!empty(opt.shortName)) + me.shortNameMap.insert(std::make_pair(opt.shortName, length(me.optionMap) - 1)); + if (!empty(opt.longName)) + me.longNameMap.insert(std::make_pair(opt.longName, length(me.optionMap) - 1)); + + // handle the case of input and output option: add a string option --${name}-file-ext. + if (isInputFileArgument(opt) || isOutputFileArgument(opt)) + { + std::string longName = opt.longName.empty() ? opt.shortName : opt.longName; + longName += "-file-ext"; + std::string helpText = "Override file extension for --"; + helpText += opt.longName; + + // Add option, copy list argument, number of allowed values. + addOption(me, ArgParseOption("", longName, helpText, ArgParseOption::STRING, "EXT", + isListArgument(opt), numberOfAllowedValues(opt))); + getOption(me, longName.c_str()).tags.push_back("file-ext-override"); + getOption(me, longName.c_str()).tags.push_back("gkn-ignore"); + // Hide option. + hideOption(me, longName); + // Copy valid values, remove leading dots. + _copyValidValuesToFileExt(me, opt.longName); + } +} + +// ---------------------------------------------------------------------------- +// Function addArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addArgument + * @headerfile + * @brief Adds an @link ArgParseArgument @endlink to an ArgumentParser. + * + * @signature void addArgument(parser, arg); + * + * @param[in,out] parser The ArgumentParser to add the argument to. + * @param[in] arg The ArgParseArgument to add to parser. + */ + +inline void _copyValidValuesToFileExt(ArgumentParser & me, unsigned no) +{ + // Copy valid values, remove leading dots. + ArgParseArgument & arg = getArgument(me, no); + if (isInputFileArgument(arg) || isOutputFileArgument(arg)) + { + std::stringstream longNameSS; + longNameSS << "arg-" << (no + 1) << "-file-ext"; + std::string longName = longNameSS.str(); + std::vector validValues = arg.validValues; + for (unsigned i = 0; i < length(validValues); ++i) + if (!validValues[i].empty() && validValues[i][0] == '.') + validValues[i].erase(0, 1); + setValidValues(me, longName, validValues); + } +} + +inline void addArgument(ArgumentParser & me, ArgParseArgument const & arg) +{ + // check previous arguments + // .. lists can only be last argument + if (!me.argumentList.empty()) + { + SEQAN_CHECK(!isListArgument(me.argumentList[me.argumentList.size() - 1]), + "You cannot add an additional argument after a list argument."); + } + + // check current argument + // .. arguments should not have default values + SEQAN_CHECK(arg.defaultValue.empty(), "Arguments cannot have default values."); + SEQAN_CHECK(arg._numberOfValues == 1, "n-Tuple of arguments are not supported."); + + me.argumentList.push_back(arg); + + // handle the case of input and output option: add a string option --${name}-file-ext. + if (isInputFileArgument(arg) || isOutputFileArgument(arg)) + { + std::stringstream longNameSS; + longNameSS << "arg-" << me.argumentList.size() << "-file-ext"; + std::string longName = longNameSS.str(); + std::stringstream helpTextSS; + helpTextSS << "Override file extension for argument " << me.argumentList.size(); + std::string helpText = helpTextSS.str(); + + // Add option, copy list argument, number of allowed values. + addOption(me, ArgParseOption("", longName, helpText, ArgParseOption::STRING, "EXT", + isListArgument(arg), numberOfAllowedValues(arg))); + getOption(me, longName.c_str()).tags.push_back("file-ext-override"); + getOption(me, longName.c_str()).tags.push_back("gkn-ignore"); + // Hide option. + hideOption(me, longName); + // Copy valid values, remove leading dots. + _copyValidValuesToFileExt(me, me.argumentList.size() - 1); + } +} + +// ---------------------------------------------------------------------------- +// Function _getOptionIndex() +// ---------------------------------------------------------------------------- +// note that it is assumed that the option exists if this method is called + +inline ArgumentParser::TOptionMapSize _getOptionIndex(ArgumentParser const & me, + std::string const & name) +{ + ArgumentParser::TOptionMapSize option_index; + if (me.shortNameMap.find(name) != me.shortNameMap.end()) + { + option_index = me.shortNameMap.find(name)->second; + } + else + { + option_index = me.longNameMap.find(name)->second; + } + return option_index; +} + +// ---------------------------------------------------------------------------- +// Function getOption() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getOption + * @headerfile + * @brief Returns a reference to the specified option. + * + * @signature TOption getOption(parser, name); + * + * @param[in] parser The parser to query. + * @param[in] name The short or long name of the option (std::string). + * + * @return TOption Reference to the @link ArgParseOption @endlink with the given short or long name. + */ + +inline ArgParseOption & getOption(ArgumentParser & me, std::string const & name) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + return me.optionMap[_getOptionIndex(me, name)]; +} + +inline ArgParseOption const & getOption(ArgumentParser const & me, std::string const & name) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + return me.optionMap[_getOptionIndex(me, name)]; +} + +// ---------------------------------------------------------------------------- +// Function setRequired() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setRequired + * @headerfile + * @brief Sets whether or not the option with the givne name is mandatory. + * + * @signature void setRequired(parser, name[, required]). + * + * @param[in,out] parser The ArgumentParser to set the flag of. + * @param[in] name The short or long name of the option (std::string). + * @param[in] required Whether or not the option is required (bool, default to true). + */ + +inline void setRequired(ArgumentParser & me, std::string const & name, bool required = true) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + setRequired(getOption(me, name), required); +} + +// ---------------------------------------------------------------------------- +// Function hideOption() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#hideOption + * @headerfile + * @brief Hides the ArgParseOption with the given name. + * + * @signature void hideOption(parser, name[, hide]). + * + * @param[in,out] parser The ArgParseOption to the the hidden flag of. + * @param[in] name The short or long name of the option to modify. + * @param[in] hide Whether or not to hide the flag (bool, defaults to true). + */ + +inline void hideOption(ArgumentParser & me, std::string const & name, bool hide) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + hideOption(getOption(me, name), hide); +} + +// ---------------------------------------------------------------------------- +// Function setAdvanced() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setAdvanced + * @headerfile + * @brief Sets whether or not the option with the givne name is advanced. + * + * @signature void setAdvanced(parser, name[, required]). + * + * @param[in,out] parser The ArgumentParser to set the flag of. + * @param[in] name The short or long name of the option (std::string). + * @param[in] required Whether or not the option is required (bool, default to true). + */ + +inline void setAdvanced(ArgumentParser & me, std::string const & name, bool advanced = true) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + setAdvanced(getOption(me, name), advanced); + // make sure the full-help options is visible so advanced options can be shown + if (advanced) + hideOption(me, "full-help", false); +} + +// ---------------------------------------------------------------------------- +// Function getArgument() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getArgument + * @headerfile + * @brief Returns a reference to the given positional argument. + * + * @signature TArgument getArgument(parser, pos); + * + * @param[in] parser The ArgumentParser to query. + * @param[in] pos The position of the argument to return (unsigned, starting at 0). + * + * @return TArgument Reference to the @link ArgParseArgument @endlink with the given position. + */ + +inline ArgParseArgument & getArgument(ArgumentParser & me, unsigned position) +{ + SEQAN_CHECK(position < me.argumentList.size(), + "ArgumentParser: Only %d arguments available", me.argumentList.size()); + return me.argumentList[position]; +} + +inline ArgParseArgument const & getArgument(ArgumentParser const & me, unsigned position) +{ + SEQAN_CHECK(position < me.argumentList.size(), + "ArgumentParser: Only %d arguments available", me.argumentList.size()); + return me.argumentList[position]; +} + +// ---------------------------------------------------------------------------- +// Function isSet() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#isSet + * @headerfile + * @brief Query whether an option was set on the command line. + * + * @signature bool isSet(parser, name); + * + * @param[in] parser The ArgumentParser to query. + * @param[in] name The short or long name of the option (std::string). + * + * @return bool Whether or not the option was set on the command line or not. + */ + +inline bool isSet(ArgumentParser const & me, std::string const & name) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + return isSet(getOption(me, name)); +} + +// ---------------------------------------------------------------------------- +// Function hasDefault() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#hasDefault + * @headerfile + * @brief Query whether an option has a default value. + * + * @signature bool hasDefault(parser, name); + * + * @param[in] parser The ArgumentParser to query. + * @param[in] name The short or long name of the option (std::string). + * + * @return bool Whether or not the option has a default value. + */ + +inline bool hasDefault(ArgumentParser const & me, std::string const & name) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + return hasDefault(getOption(me, name)); +} + +// ---------------------------------------------------------------------------- +// Function _allRequiredSet() +// ---------------------------------------------------------------------------- + +inline bool _allRequiredSet(ArgumentParser const & me) +{ + for (unsigned o = 0; o < length(me.optionMap); ++o) + if (!isSet(me.optionMap[o]) && isRequired(me.optionMap[o])) + return false; + + return true; +} + +// ---------------------------------------------------------------------------- +// Function _allArgumentsSet() +// ---------------------------------------------------------------------------- + +inline bool _allArgumentsSet(ArgumentParser const & me) +{ + for (unsigned a = 0; a < me.argumentList.size(); ++a) + if (!isSet(me.argumentList[a])) + return false; + + return true; +} + +// ---------------------------------------------------------------------------- +// Function getOptionValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getOptionValue + * @headerfile + * @brief Retrieve the value of an option. + * + * @signature bool getOptionValue(dest, parser, name[, pos]); + * + * @param[in] dest The variable to write the result to (the type is a template parameter and the value type of the + * option must be convertible in the type of dest for the retrieval to work, also see + * result value). + * @param[in] parser The ArgumentParser to get the value from. + * @param[in] name The short or long name of the option (std::string). + * @param[in] pos Optional position for multi-value options (unsigned, defaults to 0). + * + * @return bool true if the requested option was given on the command line and could be coverted to the type of + * dest. + */ + +template +inline bool getOptionValue(TValue & val, + ArgumentParser const & me, + std::string const & name, + unsigned argNo) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + + if (isSet(me, name) || hasDefault(me, name)) + { + if (isFlagOption(getOption(me, name))) + { + return _convertFlagValue(val, getArgumentValue(getOption(me, name), argNo)); + } + else + { + return _convertArgumentValue(val, + getOption(me, name), + getArgumentValue(getOption(me, name), argNo)); + } + } + else + { + return false; + } +} + +template +inline bool getOptionValue(TValue & val, + ArgumentParser const & me, + std::string const & name) +{ + return getOptionValue(val, me, name, 0); +} + +// ---------------------------------------------------------------------------- +// Function getOptionFileExtension() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getOptionFileExtension + * @headerfile + * @brief Retrieve the file extension of a file option. + * + * @signature std::string getOptionFileExtension(parser, name[, pos]); + * + * @param[in] parser The ArgumentParser to get the value from. + * @param[in] name The short or long name of the option (std::string). + * @param[in] pos Optional position for multi-value options (unsigned, defaults to 0). + * + * @return std::string The extension of the option. Empty if not set or no extension. + * + * @see ArgumentParser#getArgumentFileExtension + * + * @section Overriding File Extension on the Command Line + * + * For each option with type INPUT_FILE and OUTPUT_FILE, an option with the name + * ${name}-file-ext is automatically added to the ArgumentParser (where ${name} is the name + * of the original option). The extension can be overridden by specifying the argument. Thus, the user of + * the program could give the value "file.ext" to the parameter "fname" and override the extension on the + * command line to "ext2" as follows: + * + * @code{.console} + * # program_name --fname file.ext --fname-file-ext ext2 + * @endcode + */ + +inline std::string getOptionFileExtension(ArgumentParser const & me, + std::string const & name, + unsigned argNo = 0) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + + return getFileExtension(getOption(me, name), argNo); +} + +// ---------------------------------------------------------------------------- +// Function getOptionValueCount() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getOptionValueCount + * @headerfile + * @brief Query number of values stored for the specified option. + * + * @signature unsigned getOptionValueCount(parser, name); + * + * @param[in] parser The ArgumentParser to query. + * @param[in] name The short or long name of the option (string). + * + * @return unsigned The number of values for the option with the given name. + */ + +inline unsigned getOptionValueCount(ArgumentParser const & me, std::string const & name) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + return getArgumentValues(getOption(me, name)).size(); +} + +// ---------------------------------------------------------------------------- +// Function getArgumentValueCount() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getArgumentValueCount + * @headerfile + * @brief Query number of values stored for the specified argument. + * + * @signature unsigned getArgumentValueCount(parser, pos); + * + * @param[in] parser The ArgumentParser to query. + * @param[in] name The position of the argument (unsigned, 0-based). + * + * @return unsigned The number of values for the argument with the given position. + */ + +inline unsigned getArgumentValueCount(ArgumentParser const & me, unsigned argumentPosition) +{ + SEQAN_CHECK(me.argumentList.size() > argumentPosition, + "Argument Parser has only %d arguments.", + me.argumentList.size()); + return getArgumentValues(getArgument(me, argumentPosition)).size(); +} + +// ---------------------------------------------------------------------------- +// Function getArgumentValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getArgumentValue + * @headerfile + * @brief Retrieves the value of an argument given by its position. + * + * @signature bool getArgumentValue(dest, parser, pos[, no]); + * + * @param[in] dest The variable to write the result to (the type is a template parameter and the value type of the + * argument must be convertible in the type of dest for the retrieval to work, also see + * result value). + * @param[in] parser The ArgumentParser to get the value from. + * @param[in] pos The position of the argument to get the value of. + * @param[in] no Optional position for multi-value arguments (unsigned, defaults to 0). + * + * @return bool true if the retrieval was successful, false otherwise. + */ + +template +inline bool getArgumentValue(TValue & value, + ArgumentParser const & me, + unsigned argumentPosition, + unsigned argNo) +{ + SEQAN_CHECK(me.argumentList.size() > argumentPosition, + "Argument Parser has only %d arguments.", + me.argumentList.size()); + return _convertArgumentValue(value, getArgument(me, argumentPosition), getArgumentValue(getArgument(me, argumentPosition), argNo)); +} + +template +inline bool getArgumentValue(TValue & value, + ArgumentParser const & me, + unsigned argumentPosition) +{ + return getArgumentValue(value, me, argumentPosition, 0); +} + +// ---------------------------------------------------------------------------- +// Function getArgumentFileExtension() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getArgumentFileExtension + * @headerfile + * @brief Retrieve the file extension of a file argument. + * + * @signature std::string argumentFileExtension(parser, pos[, argNo]); + * + * @param[in] parser The ArgumentParser to get the value from. + * @param[in] pos The position of the argument to query (unsigned). + * @param[in] argNo Optional position for multi-value options (unsigned, defaults to 0). + * + * @return std::string The extension of the argument if any. + * + * @see ArgumentParser#getOptionFileExtension + * + * @section Overriding File Extensions on the Command Line + * + * For each argument with type INPUT_FILE and OUTPUT_FILE, an option with the index + * arg-${idx}-file-ext is automatically added to the ArgumentParser (where ${idx} is the index + * of the original option). The extension can be overridden by specifying the argument. Thus, the user of + * the program could give the value "file.ext" to the parameter "0" and override the extension on the + * command line to "ext2" as follows: + * + * @code{.console} + * # program_name file.ext --arg-0-file-ext ext2 + * @endcode + */ + +inline std::string getArgumentFileExtension(ArgumentParser const & me, + unsigned argumentPosition, + unsigned argNo = 0) +{ + SEQAN_CHECK(me.argumentList.size() > argumentPosition, + "Argument Parser has only %d arguments.", + me.argumentList.size()); + + + return getFileExtension(getArgument(me, argumentPosition), argNo); +} + +// ---------------------------------------------------------------------------- +// Function getOptionValues() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getOptionValues + * @headerfile + * @brief Returns all values of an option given on the command line. + * + * @signature TVector getOptionValues(parser, name); + * + * @param[in] parser The ArgumentParser to query. + * @param[in] name The short or long name of the option to get (std::string). + * + * @return TVector The resulting values (std::vector<std::string>). + */ + +inline std::vector const & getOptionValues(ArgumentParser const & me, + std::string const & name) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + return getArgumentValues(getOption(me, name)); +} + +// ---------------------------------------------------------------------------- +// Function getArgumentValues() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getArgumentValues + * @headerfile + * @brief Returns all values of an argument given on the command line. + * + * @signature TVector getArgumentValues(parser, pos); + * + * @param[in] parser The ArgumentParser to query. + * @param[in] pos The position of the argument (unsigned, 0-based). + * + * @return TVector The resulting values (std::vector<std::string>). + */ + +inline std::vector const & getArgumentValues(ArgumentParser const & me, + unsigned argumentPosition) +{ + SEQAN_CHECK(me.argumentList.size() > argumentPosition, + "Argument Parser has only %d arguments.", + me.argumentList.size()); + return getArgumentValues(getArgument(me, argumentPosition)); +} + +// ---------------------------------------------------------------------------- +// Function setDefaultValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setDefaultValue + * @headerfile + * @brief Set the default value of an option of an ArgumentParser. + * + * @signature void setDefaultValue(parser, name, v); + * + * @param[in] parser The ArgumentParser to set the default value to. + * @param[in] name The short or long name of the argument (std::string). + * @param[in] v The value to set (template parameter, must be streamable into a std::stringstream). + */ + +template +inline void setDefaultValue(ArgumentParser & me, + std::string const & name, + const TValue & value) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + setDefaultValue(getOption(me, name), value); +} + +// ---------------------------------------------------------------------------- +// Function addDefaultValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#addDefaultValue + * @headerfile + * @brief Add/append a value to the default values for an option in an ArgumentParser. + * + * @signature void addDefaultValue(parser, name, v); + * + * @param[in,out] parser The ArgumentParser to append the default value to. + * @param[in] name The short or long name of the argument (std::string). + * @param[in] v The value to append (template parameter, must be streamable into a std::stringstream). + */ + +template +inline void addDefaultValue(ArgumentParser & me, + std::string const & name, + const TValue & value) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + addDefaultValue(getOption(me, name), value); +} + +// ---------------------------------------------------------------------------- +// Function setMinValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setMinValue + * @headerfile + * @brief Set smallest allowed value for an option or argument of an ArgumentParser. + * + * @signature void setMinValue(parser, name, v); + * @signature void setMinValue(parser, pos, v); + * + * @param[in,out] parser The ArgumentParser to set the minimal value for. + * @param[in] name The name of the option to set the minimal value for (std::string). + * @param[in] pos The position of the argument to set the minimal value for (unsigned, 0-based). + * @param[in] v The minimal value to set (std::string). + * + * @section Remarks + * + * The option/argument must have an integer or double type. + */ + +inline void setMinValue(ArgumentParser & me, + std::string const & name, + std::string const & _minValue) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + setMinValue(getOption(me, name), _minValue); +} + +inline void setMinValue(ArgumentParser & me, + unsigned argumentPosition, + std::string const & _minValue) +{ + SEQAN_CHECK(me.argumentList.size() > argumentPosition, + "Argument Parser has only %d arguments.", + me.argumentList.size()); + setMinValue(getArgument(me, argumentPosition), _minValue); +} + +// ---------------------------------------------------------------------------- +// Function setMaxValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setMaxValue + * @headerfile + * @brief Set largest allowed value for an option or argument of an ArgumentParser. + * + * @signature void setMaxValue(parser, name, v); + * @signature void setMaxValue(parser, pos, v); + * + * @param[in,out] parser The ArgumentParser to set the maximal value for. + * @param[in] name The name of the option to set the maximal value for (std::string). + * @param[in] pos The position of the argument to set the maximal value for (unsigned, 0-based). + * @param[in] v The maximal value to set (std::string). + * + * @section Remarks + * + * The option/argument must have an integer or double type. + */ + +inline void setMaxValue(ArgumentParser & me, + std::string const & name, + std::string const & _maxValue) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + setMaxValue(getOption(me, name), _maxValue); +} + +inline void setMaxValue(ArgumentParser & me, + unsigned argumentPosition, + std::string const & _minValue) +{ + SEQAN_CHECK(me.argumentList.size() > argumentPosition, + "Argument Parser has only %d arguments.", + me.argumentList.size()); + setMaxValue(getArgument(me, argumentPosition), _minValue); +} + +// ---------------------------------------------------------------------------- +// Function setValidValues() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setValidValues + * @headerfile + * @brief Set valid values for an argumetn or option of an ArgumentParser. + * + * @signature void setValidValues(parser, name, values); + * @signature void setValidValues(parser, pos, values); + * + * @param[in,out] parser The ArgumentParser to set the default values to. + * @param[in] name The name of the option (std::string). + * @param[in] pos The position of the argument (unsigned, 0-based). + * @param[in] values The values to set. Either a std::string with the values as space-separated list + * or a std::vector<std::string> with the values. + */ + +inline void setValidValues(ArgumentParser & me, + std::string const & name, + std::vector const & values) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + setValidValues(getOption(me, name), values); + _copyValidValuesToFileExt(me, name); +} + +inline void setValidValues(ArgumentParser & me, + std::string const & name, + std::string const & values) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + setValidValues(getOption(me, name), values); + _copyValidValuesToFileExt(me, name); +} + +inline void setValidValues(ArgumentParser & me, + unsigned argumentPosition, + std::vector const & values) +{ + SEQAN_CHECK(me.argumentList.size() > argumentPosition, + "Argument Parser has only %d arguments.", + me.argumentList.size()); + setValidValues(getArgument(me, argumentPosition), values); + _copyValidValuesToFileExt(me, argumentPosition); +} + +inline void setValidValues(ArgumentParser & me, + unsigned argumentPosition, + std::string const & values) +{ + SEQAN_CHECK(me.argumentList.size() > argumentPosition, + "Argument Parser has only %d arguments.", + me.argumentList.size()); + setValidValues(getArgument(me, argumentPosition), values); + _copyValidValuesToFileExt(me, argumentPosition); +} + +// ---------------------------------------------------------------------------- +// Function setHelpText() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#setHelpText + * @headerfile + * @brief Set the help text of an option or argument. + * + * @signature void setHelpText(parser, name, text); + * @signature void setHelpText(parser, pos, text); + * + * @param[in,out] parser The ArgumentParser object. + * @param[in] name The name of the option to set the help text for (std::string). + * @param[in] pos The position of the argument to set the help text for. + * @param[in] text The string to use for the help text (std::string). + */ + +inline void setHelpText(ArgumentParser & me, + std::string const & name, + std::string const & text) +{ + SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name)); + setHelpText(getOption(me, name), text); +} + +inline void setHelpText(ArgumentParser & me, + unsigned argumentPosition, + std::string const & text) +{ + SEQAN_CHECK(me.argumentList.size() > argumentPosition, + "Argument Parser has only %d arguments.", + me.argumentList.size()); + setHelpText(getArgument(me, argumentPosition), text); +} + +// ---------------------------------------------------------------------------- +// Function getFileExtensions() +// ---------------------------------------------------------------------------- + +/*! + * @fn ArgumentParser#getFileExtensions + * @headerfile + * @brief Returns file format extension given a format tag. + * + * @signature TVector getFormatExtension(tag); + * @signature TVector getFormatExtension(tagList); + * @signature TVector getFormatExtension(tagSelector); + * + * @param[in] tag A single file foramt, e.g. Fastq(). + * @param[in] tagList A list of file format (@link TagList @endlink). + * @param[in] tagSelector A file format selector (@link TagSelector @endlink). + * + * @return TVector A std::vector<std::string> with the allowed file format extensions. + */ + +template +inline std::vector +getFileExtensions(T const formatTag) +{ + std::vector extensions; + _getFileExtensions(extensions, formatTag); + return extensions; +} + + +} // namespace seqan + +#endif // SEQAN_INCLUDE_ARG_PARSE_ARGUMENT_PARSER_H_ diff --git a/seqan/arg_parse/tool_doc.h b/seqan/arg_parse/tool_doc.h new file mode 100644 index 0000000..a19a983 --- /dev/null +++ b/seqan/arg_parse/tool_doc.h @@ -0,0 +1,1613 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef SEQAN_INCLUDE_ARG_PARSE_TOOL_DOC_H_ +#define SEQAN_INCLUDE_ARG_PARSE_TOOL_DOC_H_ + +#include + +#include +#include +#include + +namespace seqan { + +// ========================================================================== +// Forwards +// ========================================================================== + +class ToolDoc; +inline void clearEntries(ToolDoc & doc); +inline void append(ToolDoc & a, ToolDoc const & b); + +// ========================================================================== +// Tags, Classes, Enums +// ========================================================================== + +// -------------------------------------------------------------------------- +// Class ToolDocEntry_ +// -------------------------------------------------------------------------- + +// Base class for entries in the ToolDoc class. + +class ToolDocEntry_ +{ +public: + enum EntryType + { + SUBSECTION, SECTION, LINE, LIST_ITEM + }; + + virtual ~ToolDocEntry_() {} + + virtual EntryType getType() const = 0; +}; + +// -------------------------------------------------------------------------- +// Class ToolDocSection_ +// -------------------------------------------------------------------------- + +// A section in the ToolDoc class. + +class ToolDocSection_ : + public ToolDocEntry_ +{ +public: + CharString _title; + + ToolDocSection_(ToolDocSection_ const & sec) : + ToolDocEntry_(sec), _title(sec._title) + {} + + ToolDocSection_(CharString const & title) : + _title(title) + {} + + virtual EntryType getType() const + { + return SECTION; + } + +}; + +// -------------------------------------------------------------------------- +// Class ToolDocSubSection_ +// -------------------------------------------------------------------------- + +// A subsection. + +class ToolDocSubSection_ : + public ToolDocSection_ +{ +public: + ToolDocSubSection_(ToolDocSubSection_ const & sec) : + ToolDocSection_(sec) + {} + + ToolDocSubSection_(CharString const & title) : + ToolDocSection_(title) + {} + + virtual EntryType getType() const + { + return SUBSECTION; + } + +}; + +// -------------------------------------------------------------------------- +// Class ToolDocLine__ +// -------------------------------------------------------------------------- + +// A Line/Paragraph in ToolDoc documents. + +class ToolDocLine_ : + public ToolDocEntry_ +{ +public: + CharString _text; + // Evaluates to true if it is a paragraph and separated by .sp, false if it is a line, separated by .br. + bool _isPar; + + ToolDocLine_(ToolDocLine_ const & line) : + ToolDocEntry_(line), _text(line._text), _isPar(line._isPar) + {} + + ToolDocLine_(CharString const & text, bool isParagraph) : + _text(text), _isPar(isParagraph) + {} + + virtual EntryType getType() const + { + return LINE; + } + + bool isParagraph() const + { + return _isPar; + } + +}; + +// -------------------------------------------------------------------------- +// Class ToolDocListItem_ +// -------------------------------------------------------------------------- + +// A list item in ToolDoc documents. + +class ToolDocListItem_ : + public ToolDocEntry_ +{ +public: + CharString _term; + CharString _description; + + ToolDocListItem_(ToolDocListItem_ const & item) : + ToolDocEntry_(item), _term(item._term), _description(item._description) + {} + + ToolDocListItem_(CharString const & term, CharString const & description) : + _term(term), _description(description) + {} + + virtual EntryType getType() const + { + return LIST_ITEM; + } + +}; + +// -------------------------------------------------------------------------- +// Class ToolDocPrinter_ +// -------------------------------------------------------------------------- + +// Abstrace base class for ToolDoc printers. + +class ToolDocPrinter_ +{ +public: + virtual void print(std::ostream & stream, ToolDoc const & doc) = 0; +}; + +// -------------------------------------------------------------------------- +// Class ManToolDocPrinter_ +// -------------------------------------------------------------------------- + +// Print ToolDoc instance in man format. + +class ManToolDocPrinter_ : + public ToolDocPrinter_ +{ +public: + virtual void print(std::ostream & stream, ToolDoc const & doc); +}; + +// -------------------------------------------------------------------------- +// Class HtmlToolDocPrinter_ +// -------------------------------------------------------------------------- + +// Print ToolDoc instance in HTML format. + +class HtmlToolDocPrinter_ : + public ToolDocPrinter_ +{ +public: + void _maybeCloseList(std::ostream & stream, bool & isListOpen) + { + if (!isListOpen) + return; + + stream << "\n"; + isListOpen = false; + } + + void _maybeCloseParagraph(std::ostream & stream, bool & isParOpen) + { + if (!isParOpen) + return; + + stream << "

\n"; + isParOpen = false; + } + + // Converts formatting with \fI, \fB, and \fP to HTML. + template + TSequence _toHtml(TSequence const & input) const + { + TSequence buffer = xmlEscape(input); + TSequence result; + String openTags; + + typedef typename Iterator::Type TIterator; + TIterator endIt = end(input, Standard()); + for (TIterator it = begin(input, Standard()); it != endIt; goNext(it)) + { + if (*it == '\\') + { + // Handle escape sequence, we interpret only "\-", "\fI", and "\fB". + goNext(it); + SEQAN_ASSERT_NOT(it == endIt); + if (*it == '-') + { + appendValue(result, *it); + } + else if (*it == 'f') + { + goNext(it); + SEQAN_ASSERT_NOT(it == endIt); + if (*it == 'I') + { + appendValue(openTags, "em"); + append(result, ""); + } + else if (*it == 'B') + { + appendValue(openTags, "strong"); + append(result, ""); + } + else if (*it == 'P') + { + SEQAN_ASSERT_NOT(empty(openTags)); + append(result, ""); + eraseBack(openTags); + } + else + { + append(result, "\\f"); + appendValue(result, *it); + } + } + else + { + appendValue(result, '\\'); + appendValue(result, *it); + } + } + else + { + appendValue(result, *it); + } + } + + return result; + } + + virtual void print(std::ostream & stream, ToolDoc const & doc); +}; + +// -------------------------------------------------------------------------- +// Class TextToolDocPrinter_ +// -------------------------------------------------------------------------- + +// Print ToolDoc objects in Text format, suitable for console output. + +class TextToolDocPrinter_ : + public ToolDocPrinter_ +{ +public: + // Stores the relevant parameters of the documentation on the screen. + struct Layout_ + { + unsigned screenWidth; + unsigned defaultScreenWidth; + unsigned maximalScreenWidth; + unsigned minimalScreenWidth; + unsigned leftPadding; + unsigned centerPadding; + unsigned rightPadding; + unsigned leftColumnWidth; + unsigned rightColumnWidth; + unsigned rightColumnTab; + + Layout_() : + screenWidth(0), defaultScreenWidth(80), maximalScreenWidth(120), minimalScreenWidth(40), + leftPadding(4), centerPadding(2), rightPadding(2), leftColumnWidth(4), rightColumnWidth(0) + { + // Guess terminal screen width and set into layout. + unsigned cols = 0, rows = 0; + bool success = getTerminalSize(cols, rows); + screenWidth = (success && cols > 0) ? cols : defaultScreenWidth; + screenWidth = std::max(screenWidth, minimalScreenWidth); + screenWidth = std::min(screenWidth, maximalScreenWidth); + screenWidth -= rightPadding; + + rightColumnWidth = screenWidth - leftPadding - leftColumnWidth - centerPadding - rightPadding; + rightColumnTab = leftPadding + leftColumnWidth + centerPadding; + + // std::cerr << "screen width\t" << screenWidth << std::endl; + } + + }; + + Layout_ _layout; + + virtual void print(std::ostream & stream, ToolDoc const & doc); + + void _printSection(std::ostream & stream, ToolDocSection_ const & section) + { + std::ostream_iterator out(stream); + stream << '\n' << _toText("\\fB"); + std::transform(begin(section._title), end(section._title), out, static_cast < int(*)(int) > (toupper)); + stream << _toText("\\fP") << '\n'; + } + + void _printSubSection(std::ostream & stream, ToolDocSection_ const & section) + { + std::ostream_iterator out(stream); + stream << '\n' << _toText("\\fB"); + std::fill_n(out, _layout.leftPadding / 2, ' '); + stream << section._title << _toText("\\fP") << '\n'; + } + + void _printLine(std::ostream & stream, ToolDocLine_ const & line) + { + std::ostream_iterator out(stream); + std::fill_n(out, _layout.leftPadding, ' '); + + _printText(stream, line._text, _layout.leftPadding); + } + + CharString _toText(CharString const & str) const + { + CharString result; + + typedef Iterator::Type TIterator; + for (TIterator it = begin(str, Rooted()); !atEnd(it); goNext(it)) + { + if (*it == '\\') + { + // Handle escape sequence, we interpret only "\-", "\fI", and "\fB". + goNext(it); + SEQAN_ASSERT_NOT(atEnd(it)); + if (*it == '-') + { + appendValue(result, *it); + } + else if (*it == 'f') + { + goNext(it); + SEQAN_ASSERT_NOT(atEnd(it)); + if (*it == 'I') + { + if (isTerminal()) + append(result, "\033[4m"); + } + else if (*it == 'B') + { + if (isTerminal()) + append(result, "\033[1m"); + } + else if (*it == 'P') + { + if (isTerminal()) + append(result, "\033[0m"); + } + else + { + append(result, "\\f"); + appendValue(result, *it); + } + } + else + { + appendValue(result, '\\'); + appendValue(result, *it); + } + } + else + { + appendValue(result, *it); + } + } + + return result; + } + + void _printListItem(std::ostream & stream, ToolDocListItem_ const & listItem) + { + std::ostream_iterator out(stream); + + // Print term. + std::fill_n(out, _layout.leftPadding, ' '); + stream << _toText(listItem._term); + unsigned pos = _layout.leftPadding + length(listItem._term); + if (pos + _layout.centerPadding > _layout.rightColumnTab) + { + stream << '\n'; + pos = 0; + } + std::fill_n(out, _layout.rightColumnTab - pos, ' '); + + _printText(stream, listItem._description, _layout.rightColumnTab); + } + + // Returns width of text if printed, i.e. "\-" has length 1, "\fI", "\fB", "\fP" have length 0. + unsigned _textWidth(CharString const & text) + { + unsigned result = 0; + + for (unsigned i = 0; i < length(text); ++i) + { + if (text[i] != '\\') + { + result += 1; + continue; + } + + if (i + 1 == length(text)) + { + result += 1; // Will print "\\". + continue; + } + + if (text[i + 1] == '\\' || text[i + 1] == '-') + { + i += 1; + result += 1; + continue; // Will print '\\' or '-'. + } + + if (i + 2 == length(text)) + { + i += 1; + result += 2; // Will print two chars. + continue; + } + + if (text[i + 1] == 'f') + { + if (text[i + 2] == 'B' || text[i + 2] == 'I' || text[i + 2] == 'P') + i += 2; // Skip f and {B, I, P}. + else + result += 1; + } + } + + return result; + } + + // Print text, must be at tab already. + void _printText(std::ostream & stream, CharString const & text, unsigned tab) + { + unsigned pos = tab; + std::ostream_iterator out(stream); + + // Tokenize the text. + std::istringstream iss(toCString(text)); + std::vector tokens; + std::copy(std::istream_iterator(iss), std::istream_iterator(), + std::back_inserter >(tokens)); + + // Print the text. + SEQAN_ASSERT_LEQ(pos, tab); + std::fill_n(out, tab - pos, ' '); // go to tab + + pos = tab; + typedef std::vector::const_iterator TConstIter; + for (TConstIter it = tokens.begin(); it != tokens.end(); ++it) + { + if (it == tokens.begin()) + { + stream << _toText(*it); + pos += _textWidth(*it); + if (pos > _layout.screenWidth) + { + stream << '\n'; + std::fill_n(out, tab, ' '); + pos = tab; + } + } + else + { + if (pos + 1 + _textWidth(*it) > _layout.screenWidth) + { + // Would go over screen with next, print current word on next line. + stream << '\n'; + fill_n(out, tab, ' '); + stream << _toText(*it); + pos = tab + _textWidth(*it); + } + else + { + stream << ' '; + stream << _toText(*it); + pos += _textWidth(*it) + 1; + } + } + } + if (!empty(tokens)) + stream << '\n'; + } + +}; + +// -------------------------------------------------------------------------- +// Class ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @class ToolDoc + * @implements AssignableConcept + * @headerfile + * @brief Container for string documentation on a command line tool. + * + * @signature class ToolDoc; + * + * @section Remarks + * + * This class is generally not used directly by the user but through @link ArgumentParser @endlink. It allows one to store + * and represent all information related to a command line tool that would normally go into a man page. It can be + * printed to STL streams in different formats, currently plain text, HTML and man pages are supported. + * + * You can also use basic formatting in text. This formatting is tailored to the usage on the command line. Use + * \fB to start bold font, \fI to start italic font and \fP to use the previous font (of + * course, use correct escaping of the backslash in C strings, so use "\\fB", "\\fI", and + * "\\fP" in your code. + * + * @section Examples + * + * The following shows a brief example of how to use @link ToolDoc @endlink. + * + * @code{.cpp} + * ToolDoc doc; + * setName(doc, "RazerS"); + * setShortDescription(doc, "Read mapping with controllable sensitivity."); + * setDate(doc, "04 March 2012"); + * setVersion(doc, "1.0"); + * setCategory(doc, "Read Mapping"); + * setManTitle(doc, "SeqAn Apps Reference Manual"); + * + * addSection(doc, "Synopsis"); + * addText(doc, "\\fBrazers\\fP [\\fIOPTIONS\\fP] \\fIREFERENCE\\fP \\fIREADS\\fP", false); + * addText(doc, + * "\\fBrazers\\fP [\\fIOPTIONS\\fP] \\fIREFERENCE\\fP \\fILEFT_READS\\fP " + * "\\fIRIGHT_READS\\fP", false); + * + * addSection(doc, "Description"); + * addText(doc, + * "RazerS is a read mapper with controllable, sensitivity. This " + * "means that you can find all read matches in the reference sequence " + * "and optionally, you can trade lower sensitivity for better " + * "performance."); + * addText(doc, + * "What's special about RazerS is that you can control the sensitivity."); + * + * addSection(doc, "Options"); + * addSubSection(doc, "Main Options"); + * addListItem(doc, "\\fB-id\\fP, \\fB--indels\\fP", + * "Enable mapping with indels enabled."); + * addListItem(doc, "\\fB-i\\fP, \\fB--identity\\fP \\fIIDENTITY\\fP", + * "Set minimal identity of matches to find."); + * + * print(std::cout, doc, "text"); + * @endcode + * + * @see ToolDoc#addText + * @see ToolDoc#addListItem + * @see ArgumentParser + */ + +/*! + * @fn ToolDoc::ToolDoc + * @brief Constructor + * + * @signature ToolDoc::ToolDoc() + */ + +class ToolDoc +{ +public: + CharString _name; + CharString _shortDescription; + CharString _url; + CharString _date; + CharString _version; + CharString _shortCopyright; + CharString _longCopyright; + CharString _citation; + CharString _manTitle; + CharString _category; + unsigned _manSection; + + String _entries; + + enum Format {FORMAT_HTML, FORMAT_MAN, FORMAT_TXT}; + + ToolDoc() : + _manSection(1) {} + + ToolDoc(ToolDoc const & toolDoc) : + _name(toolDoc._name), _shortDescription(toolDoc._shortDescription), _url(toolDoc._url), + _date(toolDoc._date), _version(toolDoc._version), _shortCopyright(toolDoc._shortCopyright), + _longCopyright(toolDoc._longCopyright), _citation(toolDoc._citation), _manTitle(toolDoc._manTitle), + _category(toolDoc._category), _manSection(1) + { + append(*this, toolDoc); + } + + ~ToolDoc() + { + clearEntries(*this); + } + + void print(std::ostream & stream, Format format) const + { + switch (format) + { + case FORMAT_HTML: + { + HtmlToolDocPrinter_ p; + p.print(stream, *this); + } + break; + + case FORMAT_MAN: + { + ManToolDocPrinter_ p; + p.print(stream, *this); + } + break; + + case FORMAT_TXT: + { + TextToolDocPrinter_ p; + p.print(stream, *this); + } + break; + } + } + + void print(std::ostream & stream, CharString const & format) const + { + if (format == "html") + print(stream, FORMAT_HTML); + else if (format == "man") + print(stream, FORMAT_MAN); + else + print(stream, FORMAT_TXT); + } + +}; + +// ========================================================================== +// Metafunctions +// ========================================================================== + +// ========================================================================== +// Functions +// ========================================================================== + +// -------------------------------------------------------------------------- +// Function append() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#append + * @headerfile + * @brief Append two @link ToolDoc @endlink objects. + * + * @signature void append(a, b); + * + * @param[in,out] a This object is updated + * @param[in] b This object is appended to b. + */ + +inline void append(ToolDoc & a, ToolDoc const & b) +{ + for (unsigned i = 0; i < length(b._entries); ++i) + { + // TODO(holtgrew): This is quite ugly and can be made better with shared_ptr<> in C++11. + switch (b._entries[i]->getType()) + { + case ToolDocEntry_::SUBSECTION: + appendValue(a._entries, new ToolDocSubSection_(*static_cast(b._entries[i]))); + break; + + case ToolDocEntry_::SECTION: + appendValue(a._entries, new ToolDocSection_(*static_cast(b._entries[i]))); + break; + + case ToolDocEntry_::LINE: + appendValue(a._entries, new ToolDocLine_(*static_cast(b._entries[i]))); + break; + + case ToolDocEntry_::LIST_ITEM: + appendValue(a._entries, new ToolDocListItem_(*static_cast(b._entries[i]))); + break; + } + } +} + +// -------------------------------------------------------------------------- +// Function setName() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#setName + * @headerfile + * @brief Set the tool name. + * + * @signature void setName(toolDoc, name); + * + * @param[in,out] toolDoc The ToolDoc object to the set the name for. + * @param[in] name The name of the tool (@link CharString @endlink). + */ + +inline void setName(ToolDoc & doc, CharString const & name) +{ + doc._name = name; +} + +// -------------------------------------------------------------------------- +// Function getName() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#getName + * @headerfile + * @brief Get the tool name. + * + * @signature CharString getName(toolDoc); + * + * @param[in] toolDoc The ToolDoc object to the get the name for. + * + * @return CharString Resulting name (@link CharString @endlink). + */ + +inline CharString const & getName(ToolDoc const & doc) +{ + return doc._name; +} + +// -------------------------------------------------------------------------- +// Function setCategory() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#setCategory + * @headerfile + * @brief Set the tool name. + * + * @signature void setName(toolDoc, name); + * + * @param[in,out] toolDoc The ToolDoc object to the set the name for. + * @param[in] name The name of the tool (@link CharString @endlink). + */ + +inline void setCategory(ToolDoc & doc, CharString const & category) +{ + doc._category = category; +} + +// -------------------------------------------------------------------------- +// Function getCategory() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#getCategory + * @headerfile + * @brief Get the tool category. + * + * @signature CharString getCategory(toolDoc); + * + * @param[in] toolDoc The ToolDoc object to the get the category for. + * + * @return CharString Resulting category (@link CharString @endlink). + */ + +inline CharString const & getCategory(ToolDoc const & doc) +{ + return doc._category; +} + +// -------------------------------------------------------------------------- +// Function setShortDescription() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#setShortDescription + * @headerfile + * @brief Set the tool short description. + * + * @signature void setShortDescription(toolDoc, text); + * + * @param[in,out] toolDoc The ToolDoc object to the set the short description for. + * @param[in] text The short description of the tool (@link CharString @endlink). + */ + +inline void setShortDescription(ToolDoc & doc, CharString const & shortDescription) +{ + doc._shortDescription = shortDescription; +} + +// -------------------------------------------------------------------------- +// Function getShortDescription() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#getShortDescription + * @headerfile + * @brief Get the tool short description. + * + * @signature CharString getShortDescription(toolDoc); + * + * @param[in] toolDoc The ToolDoc object to the get the short description for. + * + * @return CharString Resulting short description (@link CharString @endlink). + */ + +inline CharString const & getShortDescription(ToolDoc const & doc) +{ + return doc._shortDescription; +} + +// -------------------------------------------------------------------------- +// Function setUrl() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#setUrl + * @headerfile + * @brief Set the url string to the app repository or website. + * + * @signature void setUrl(toolDoc, str); + * + * @param[in,out] toolDoc The ToolDoc object to the set the version string for. + * @param[in] str The url string of the tool (@link CharString @endlink). + */ + +inline void setUrl(ToolDoc & doc, CharString url) +{ + std::swap(doc._url, url); +} + +// -------------------------------------------------------------------------- +// Function getUrl() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#getUrl + * @headerfile + * @brief Get the url string to the app repository or website. + * + * @signature CharString getUrl(toolDoc); + * + * @param[in] toolDoc The ToolDoc object to the get the version string. + * + * @return CharString Resulting url string (@link CharString @endlink). + */ + +inline CharString const & getUrl(ToolDoc const & doc) +{ + return doc._url; +} + +// -------------------------------------------------------------------------- +// Function setDate() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#setDate + * @headerfile + * @brief Set the date string. + * + * @signature void setName(toolDoc, str); + * + * @param[in,out] toolDoc The ToolDoc object to the set the date string for. + * @param[in] str The date string of the tool (@link CharString @endlink). + */ + +inline void setDate(ToolDoc & doc, CharString const & date) +{ + doc._date = date; +} + +// -------------------------------------------------------------------------- +// Function getDate() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#getDate + * @headerfile + * @brief Get the date. + * + * @signature CharString getDate(toolDoc); + * + * @param[in] toolDoc The ToolDoc object to the get the date from. + * + * @return CharString Resulting date string (@link CharString @endlink). + */ + +inline CharString const & getDate(ToolDoc const & doc) +{ + return doc._date; +} + +// -------------------------------------------------------------------------- +// Function setVersion() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#setVersion + * @headerfile + * @brief Set the tool version string. + * + * @signature void setVersion(toolDoc, str); + * + * @param[in,out] toolDoc The ToolDoc object to the set the version string for. + * @param[in] str The version string of the tool (@link CharString @endlink). + */ + +inline void setVersion(ToolDoc & doc, CharString const & version) +{ + doc._version = version; +} + +// -------------------------------------------------------------------------- +// Function getVersion() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#getVersion + * @headerfile + * @brief Get the tool version string. + * + * @signature CharString getVersion(toolDoc); + * + * @param[in] toolDoc The ToolDoc object to the get the version string. + * + * @return CharString Resulting version string (@link CharString @endlink). + */ + +inline CharString const & getVersion(ToolDoc const & doc) +{ + return doc._version; +} + +// -------------------------------------------------------------------------- +// Function setShortCopyright() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#setShortCopyright + * @headerfile + * @brief Set the tool short copyright string. + * + * @signature void setShortCopyright(toolDoc, str); + * + * @param[in,out] toolDoc The ToolDoc object to the set the short copyright string for. + * @param[in] str The short copyright string of the tool (@link CharString @endlink). + */ + +inline void setShortCopyright(ToolDoc & doc, CharString const & shortCopyright) +{ + doc._shortCopyright = shortCopyright; +} + +// -------------------------------------------------------------------------- +// Function getShortCopyright() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#getShortCopyright + * @headerfile + * @brief Get the tool short copyright string. + * + * @signature CharString getShortCopyright(toolDoc); + * + * @param[in] toolDoc The ToolDoc object to the get the short copyright string. + * + * @return CharString Resulting short copyright string (@link CharString @endlink). + */ + +inline CharString const & getShortCopyright(ToolDoc const & doc) +{ + return doc._shortCopyright; +} + +// -------------------------------------------------------------------------- +// Function setLongCopyright() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#setLongCopyright + * @headerfile + * @brief Set the tool long copyright string. + * + * @signature void setLongCopyright(toolDoc, str); + * + * @param[in,out] toolDoc The ToolDoc object to the set the long copyright string for. + * @param[in] str The long copyright string of the tool (@link CharString @endlink). + */ + +inline void setLongCopyright(ToolDoc & doc, CharString const & longCopyright) +{ + doc._longCopyright = longCopyright; +} + +// -------------------------------------------------------------------------- +// Function getLongCopyright() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#getLongCopyright + * @headerfile + * @brief Get the tool long copyright string. + * + * @signature CharString getLongCopyright(toolDoc); + * + * @param[in] toolDoc The ToolDoc object to the get the long copyright string. + * + * @return CharString Resulting long copyright string (@link CharString @endlink). + */ + +inline CharString const & getLongCopyright(ToolDoc const & doc) +{ + return doc._longCopyright; +} + +// -------------------------------------------------------------------------- +// Function setCitation() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#setCitation + * @headerfile + * @brief Set the tool citation string. + * + * @signature void setCitation(toolDoc, str); + * + * @param[in,out] toolDoc The ToolDoc object to the set the citation string for. + * @param[in] str The citation string of the tool (@link CharString @endlink). + */ + +inline void setCitation(ToolDoc & doc, CharString const & citation) +{ + doc._citation = citation; +} + +// -------------------------------------------------------------------------- +// Function getCitation() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#getCitation + * @headerfile + * @brief Get the tool citation string. + * + * @signature CharString getCitation(toolDoc); + * + * @param[in] toolDoc The ToolDoc object to the get the citation string. + * + * @return CharString Resulting citation string (@link CharString @endlink). + */ + +inline CharString const & getCitation(ToolDoc const & doc) +{ + return doc._citation; +} + + +// -------------------------------------------------------------------------- +// Function setManTitle() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#setManTitle + * @headerfile + * @brief Set the man title. + * + * @signature void setTitle(toolDoc, title); + * + * @param[in,out] toolDoc The ToolDoc object to the set the title for. + * @param[in] title The title of the tool (@link CharString @endlink). + */ + +inline void setManTitle(ToolDoc & doc, CharString const & title) +{ + doc._manTitle = title; +} + +// -------------------------------------------------------------------------- +// Function getManTitle() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#getManTitle + * @headerfile + * @brief Get the tool man page title of. + * + * @signature CharString getManTitle(toolDoc); + * + * @param[in] toolDoc The ToolDoc object to the get the man page title. + * + * @return CharString Resulting man page title (@link CharString @endlink). + */ + +inline CharString const & getManTitle(ToolDoc & doc) +{ + return doc._manTitle; +} + +// -------------------------------------------------------------------------- +// Function addSection()ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#addSection + * @headerfile + * @brief Add a section with the given title. + * + * @signature void addSection(toolDoc, title); + * + * @param[in,out] toolDoc The ToolDoc object to add a section for. + * @param[in] title The section title (@link CharString @endlink). + */ + +inline void addSection(ToolDoc & doc, CharString const & title) +{ + appendValue(doc._entries, new ToolDocSection_(title)); +} + +// -------------------------------------------------------------------------- +// Function addSubSection() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#addSubSection + * @headerfile + * @brief Add a subsection with the given title. + * + * @signature void addSubSection(toolDoc, title); + * + * @param[in,out] toolDoc The ToolDoc object to add a subsection for. + * @param[in] title The subsection title (@link CharString @endlink). + */ + +inline void addSubSection(ToolDoc & doc, CharString const & title) +{ + appendValue(doc._entries, new ToolDocSubSection_(title)); +} + +// -------------------------------------------------------------------------- +// Function addText() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#addText + * @headerfile + * @brief Add a text line/paragraph to ToolDoc. + * + * @signature void addText(toolDoc, text[, isParagraph]); + * + * @param[in,out] toolDoc The ToolDoc to add the text to. + * @param[in] text The text to add (@link CharString @endlink). + * @param[in] isParagraph Whether to insert as paragraph or just a line (only one line break if not a paragraph). + */ + +inline void addText(ToolDoc & doc, CharString const & text, bool isParagraph) +{ + appendValue(doc._entries, new ToolDocLine_(text, isParagraph)); +} + +inline void addText(ToolDoc & doc, CharString const & text) +{ + addText(doc, text, true); +} + +// -------------------------------------------------------------------------- +// Function addListItem() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#addListItem + * @headerfile + * @brief Add a list item to a ToolDoc. + * + * @signature void addListItem(toolDoc, key, value); + * + * @param[in,out] toolDoc The ToolDoc object to add the list item to. + * @param[in] key The key for the list (@link CharString @endlink). + * @param[in] value The value for the list (@link CharString @endlink). + */ + +inline void addListItem(ToolDoc & doc, CharString const & key, CharString const & value) +{ + appendValue(doc._entries, new ToolDocListItem_(key, value)); +} + +// -------------------------------------------------------------------------- +// Function print() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#print + * @headerfile + * @brief Print ToolDoc object in a given format. + * + * @signature void print(stream, toolDoc, format); + * + * @param[in,out] stream The std::ostream to write to. + * @param[in] toolDoc The ToolDoc to print. + * @param[in] format The format, one of {"html", "man", "txt"}. + */ + +inline void print(std::ostream & stream, ToolDoc const & doc, CharString const & format) +{ + doc.print(stream, format); +} + +// -------------------------------------------------------------------------- +// Function clearEntries() ToolDoc +// -------------------------------------------------------------------------- + +/*! + * @fn ToolDoc#clearEntries + * @headerfile + * @brief Clear entries from ToolDoc. + * + * @signature void clearEntries(toolDoc); + * + * @param[in,out] toolDoc The ToolDoc object to clear entries from. + */ + +inline void clearEntries(ToolDoc & doc) +{ + typedef Iterator, Rooted>::Type TIter; + for (TIter it = begin(doc._entries, Rooted()); !atEnd(it); goNext(it)) + delete *it; + clear(doc._entries); +} + +// -------------------------------------------------------------------------- +// Function HtmlDocPrinter_::print() +// -------------------------------------------------------------------------- + +inline +void HtmlToolDocPrinter_::print(std::ostream & stream, ToolDoc const & doc) +{ + // Print HTML boilerplate header. + stream << "\n" + << "\n" + << "\n" + << "\n" + << "" << xmlEscape(doc._name) << " — " << xmlEscape(doc._shortDescription) << "\n" + << "\n" + << "\n"; + + stream << "

" << _toHtml(doc._name) << "

\n" + << "
" << _toHtml(doc._shortDescription) << "
\n"; + + typedef Iterator const, Rooted>::Type TIter; + bool isDl = false; + bool isP = false; + for (TIter it = begin(doc._entries, Rooted()); !atEnd(it); goNext(it)) + { + SEQAN_ASSERT_NOT_MSG(isDl && isP, "Current
and

are mutually exclusive."); + ToolDocEntry_ * entry = *it; + + switch (entry->getType()) + { + case ToolDocEntry_::SECTION: + { + _maybeCloseList(stream, isDl); + _maybeCloseParagraph(stream, isP); + ToolDocSection_ const * sec = static_cast(entry); + stream << "

" << _toHtml(sec->_title) << "

\n"; + } + break; + + case ToolDocEntry_::SUBSECTION: + { + _maybeCloseList(stream, isDl); + _maybeCloseParagraph(stream, isP); + ToolDocSection_ const * sec = static_cast(entry); + stream << "

" << _toHtml(sec->_title) << "

\n"; + } + break; + + case ToolDocEntry_::LINE: + { + ToolDocLine_ const * line = static_cast(entry); + _maybeCloseList(stream, isDl); + if (!isP) + { + stream << "

\n"; + isP = true; + } + stream << _toHtml(line->_text) << "\n"; + if (line->isParagraph()) + _maybeCloseParagraph(stream, isP); + else + stream << "
\n"; + } + break; + + case ToolDocEntry_::LIST_ITEM: + { + _maybeCloseParagraph(stream, isP); + ToolDocListItem_ const * item = static_cast(entry); + if (!isDl) + { + stream << "

\n"; + isDl = true; + } + stream << "
" << _toHtml(item->_term) << "
\n" + << "
" << _toHtml(item->_description) << "
\n"; + } + break; + } + } + _maybeCloseList(stream, isDl); + + // Print version, date and url. + stream << "

Version

\n" + << "Last update: " << _toHtml(doc._date) << "
\n" + << doc._name << " version: " << doc._version << "
\n" + << "SeqAn version: " << SEQAN_VERSION_MAJOR << '.' << SEQAN_VERSION_MINOR << '.' + << SEQAN_VERSION_PATCH; + if (SEQAN_VERSION_PRE_RELEASE != 0) + stream << "-pre" << SEQAN_VERSION_PRE_RELEASE; + if (!empty(doc._url)) + { + stream << "

Url

\n" + << doc._url << "
\n"; + } + stream << "
\n"; + + // Print legal stuff + if ((!empty(doc._shortCopyright)) || (!empty(doc._longCopyright)) || (!empty(doc._citation))) + { + stream << "

Legal

\n"; + + if (!empty(doc._shortCopyright)) + stream << doc._name << " Copyright: " + << doc._shortCopyright << "
\n"; + + stream << "SeqAn Copyright: 2006-2015 Knut Reinert, FU-Berlin; released under the 3-clause BSDL.
\n"; + + if (!empty(doc._citation)) + stream << "In your academic works please cite: " << doc._citation << "
\n"; + else + stream << "
"; + + if (!empty(doc._longCopyright)) + stream << "For full copyright and/or warranty information see --copyright.\n"; + } + + // Print HTML boilerplate footer. + stream << ""; +} + +// -------------------------------------------------------------------------- +// Function TextDocPrinter_::print() +// -------------------------------------------------------------------------- + +inline +void TextToolDocPrinter_::print(std::ostream & stream, ToolDoc const & doc) +{ + std::ostream_iterator out(stream); + + stream << doc._name; + if (!empty(doc._shortDescription)) + stream << " - " << doc._shortDescription; + stream << "\n"; + unsigned len = _textWidth(doc._name) + (empty(doc._shortDescription) ? 0 : 3) + _textWidth(doc._shortDescription); + std::fill_n(out, len, '='); + stream << '\n'; + + typedef Iterator const, Rooted>::Type TIter; + bool prevWasParagraph = false; // Stores whether to add a line break. + for (TIter it = begin(doc._entries, Rooted()); !atEnd(it); goNext(it)) + { + ToolDocEntry_ * entry = *it; + + switch (entry->getType()) + { + case ToolDocEntry_::SECTION: + { + ToolDocSection_ const * sec = static_cast(entry); + _printSection(stream, *sec); + prevWasParagraph = false; + } + break; + + case ToolDocEntry_::SUBSECTION: + { + ToolDocSection_ const * sec = static_cast(entry); + _printSubSection(stream, *sec); + prevWasParagraph = false; + } + break; + + case ToolDocEntry_::LINE: + { + if (prevWasParagraph) + stream << '\n'; + ToolDocLine_ const * line = static_cast(entry); + _printLine(stream, *line); + prevWasParagraph = line->isParagraph(); + } + break; + + case ToolDocEntry_::LIST_ITEM: + { + if (prevWasParagraph) + stream << '\n'; + ToolDocListItem_ const * item = static_cast(entry); + _printListItem(stream, *item); + prevWasParagraph = false; + } + break; + } + } + + // Print version, date and url. + stream << "\n" << _toText("\\fB") << "VERSION" << _toText("\\fP") << "\n"; + std::fill_n(out, _layout.leftPadding, ' '); + stream << _toText("\\fB") << "Last update: " << _toText("\\fP") << doc._date << "\n"; + std::fill_n(out, _layout.leftPadding, ' '); + stream << _toText("\\fB") << doc._name << " version: " << _toText("\\fP") << doc._version << "\n"; + std::fill_n(out, _layout.leftPadding, ' '); + stream << _toText("\\fB") << "SeqAn version: " << _toText("\\fP") << SEQAN_VERSION_MAJOR << '.' + << SEQAN_VERSION_MINOR << '.' << SEQAN_VERSION_PATCH; + if (SEQAN_VERSION_PRE_RELEASE != 0) + stream << "-pre" << SEQAN_VERSION_PRE_RELEASE; + if (!empty(doc._url)) + { + stream << "\n" << _toText("\\fB") << "URL" << _toText("\\fP") << "\n"; + std::fill_n(out, _layout.leftPadding, ' '); + stream << doc._url << "\n"; + } + stream << "\n"; + + // Print legal stuff + if ((!empty(doc._shortCopyright)) || (!empty(doc._longCopyright)) || (!empty(doc._citation))) + { + stream << "\n" << _toText("\\fB") << "LEGAL" << _toText("\\fP") << "\n"; + + if (!empty(doc._shortCopyright)) + { + std::fill_n(out, _layout.leftPadding, ' '); + stream << _toText("\\fB") << doc._name << " Copyright: " + << _toText("\\fP") << doc._shortCopyright << "\n"; + } + std::fill_n(out, _layout.leftPadding, ' '); + stream << _toText("\\fB") << "SeqAn Copyright: " << _toText("\\fP") + << "2006-2015 Knut Reinert, FU-Berlin; released under the 3-clause BSDL.\n"; + if (!empty(doc._citation)) + { + std::fill_n(out, _layout.leftPadding, ' '); + stream << _toText("\\fB") << "In your academic works please cite: " << _toText("\\fP") + << doc._citation << "\n"; + } + if (!empty(doc._longCopyright)) + { + std::fill_n(out, _layout.leftPadding, ' '); + stream << "For full copyright and/or warranty information see " << _toText("\\fB") + << "--copyright" << _toText("\\fP") << ".\n"; + } + } +} + +inline +void ManToolDocPrinter_::print(std::ostream & stream, ToolDoc const & doc) +{ + std::ostream_iterator out(stream); + + // Print .TH line. + stream << ".TH "; + std::transform(begin(doc._name), end(doc._name), out, static_cast < int(*)(int) > (toupper)); + stream << " " << doc._manSection << " \"" << doc._date << "\" \""; + std::transform(begin(doc._name), end(doc._name), out, static_cast < int(*)(int) > (tolower)); + stream << " " << doc._version << "\" \"" << doc._manTitle << "\"\n"; + + // Print NAME section. + stream << ".SH NAME\n" + << doc._name << " \\- " << doc._shortDescription << std::endl; + + // Print text. + typedef Iterator const, Rooted>::Type TIter; + bool isFirstInSection = true; + for (TIter it = begin(doc._entries, Rooted()); !atEnd(it); goNext(it)) + { + ToolDocEntry_ * entry = *it; + switch (entry->getType()) + { + case ToolDocEntry_::SUBSECTION: + { + ToolDocSubSection_ const * sec = static_cast(entry); + stream << ".SS " << sec->_title << "\n"; + isFirstInSection = true; + } + break; + + case ToolDocEntry_::SECTION: + { + ToolDocSection_ const * sec = static_cast(entry); + stream << ".SH "; + std::transform(begin(sec->_title), end(sec->_title), out, static_cast < int(*)(int) > (toupper)); + stream << "\n"; + isFirstInSection = true; + } + break; + + case ToolDocEntry_::LINE: + { + ToolDocLine_ const * line = static_cast(entry); + if (!isFirstInSection && line->isParagraph()) + stream << ".sp\n"; + else if (!isFirstInSection && !line->isParagraph()) + stream << ".br\n"; + stream << line->_text << "\n"; + isFirstInSection = false; + } + break; + + case ToolDocEntry_::LIST_ITEM: + { + ToolDocListItem_ const * item = static_cast(entry); + stream << ".TP\n" + << item->_term << "\n" + << item->_description << "\n"; + isFirstInSection = false; + } + break; + } + } + + // Print legal stuff + if ((!empty(doc._shortCopyright)) || (!empty(doc._longCopyright)) || (!empty(doc._citation))) + { + stream << ".SH LEGAL\n"; + + if (!empty(doc._shortCopyright)) + stream << "\\fB" << doc._name << " Copyright:\\fR " << doc._shortCopyright << "\n.br\n"; + + stream << "\\fBSeqAn Copyright:\\fR 2006-2015 Knut Reinert, FU-Berlin; released under the 3-clause BSDL.\n.br\n"; + + if (!empty(doc._citation)) + stream << "\\fBIn your academic works please cite:\\fR " << doc._citation << "\n.br\n"; + + if (!empty(doc._longCopyright)) + stream << "For full copyright and/or warranty information see \\fB--copyright\\fR.\n"; + } +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_MISC_TOOL_DOC_H_ diff --git a/seqan/arg_parse/xml_support.h b/seqan/arg_parse/xml_support.h new file mode 100644 index 0000000..6e14d40 --- /dev/null +++ b/seqan/arg_parse/xml_support.h @@ -0,0 +1,95 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Stephan Aiche +// ========================================================================== + +#ifndef INCLUDE_SEQAN_ARG_PARSE_XML_SUPPORT_H_ +#define INCLUDE_SEQAN_ARG_PARSE_XML_SUPPORT_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function _xmlEscape() +// ---------------------------------------------------------------------------- + +/* + * make sure that the text we put into the XML does not break the XML + * candidates are + * " -> " + * ' -> ' + * & -> & + * < -> < + * > -> > + */ +template +TSequence xmlEscape(TSequence const & original) +{ + typedef typename Iterator::Type TSequenceIterator; + TSequence escaped; + TSequenceIterator endIter = end(original, Standard()); + for (TSequenceIterator ch = begin(original, Standard()); ch != endIter; goNext(ch)) + { + if (value(ch) == '"') + append(escaped, """); + else if (value(ch) == '\'') + append(escaped, "'"); + else if (value(ch) == '&') + append(escaped, "&"); + else if (value(ch) == '<') + append(escaped, "<"); + else if (value(ch) == '>') + append(escaped, ">"); + else + appendValue(escaped, *ch); + } + return escaped; +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_ARG_PARSE_XML_SUPPORT_H_ diff --git a/seqan/bam_io.h b/seqan/bam_io.h new file mode 100644 index 0000000..f9f9842 --- /dev/null +++ b/seqan/bam_io.h @@ -0,0 +1,96 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// Author: David Weese +// ========================================================================== +// Facade header for module bam_io. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_H_ +#define INCLUDE_SEQAN_BAM_IO_H_ + +// =========================================================================== +// Prerequisites. +// =========================================================================== + +#include +#include +#include +#include +#include +#include + +// =========================================================================== +// Data Structures & Conversion. +// =========================================================================== + +#include +#include +#include +#include +#include +#include + +// =========================================================================== +// Actual I/O Code. +// =========================================================================== + +#include +#include +#include +#include + +// =========================================================================== +// Easy BAM / SAM I/O. +// =========================================================================== + +#include + +// =========================================================================== +// Utility Routines. +// =========================================================================== + +#include + +// Not included by default, requires C++11 +//#include + +// =========================================================================== +// BAM Index Related. +// =========================================================================== + +// BAM indices are only available when ZLIB is available. +#if SEQAN_HAS_ZLIB +#include +#endif // #if SEQAN_HAS_ZLIB + +#endif // INCLUDE_SEQAN_BAM_IO_H_ diff --git a/seqan/bam_io/bam_alignment_record.h b/seqan/bam_io/bam_alignment_record.h new file mode 100644 index 0000000..4e694d5 --- /dev/null +++ b/seqan/bam_io/bam_alignment_record.h @@ -0,0 +1,612 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// The class BamAlignmentRecord, flag checking methods, flag constants. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_BAM_RECORD_H_ +#define INCLUDE_SEQAN_BAM_IO_BAM_RECORD_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +class BamAlignmentRecord; +inline void clear(BamAlignmentRecord & record); + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @enum BamFlags + * @headerfile + * @brief Shortcuts to the bitmask flags for BAM/SAM files. + * + * @signature enum BamFlags; + * + * @val BamFlags BAM_FLAG_MULTIPLE = 0x0001; + * @brief Template has multiple fragments in sequencing. + * + * @val BamFlags BAM_FLAG_ALL_PROPER = 0x0002; + * @brief All fragments in the template are properly mapped. + * + * @val BamFlags BAM_FLAG_UNMAPPED = 0x0004; + * @brief This fragment is unmapped. + * + * @val BamFlags BAM_FLAG_NEXT_UNMAPPED = 0x0008; + * @brief Next fragment in template is unmapped. + * + * @val BamFlags BAM_FLAG_RC = 0x0010; + * @brief Fragment is reverse-complemented. + * + * @val BamFlags BAM_FLAG_NEXT_RC = 0x0020; + * @brief Next fragment in template is reverse-complemented. + * + * @val BamFlags BAM_FLAG_FIRST = 0x0040; + * @brief This fragment is the first one in its template. + * + * @val BamFlags BAM_FLAG_LAST = 0x0080; + * @brief This fragment is the last one in its template (second in case of paired sequencing). + * + * @val BamFlags BAM_FLAG_SECONDARY = 0x0100; + * @brief Secondary alignment. + * + * @val BamFlags BAM_FLAG_QC_NO_PASS = 0x0200; + * @brief Does not pass quality controls. + * + * @val BamFlags BAM_FLAG_DUPLICATE = 0x0400; + * @brief PCR or optical duplicate. + * + * @var BamFlags BAM_FLAG_SUPPLEMENTARY = 0x0800; + * @brief Supplementary alignment. + */ + +enum BamFlags +{ + BAM_FLAG_MULTIPLE = 0x0001, + BAM_FLAG_ALL_PROPER = 0x0002, + BAM_FLAG_UNMAPPED = 0x0004, + BAM_FLAG_NEXT_UNMAPPED = 0x0008, + BAM_FLAG_RC = 0x0010, + BAM_FLAG_NEXT_RC = 0x0020, + BAM_FLAG_FIRST = 0x0040, + BAM_FLAG_LAST = 0x0080, + BAM_FLAG_SECONDARY = 0x0100, + BAM_FLAG_QC_NO_PASS = 0x0200, + BAM_FLAG_DUPLICATE = 0x0400, + BAM_FLAG_SUPPLEMENTARY = 0x0800 +}; + +template +struct BamTypeChar +{ + enum + { + VALUE = + (IsSameType::VALUE)? 'A': + (IsSameType::VALUE)? 'c': + (IsSameType::VALUE)? 'C': + (IsSameType::VALUE)? 's': + (IsSameType::VALUE)? 'S': + (IsSameType::VALUE)? 'i': + (IsSameType::VALUE)? 'I': + (IsSameType::VALUE)? 'f': +// (IsSameType::VALUE)? 'd': + (IsSequence::VALUE)? 'Z': + '?' + }; +}; + +// List of primitive BAM types (ordered by expected usage frequency) +typedef TagList > > > > > > > BamTagTypes; + +// ---------------------------------------------------------------------------- +// Class BamAlignmentRecord +// ---------------------------------------------------------------------------- + +/*! + * @class BamAlignmentRecord + * @headerfile + * @implements FormattedFileRecordConcept + * @signature class BamAlignmentRecord; + * @brief Represent a record from a BAM or SAM file. + * + * @section Remarks + * + * While also used to represent SAM records, the type is called BamAlignmentRecord since the data directly + * reflects a BAM records (0-based positions, identify references by id, and tags are stored in BAM format. + * + * @see BamFileIn + * @see BamFileOut + */ + +/*! + * @var uint32_t BamAlignmentRecord::INVALID_POS + * @brief Static member with invalid sentinel/position value (-1). + * + * @var uint32_t BamAlignmentRecord::INVALID_REFID + * @brief Static member with invalid sentinel/position value (-1). + * + * @var uint32_t BamAlignmentRecord::INVALID_LEN + * @brief Static member with invalid/sentinel reference ids (0 as in BAM/SAM). + * + * @var CharString BamAlignmentRecord::qName; + * @brief The query/read name. + * + * Note that the reads of a template all of the same query name and are differentiated by their position + * and the BAM_FLAG_FIRST/BAM_FLAG_LAST flag values. + * + * @var uint16_t BamAlignmentRecord::flag; + * @brief The flag of this mapping. + * + * See @link BamFlags @endlink for flag constants and also see the hasFlag*() functions. + * + * @var int32_t BamAlignmentRecord::rID + * @brief ID of reference for this fragment mapping (0-based, INVALID_REFID for '*' in SAM). + * + * @var int32_t BamAlignmentRecord::beginPos + * @brief Begin position of the alignment (0-based, INVALID_POS for '0' in SAM). + * + * @var uint8_t BamAlignmentRecord::mapQ; + * @brief Mapping quality (255 for '*'). + * + * @var uint16_t BamAlignmentRecord::bin; + * @brief The bin of the alignment, automatically computed when writing BAM. + * + * @var TCigarString BamAlignmentRecord::cigar; + * @brief The CIGAR string for the BAM alignment (of type String >). + * + * @var int32_t BamAlignmentRecord::rNextId; + * @brief The ID of the reference where the next fragment in this template aligns. + * + * INVALID_REFID for '*'. + * + * @var int32_t BamAlignmentRecord::pNext; + * @brief Position on the reference where the next fragment in this template aligns. + * + * INVALID_POS for '*'. + * + * @var int32_t BamAlignmentRecord::tLen; + * @brief The inferred template size. + * + * INVALID_LEN for '*'. + * + * @var CharString BamAlignmentRecord::seq; + * @brief The fragment sequence. + * + * @var CharString BamAlignmentRecord::qual; + * @brief The PHRED quality values of the sequence (as in SAM), empty for '*'. + * + * @var CharString BamAlignmentRecord::tags; + * @brief Raw BAM tag string, use @link BamTagsDict @endlink for comfortable access. + */ + +struct BamAlignmentRecordCore +{ + int32_t rID; + int32_t beginPos; + mutable uint32_t _l_qname:8; + uint32_t mapQ:8; + mutable uint32_t bin:16; + mutable uint32_t _n_cigar:16; + uint32_t flag:16; + mutable int32_t _l_qseq; // _l_qname, _n_cigar and _l_qseq for internal usage + int32_t rNextId; + int32_t pNext; + int32_t tLen; +}; + +class BamAlignmentRecord : public BamAlignmentRecordCore +{ +public: + uint32_t _qID; // TODO(holtgrew): Undocumented as of yet. + String > cigar; + CharString qName; + IupacString seq; + CharString qual; + CharString tags; // raw tags in BAM format + CharString _buffer; // reusable internal buffer (used for I/O) + + static int32_t const INVALID_POS = -1; + static int32_t const INVALID_REFID = -1; // TODO(holtgrew): Rename to ...REF_ID. + static int32_t const INVALID_LEN = 0; + static uint32_t const INVALID_QID = 4294967295u; // TODO(holtgrew): Undocumented as of yet. + + BamAlignmentRecord() : _qID(MaxValue::VALUE) { clear(*this); } +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#clear + * @brief Clear BamAlignmentRecord. + * + * @signature void clear(record); + * + * @param[in,out] record The BamAlignmentRecord to clear. + * + * Clears all strings and resets it to default initialization state. + */ + +inline void +clear(BamAlignmentRecord & record) +{ + clear(record.qName); + record.flag = 0; + record._qID = MaxValue::VALUE; + record.rID = BamAlignmentRecord::INVALID_REFID; + record.beginPos = BamAlignmentRecord::INVALID_POS; + record.mapQ = 255; + record.bin = 0; + clear(record.cigar); + record.rNextId = BamAlignmentRecord::INVALID_REFID; + record.pNext = BamAlignmentRecord::INVALID_POS; + record.tLen = BamAlignmentRecord::INVALID_LEN; + clear(record.seq); + clear(record.qual); + clear(record.tags); +} + +// ---------------------------------------------------------------------------- +// Function hasFlagMultiple() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagMultiple + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "multiple" flag set. + * + * @signature bool hasFlagMultiple(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagMultiple(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_MULTIPLE) == BAM_FLAG_MULTIPLE; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagAllProper() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagAllProper + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "all properly aligned" flag set. + * + * @signature bool hasFlagAllProper(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagAllProper(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_ALL_PROPER) == BAM_FLAG_ALL_PROPER; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagUnmapped() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagUnmapped + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "unmapped" flag set. + * + * @signature bool hasFlagUnmapped(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagUnmapped(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_UNMAPPED) == BAM_FLAG_UNMAPPED; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagNextUnmapped() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagNextUnmapped + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "next unmapped" flag set. + * + * @signature bool hasFlagNextUnmapped(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagNextUnmapped(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_NEXT_UNMAPPED) == BAM_FLAG_NEXT_UNMAPPED; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagRC() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagRC + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "reverse-complemented" flag set. + * + * @signature bool hasFlagRC(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagRC(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_RC) == BAM_FLAG_RC; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagNextRC() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagNextRC + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "next reverse-complemented" flag set. + * + * @signature bool hasFlagNextRC(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagNextRC(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_NEXT_RC) == BAM_FLAG_NEXT_RC; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagFirst() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagFirst + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "first in template" flag set. + * + * @signature bool hasFlagFirst(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagFirst(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_FIRST) == BAM_FLAG_FIRST; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagLast() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagLast + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "last in template" flag set. + * + * @signature bool hasFlagLast(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagLast(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_LAST) == BAM_FLAG_LAST; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagSecondary() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagSecondary + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "secondary" flag set. + * + * @signature bool hasFlagSecondary(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagSecondary(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_SECONDARY) == BAM_FLAG_SECONDARY; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagQCNoPass() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagQCNoPass + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "did not pass QC" flag set. + * + * @signature bool hasFlagQCNoPass(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagQCNoPass(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_QC_NO_PASS) == BAM_FLAG_QC_NO_PASS; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagDuplicate() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagDuplicate + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "duplicate" flag set. + * + * @signature bool hasFlagDuplicate(record); + * + * @param[in] record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + * + * @see BamFlags + */ + +inline bool +hasFlagDuplicate(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_DUPLICATE) == BAM_FLAG_DUPLICATE; +} + +// ---------------------------------------------------------------------------- +// Function hasFlagSupplementary() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#hasFlagSupplementary + * @headerfile + * @brief Return true if a @link BamAlignmentRecord @endlink has the "supplementary" flag set. + * + * @signature bool hasFlagSupplementary(record); + * + * @param record The BamAlignmentRecord to query. + * + * @return bool true if the flag is set, false otherwise. + */ + +inline bool +hasFlagSupplementary(BamAlignmentRecord const & record) +{ + return (record.flag & BAM_FLAG_SUPPLEMENTARY) == BAM_FLAG_SUPPLEMENTARY; +} + +// ---------------------------------------------------------------------------- +// Function getAlignmentLengthInRef() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#getAlignmentLengthInRef + * @headerfile + * @brief Return the alignment length in the record's projection in the reference. + * + * @signature unsigned getAlignmentLengthInRef(record); + * + * @param[in] record The BamAlignmentRecord to compute length for. + * + * @return unsigned The alignment length. + * + * @see BamFlags + */ + +inline unsigned +getAlignmentLengthInRef(BamAlignmentRecord const & record) +{ + unsigned l = 0; + _getLengthInRef(l, record.cigar); + return l; +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_BAM_RECORD_H_ diff --git a/seqan/bam_io/bam_alignment_record_util.h b/seqan/bam_io/bam_alignment_record_util.h new file mode 100644 index 0000000..1a7a02f --- /dev/null +++ b/seqan/bam_io/bam_alignment_record_util.h @@ -0,0 +1,253 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_BAM_ALIGNMENT_RECORD_UTIL_H_ +#define INCLUDE_SEQAN_BAM_IO_BAM_ALIGNMENT_RECORD_UTIL_H_ + +namespace seqan { + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function getContigName() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#getContigName + * @brief Return the name of the reference contig of a @link BamAlignmentRecord @endlink. + * + * @signature TNameString getContigName(record, file); + * + * @param[in] record The @link BamAlignmentRecord @endlink to query. + * @param[in] file The @link BamFileIn @endlink or @link BamFileOut @endlink where the record belongs to. + * + * @return TNameString The name of the reference contig. TNameString is the @link Value @endlink type of the NameStore. + * The NameStore type can be determined using the @link Member @endlink metafunction + * for the @link BamIOContext @endlink in conjunction with the @link BamIOContextMemberTag#NameStoreMember @endlink tag. + */ + +template +inline typename Value, Dependent<> >::Type, NameStoreMember>::Type>::Type const & +getContigName(BamAlignmentRecord const & record, FormattedFile const & file) +{ + return contigNames(context(file))[record.rID]; +} + +// ---------------------------------------------------------------------------- +// Function getContigLength() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamAlignmentRecord#getContigLength + * @brief Return the length of the reference contig of a @link BamAlignmentRecord @endlink. + * + * @signature TLength getContigLength(record, file); + * + * @param[in] record The @link BamAlignmentRecord @endlink to query. + * @param[in] file The @link BamFileIn @endlink or @link BamFileOut @endlink where the record belongs to. + * + * @return TLength The length of the reference contig. TLength is the @link Value @endlink type of the LengthStore. + * The LengthStore type can be determined using the @link Member @endlink metafunction + * for the @link BamIOContext @endlink in conjunction with the @link BamIOContextMemberTag#LengthStoreMember @endlink tag. + */ + +template +inline typename Value, Dependent<> >::Type, LengthStoreMember>::Type>::Type +getContigLength(BamAlignmentRecord const & record, FormattedFile const & file) +{ + return contigLengths(context(file))[record.rID]; +} + +// ---------------------------------------------------------------------------- +// Function getClippedPos() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Test me! +// TODO(holtgrew): Document me! + +// Extract positions of soft clipping. + +inline bool +getClippedPos(unsigned & posBegin, unsigned & posEnd, BamAlignmentRecord const & record) +{ + posBegin = 0; + posEnd = length(record.seq); + + for (unsigned j = 0; j < length(record.cigar); ++j) + { + if (record.cigar[j].operation == 'S') + posBegin += record.cigar[j].count; + else + break; + } + for (unsigned j = 0; j < length(record.cigar); ++j) + { + if (record.cigar[length(record.cigar) - j - 1].operation == 'S') + posEnd -= record.cigar[length(record.cigar) - j - 1].count; + else + break; + } + SEQAN_ASSERT_LEQ(posBegin, posEnd); + SEQAN_ASSERT_LEQ(posBegin, length(record.seq)); + SEQAN_ASSERT_LEQ(posEnd, length(record.seq)); + + return (posBegin != 0) || (posEnd != length(record.seq)); +} + +// ---------------------------------------------------------------------------- +// Function clippedSeqInfix() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Test me! +// TODO(holtgrew): Document me! + +// Returns clipped infix of seq member. + +inline Infix::Type +clippedSeqInfix(BamAlignmentRecord & record) +{ + unsigned begPos = 0, endPos = 0; + getClippedPos(begPos, endPos, record); + return infix(record.seq, begPos, endPos); +} + +inline Infix::Type +clippedSeqInfix(BamAlignmentRecord const & record) +{ + unsigned begPos = 0, endPos = 0; + getClippedPos(begPos, endPos, record); + return infix(record.seq, begPos, endPos); +} + +// ---------------------------------------------------------------------------- +// Function clippedQualInfix() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Test me! +// TODO(holtgrew): Document me! + +// Returns clipped infix of qual member. + +inline Infix::Type +clippedQualInfix(BamAlignmentRecord & record) +{ + unsigned begPos = 0, endPos = 0; + getClippedPos(begPos, endPos, record); + return infix(record.qual, begPos, endPos); +} + +inline Infix::Type +clippedQualInfix(BamAlignmentRecord const & record) +{ + unsigned begPos = 0, endPos = 0; + getClippedPos(begPos, endPos, record); + return infix(record.qual, begPos, endPos); +} + +// ---------------------------------------------------------------------------- +// Function countPaddings() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): This actually belongs to wherever CigarElement is defined. + +inline unsigned countPaddings(String > const & cigarString) +{ + unsigned result = 0; + for (unsigned i = 0; i < length(cigarString); ++i) + if (cigarString[i].operation == 'P') + result += cigarString[i].count; + return result; +} + +// ---------------------------------------------------------------------------- +// Function bamRecordToAlignment() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Should rather be a global function? + +/*! + * @fn BamAlignmentRecord#bamRecordToAlignment + * @headerfile + * @brief Construct an @link Align @endlink object from a BamAlignmentRecord object. + * + * @signature void bamRecordToAlignment(align, reference, record); + * + * @param[out] align The @link Align @endlink object to create the alignment object in. + * @param[in] reference The string with the reference that record lies on. + * @param[in] record The @link BamAlignmentRecord @endlink to construct alignment from. + * + * The function will resize align to have two rows. The part of the reference that the read from + * record aligns to will be copied to the first row and the sequence from record will be copied to the second + * row (and reverse-complemented if appropriate). Then, the gaps from the CIGAR string in record will be + * copied to align. + * + * @section Example + * + * Here is an example: + * + * @code{.cpp} + * StringSet references; + * BamAlignment record; + * // Read references and record. + * Align align; + * if (record.rID != BamAlignmentRecord::INVALID_REFID) + * bamRecordToAlignment(align, references[record.refId], record); + * @endcode + */ + +// TODO(holtgrew): Convert into full example. + +template +void +bamRecordToAlignment(Align & result, TReference & reference, BamAlignmentRecord const & record) +{ + // TODO(holtgrew): Clipping better than copying infix? But is it generic? + resize(rows(result), 2); + + unsigned len = record.beginPos + getAlignmentLengthInRef(record) - countPaddings(record.cigar); + + setSource(row(result, 0), reference); + setClippedEndPosition(row(result, 0), record.beginPos + len); + setClippedBeginPosition(row(result, 0), record.beginPos); + cigarToGapAnchorContig(row(result, 0), record.cigar); + + assignSource(row(result, 1), record.seq); + cigarToGapAnchorRead(row(result, 1), record.cigar); +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_BAM_ALIGNMENT_RECORD_UTIL_H_ diff --git a/seqan/bam_io/bam_file.h b/seqan/bam_io/bam_file.h new file mode 100644 index 0000000..bf1c681 --- /dev/null +++ b/seqan/bam_io/bam_file.h @@ -0,0 +1,363 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// ========================================================================== +// Class for reading/writing files in SAM or BAM format. +// ========================================================================== + +#ifndef SEQAN_BAM_IO_BAM_FILE_H_ +#define SEQAN_BAM_IO_BAM_FILE_H_ + +namespace seqan { + +// ============================================================================ +// Typedefs +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Type BamFileIn +// ---------------------------------------------------------------------------- + +/*! + * @class BamFileIn + * @signature typedef FormattedFile BamFileIn; + * @extends FormattedFileIn + * @headerfile + * @brief Class for reading SAM and BAM files. + * + * @see BamHeader + * @see BamAlignmentRecord + * + * @section Example + * + * Access SAM or BAM files. + * + * @include demos/tutorial/sam_and_bam_io/solution1.cpp + * + * The output is as follows: + * + * @include demos/tutorial/sam_and_bam_io/example.sam + */ + +typedef FormattedFile BamFileIn; + +// ---------------------------------------------------------------------------- +// Type BamFileOut +// ---------------------------------------------------------------------------- + +/*! + * @class BamFileOut + * @signature typedef FormattedFile BamFileOut; + * @extends FormattedFileOut + * @headerfile + * @brief Class for writing SAM and BAM files. + * + * @see BamHeader + * @see BamAlignmentRecord + * + * @section Example + * + * Access SAM or BAM files. + * + * @include demos/tutorial/sam_and_bam_io/solution1.cpp + * + * The output is as follows: + * + * @include demos/tutorial/sam_and_bam_io/example.sam + */ + +typedef FormattedFile BamFileOut; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction FormattedFileContext +// ---------------------------------------------------------------------------- + +template +struct FormattedFileContext, TStorageSpec> +{ + typedef StringSet TNameStore; + typedef NameStoreCache TNameStoreCache; + typedef BamIOContext Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction FileFormats +// ---------------------------------------------------------------------------- + +template +struct FileFormat > +{ +#if SEQAN_HAS_ZLIB + typedef TagSelector< + TagList > + > Type; +#else + typedef Sam Type; +#endif +}; + +// -------------------------------------------------------------------------- +// Function _mapBamFormatToCompressionFormat() +// -------------------------------------------------------------------------- + +inline BgzfFile +_mapFileFormatToCompressionFormat(Bam) +{ + return BgzfFile(); +} + +// ---------------------------------------------------------------------------- +// Function readHeader(); BamHeader +// ---------------------------------------------------------------------------- + +// support for dynamically chosen file formats +template +inline void +readHeader(BamHeader & /* header */, + BamIOContext & /* context */, + TForwardIter & /* iter */, + TagSelector<> const & /* format */) +{ + SEQAN_FAIL("BamFileIn: File format not specified."); +} + +template +inline void +readHeader(BamHeader & header, + BamIOContext & context, + TForwardIter & iter, + TagSelector const & format) +{ + typedef typename TTagList::Type TFormat; + + if (isEqual(format, TFormat())) + readHeader(header, context, iter, TFormat()); + else + readHeader(header, context, iter, static_cast::Base const &>(format)); +} + +// convenient BamFile variant +template +inline void +readHeader(BamHeader & header, FormattedFile & file) +{ + readHeader(header, context(file), file.iter, file.format); +} + +// ---------------------------------------------------------------------------- +// Function readRecord(); BamAlignmentRecord +// ---------------------------------------------------------------------------- + +// support for dynamically chosen file formats +template +inline void +_readBamRecord(TBuffer & /* rawRecord */, TForwardIter & /* iter */, TagSelector<> const & /* format */) +{ + SEQAN_FAIL("BamFileIn: File format not specified."); +} + +template +inline void +_readBamRecord(TBuffer & rawRecord, TForwardIter & iter, TagSelector const & format) +{ + typedef typename TTagList::Type TFormat; + + if (isEqual(format, TFormat())) + _readBamRecord(rawRecord, iter, TFormat()); + else + _readBamRecord(rawRecord, iter, static_cast::Base const &>(format)); +} + +// ---------------------------------------------------------------------------- +// Function readRecord(); BamAlignmentRecord +// ---------------------------------------------------------------------------- + +// support for dynamically chosen file formats +template +inline void +readRecord(BamAlignmentRecord & /* record */, + BamIOContext & /* context */, + TForwardIter & /* iter */, + TagSelector<> const & /* format */) +{ + SEQAN_FAIL("BamFileIn: File format not specified."); +} + +template +inline void +readRecord(BamAlignmentRecord & record, + BamIOContext & context, + TForwardIter & iter, + TagSelector const & format) +{ + typedef typename TTagList::Type TFormat; + + if (isEqual(format, TFormat())) + readRecord(record, context, iter, TFormat()); + else + readRecord(record, context, iter, static_cast::Base const &>(format)); +} + +// convenient BamFile variant +template +inline void +readRecord(BamAlignmentRecord & record, FormattedFile & file) +{ + readRecord(record, context(file), file.iter, file.format); +} + +template +inline SEQAN_FUNC_ENABLE_IF(And::Type, BamAlignmentRecord>, + IsInteger >, TSize) +readRecords(TRecords & records, FormattedFile & file, TSize maxRecords) +{ + String & buffers = context(file).buffers; + if (static_cast(length(buffers)) < maxRecords) + resize(buffers, maxRecords, Exact()); + if (static_cast(length(records)) < maxRecords) + resize(records, maxRecords, Exact()); + + TSize numRecords = 0; + for (; numRecords < maxRecords && !atEnd(file.iter); ++numRecords) + _readBamRecord(buffers[numRecords], file.iter, file.format); + +// SEQAN_OMP_PRAGMA(parallel for) + for (int i = 0; i < (int)numRecords; ++i) + { + CharIterator bufIter = begin(buffers[i]); + readRecord(records[i], context(file), bufIter, file.format); + } + return numRecords; +} + +// ---------------------------------------------------------------------------- +// Function writeHeader(); BamHeader +// ---------------------------------------------------------------------------- + +// support for dynamically chosen file formats +template +inline void +write(TTarget & /* target */, + BamHeader const & /* header */, + BamIOContext & /* context */, + TagSelector<> const & /* format */) +{ + SEQAN_FAIL("BamFileOut: File format not specified."); +} + +template +inline void +write(TTarget & target, + BamHeader const & header, + BamIOContext & context, + TagSelector const & format) +{ + typedef typename TTagList::Type TFormat; + + if (isEqual(format, TFormat())) + write(target, header, context, TFormat()); + else + write(target, header, context, static_cast::Base const &>(format)); +} + +// convenient BamFile variant +template +inline void +writeHeader(FormattedFile & file, BamHeader const & header) +{ + write(file.iter, header, context(file), file.format); +} + +// ---------------------------------------------------------------------------- +// Function writeRecord(); BamAlignmentRecord +// ---------------------------------------------------------------------------- + +// support for dynamically chosen file formats +template +inline void +write(TTarget & /* target */, + BamAlignmentRecord const & /* record */, + BamIOContext & /* context */, + TagSelector<> const & /* format */) +{ + SEQAN_FAIL("BamFileOut: File format not specified."); +} + +template +inline void +write(TTarget & target, + BamAlignmentRecord const & record, + BamIOContext & context, + TagSelector const & format) +{ + typedef typename TTagList::Type TFormat; + + if (isEqual(format, TFormat())) + write(target, record, context, TFormat()); + else + write(target, record, context, static_cast::Base const &>(format)); +} + +template +inline void +writeRecord(FormattedFile & file, BamAlignmentRecord const & record) +{ + write(file.iter, record, context(file), file.format); +} + +template +inline SEQAN_FUNC_ENABLE_IF(IsSameType::Type, BamAlignmentRecord>, void) +writeRecords(FormattedFile & file, TRecords const & records) +{ + String & buffers = context(file).buffers; + if (length(buffers) < length(records)) + resize(buffers, length(records)); + + SEQAN_OMP_PRAGMA(parallel for) + for (int i = 0; i < (int)length(records); ++i) + { + clear(buffers[i]); + write(buffers[i], records[i], context(file), file.format); + } + for (int i = 0; i < (int)length(records); ++i) + write(file.iter, buffers[i]); +} + +} // namespace seqan + +#endif // SEQAN_BAM_IO_BAM_FILE_H_ diff --git a/seqan/bam_io/bam_header_record.h b/seqan/bam_io/bam_header_record.h new file mode 100644 index 0000000..0854d33 --- /dev/null +++ b/seqan/bam_io/bam_header_record.h @@ -0,0 +1,483 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// BamHeaderRecord class, supporting types and functions for accessing tags +// in headers. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_BAM_HEADER_RECORD_H_ +#define INCLUDE_SEQAN_BAM_IO_BAM_HEADER_RECORD_H_ + +namespace seqan { + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Enum BamHeaderRecordType +// ---------------------------------------------------------------------------- + +/*! + * @enum BamHeaderRecordType + * @headerfile + * @brief Enumeration for the header record type. + * + * @signature enum BamHeaderRecordType; + * + * @val BamHeaderRecordType BAM_HEADER_FIRST = 0; + * @brief Is the first header (HD). + * + * @val BamHeaderRecordType BAM_HEADER_REFERENCE = 1; + * @brief Is a reference (SQ) header. + * + * @val BamHeaderRecordType BAM_HEADER_READ_GROUP = 2; + * @brief Is a read group (RG) header. + * + * @val BamHeaderRecordType BAM_HEADER_PROGRAM = 3; + * @brief Is a program (PG) header. + * + * @val BamHeaderRecordType BAM_HEADER_COMMENT = 4; + * @brief Is a comment (CO) header. + */ + +enum BamHeaderRecordType +{ + BAM_HEADER_FIRST = 0, + BAM_HEADER_REFERENCE = 1, + BAM_HEADER_READ_GROUP = 2, + BAM_HEADER_PROGRAM = 3, + BAM_HEADER_COMMENT = 4 +}; + +// ---------------------------------------------------------------------------- +// Enum BamSortOrder +// ---------------------------------------------------------------------------- + +/*! + * @enum BamSortOrder + * @headerfile + * @brief Enumeration for the header record type. + * + * @signature enum BamSortOrder; + * + * @val BamSortOrder BAM_SORT_UNKNOWN = 0; + * @brief BAM file sort order is unknown. + * + * @val BamSortOrder BAM_SORT_UNSORTED = 1; + * @brief BAM file is unsorted. + * + * @val BamSortOrder BAM_SORT_QUERYNAME = 2; + * @brief BAM file is sorted by query name; + * + * @val BamSortOrder BAM_SORT_COORDINATE = 3; + * @brief BAM file is sorted by coordinate. + */ + +enum BamSortOrder +{ + BAM_SORT_UNKNOWN = 0, + BAM_SORT_UNSORTED = 1, + BAM_SORT_QUERYNAME = 2, + BAM_SORT_COORDINATE = 3 +}; + +// ---------------------------------------------------------------------------- +// Class BamHeaderRecord +// ---------------------------------------------------------------------------- + +/*! + * @class BamHeaderRecord + * @headerfile + * @brief Represents a header entry in a SAM file or the header section of the BAM header. + * + * @signature class BamHeaderRecord; + * + * @section Remarks + * + * Comment records are stored with one tag where the key is empty and the value is the comment. + */ + +/*! + * @fn BamHeaderRecord::BamHeaderRecord + * @brief Constructor. + * @signature BamHeaderRecord::BamRecord(); + * + * Only the default constructor is provided. + */ + +/*! + * @typedef BamHeaderRecord::TTagName + * @brief Type of the tag keys (@link CharString @endlink). + * @signature BamHeaderRecord::TTagName; + * + * @typedef BamHeaderRecord::TTagValue + * @brief Type of the tag values (@link CharString @endlink). + * @signature BamHeaderRecord::TTagValue; + * + * @typedef BamHeaderRecord::TTag + * @brief Type of the tag keys (@link Pair @endlink of TTagName and TTagValue). + * @signature BamHeaderRecord::TTag; + * + * @typedef BamHeaderRecord::TTags + * @brief Type of the tags string (@link AllocString @endlink of TTag). + * @signature BamHeaderRecord::TTags; + * + * @var BamHeaderRecordType BamHeaderRecord::type; + * @brief Type of the record. + * + * @var TRecordString BamHeaderRecord::tags; + * @brief The header record's tags, of type @link BamHeaderRecord::TTags @endlink. + */ + +class BamHeaderRecord +{ +public: + typedef CharString TTagName; + typedef CharString TTagValue; + typedef Pair TTag; + typedef String TTags; + + BamHeaderRecordType type; + TTags tags; + + BamHeaderRecord() : type(BAM_HEADER_FIRST) {} +}; + +// ---------------------------------------------------------------------------- +// Class BamHeader +// ---------------------------------------------------------------------------- + +/*! + * @class BamHeader + * @headerfile + * @implements FormattedFileHeaderConcept + * @signature typedef String BamHeader; + * @brief Represent the information of the BAM header. + * + * @see BamFileIn + * @see BamFileOut + */ + +typedef String BamHeader; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function std::swap() +// ---------------------------------------------------------------------------- + +inline void +swap(BamHeaderRecord &a, BamHeaderRecord &b) +{ + std::swap(a.type, b.type); + swap(a.tags, b.tags); +} + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamHeaderRecord::clear + * @brief Clear BamHeaderRecord object. + * + * @signature void clear(record); + * + * @param[in,out] record The record to clear. + */ + +inline void +clear(BamHeaderRecord & record) +{ + clear(record.tags); +} + +// ---------------------------------------------------------------------------- +// Function findTagKey() +// ---------------------------------------------------------------------------- + +template +inline bool +findTagKey(unsigned & idx, TKeyName const & key, BamHeaderRecord const & record) +{ + typedef BamHeaderRecord::TTags const TTags; + typedef Iterator::Type TIterator; + + idx = 0; + TIterator itEnd = end(record.tags, Standard()); + for (TIterator it = begin(record.tags, Standard()); it != itEnd; goNext(it), ++idx) + if (it->i1 == key) + return true; + + return false; +} + +// ---------------------------------------------------------------------------- +// Function getTagValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamHeaderRecord::getTagValue + * @brief Return tag value from a @link BamHeaderRecord @endlink. + * + * @signature bool getTagValue(tagValue, idx, record); + * @signature bool getTagValue(tagValue, key, record); + * + * @param[out] tagValue The @link CharString @endlink to write the tag value to. + * @param[in] idx An integer with the index of the tag in the header record. + * @param[in] key A two-letter sequence with the key of the tag in the header record. + * + * @return bool true in case the value could be retrieved, false otherwise. + * + * @section Example + * + * @code{.cpp} + * CharString tagValue; + * bool keyFound = getTagValue(tagValue, "SN", record); + * @endcode + */ + +template +SEQAN_FUNC_ENABLE_IF( + IsInteger, + bool) +inline getTagValue(CharString & value, TId idx, BamHeaderRecord const & record) +{ + if ((unsigned)idx >= length(record.tags)) + return false; + value = record.tags[idx].i2; + return true; +} + +template +SEQAN_FUNC_ENABLE_IF( + IsSequence, + bool) +inline getTagValue(CharString & value, TKeyName const & key, BamHeaderRecord const & record) +{ + unsigned idx = 0; + if (!findTagKey(idx, key, record)) + return false; + return getTagValue(value, idx, record); +} + +/*! + * @fn BamHeaderRecord::setTagValue + * @brief Sets the value of a tag in a BamHeaderRecord. + * + * @signature void setTagValue(idx, value, record); + * @signature void setTagValue(key, value, record); + * + * @param[in,out] idx The index of the tag in the header record to set the value for. + * @param[in] key The name of the tag (two-letter sequence) to set. + * @param[in] record The header record to set the value for. + */ + +// TODO(holtgrew): Parameter order! + +template +SEQAN_FUNC_ENABLE_IF( + IsInteger, + void) +inline setTagValue(TId idx, CharString const & value, BamHeaderRecord & record) +{ + if (idx >= length(record.tags)) + return; + record.tags[idx].i2 = value; +} + +template +SEQAN_FUNC_ENABLE_IF( + IsSequence, + void) +inline setTagValue(TKeyName const & key, CharString const & value, BamHeaderRecord & record) +{ + unsigned idx = 0; + if (!findTagKey(idx, key, record)) + { + idx = length(record.tags); + resize(record.tags, idx + 1); + record.tags[idx].i1 = key; + } + setTagValue(idx, value, record); +} + +// ---------------------------------------------------------------------------- +// Function getSortOrder() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Document me! Test me! + + +inline bool +searchRecord(unsigned & recordIdx, + BamHeader const & header, + BamHeaderRecordType recordType, + unsigned startIdx) +{ + for (recordIdx = startIdx; recordIdx < length(header); ++recordIdx) + if (header[recordIdx].type == recordType) + return true; + return false; +} + +inline bool +searchRecord(unsigned & recordIdx, + BamHeader const & header, + BamHeaderRecordType recordType) +{ + return searchRecord(recordIdx, header, recordType, 0); +} + + +struct BamHeaderRecordTypeLess +{ + bool operator() (BamHeaderRecord const &a, BamHeaderRecord const &b) const + { + return a.type < b.type; + } +}; + +struct BamHeaderRecordEqual +{ + bool operator() (BamHeaderRecord const &a, BamHeaderRecord const &b) const + { + return a.type == b.type && a.tags == b.tags; + } +}; + + +inline void +removeDuplicates(BamHeader & header) +{ + BamHeaderRecordTypeLess less; + BamHeaderRecordEqual pred; + + std::stable_sort(begin(header, Standard()), end(header, Standard()), less); + + for (size_t uniqueBegin = 0, uniqueEnd = 1; uniqueEnd < length(header);) + { + if (less(header[uniqueBegin], header[uniqueEnd])) + uniqueBegin = uniqueEnd; + + size_t j; + for (j = uniqueBegin; j < uniqueEnd; ++j) + if (pred(header[j], header[uniqueEnd])) + { + erase(header, uniqueEnd); + break; + } + + if (j == uniqueEnd) + ++uniqueEnd; + } +} + +inline BamSortOrder +getSortOrder(BamHeader const & header) +{ + CharString soString; + for (unsigned recIdx = 0; searchRecord(recIdx, header, BAM_HEADER_FIRST, recIdx); ++recIdx) + { + if (getTagValue(soString, "SO", header[recIdx])) + { + if (soString == "unsorted") + return BAM_SORT_UNSORTED; + else if (soString == "queryname") + return BAM_SORT_QUERYNAME; + else if (soString == "coordinate") + return BAM_SORT_COORDINATE; + else + return BAM_SORT_UNKNOWN; + } + } + return BAM_SORT_UNKNOWN; +} + +inline void +setSortOrder(BamHeader & header, BamSortOrder sortOrder) +{ + char const * soString; + switch (sortOrder) + { + case BAM_SORT_UNSORTED: + soString = "unsorted"; + break; + + case BAM_SORT_QUERYNAME: + soString = "queryname"; + break; + + case BAM_SORT_COORDINATE: + soString = "coordinate"; + break; + + default: + soString = "unknown"; + } + + bool notFound = true; + for (unsigned recIdx = 0; searchRecord(recIdx, header, BAM_HEADER_FIRST, recIdx); ++recIdx) + { + unsigned idx = 0; + if (findTagKey(idx, "SO", header[recIdx])) + { + notFound = false; + setTagValue(idx, soString, header[recIdx]); + } + } + + if (notFound) + { + unsigned recIdx = 0; + if (searchRecord(recIdx, header, BAM_HEADER_FIRST)) + { + setTagValue("SO", soString, header[recIdx]); + } + else + { + BamHeaderRecord rec; + rec.type = BAM_HEADER_FIRST; + setTagValue("VN", "1.4", rec); + setTagValue("SO", soString, rec); + insert(header, 0, rec); + } + } +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_BAM_HEADER_RECORD_H_ diff --git a/seqan/bam_io/bam_index_bai.h b/seqan/bam_io/bam_index_bai.h new file mode 100644 index 0000000..db5ed68 --- /dev/null +++ b/seqan/bam_io/bam_index_bai.h @@ -0,0 +1,794 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +// The index building algorithm is based on the samtools implementation which +// is under the MIT License: + +/* The MIT License + + Copyright (c) 2008-2009 Genome Research Ltd. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef INCLUDE_SEQAN_BAM_IO_BAM_INDEX_BAI_H_ +#define INCLUDE_SEQAN_BAM_IO_BAM_INDEX_BAI_H_ + +namespace seqan { + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class BamIndex +// ---------------------------------------------------------------------------- + +/*! + * @class BamIndex + * @headerfile + * + * @brief Access to BAM indices. + * + * @signature template + * class BamIndex; + * + * This is an abstract class; don't use it itself but its specializations. + * + * @see BamFileIn + */ + +template +class BamIndex; + +// ---------------------------------------------------------------------------- +// Tag Bai +// ---------------------------------------------------------------------------- + +struct Bai_; +typedef Tag Bai; + +// ---------------------------------------------------------------------------- +// Helper Class BaiBamIndexBinData_ +// ---------------------------------------------------------------------------- + +// Store the information of a bin. + +struct BaiBamIndexBinData_ +{ + String > chunkBegEnds; +}; + +// ---------------------------------------------------------------------------- +// Spec BAI BamIndex +// ---------------------------------------------------------------------------- + +/*! + * @class BaiBamIndex + * @headerfile + * @extends BamIndex + * @brief Access to BAI (samtools-style). + * + * @signature template <> + * class BamIndex; + */ + +/*! + * @fn BaiBamIndex::BamIndex + * @brief Constructor. + * + * @signature BamIndex::BamIndex(); + * + * @section Remarks + * + * Only the default constructor is provided. + */ + +template <> +class BamIndex +{ +public: + typedef std::map TBinIndex_; + typedef String TLinearIndex_; + + uint64_t _unalignedCount; + + // 1<<14 is the size of the minimum bin. + static const int32_t BAM_LIDX_SHIFT = 14; + + String _binIndices; + String _linearIndices; + + BamIndex() : _unalignedCount(maxValue()) + {} +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function jumpToRegion() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamFileIn#jumpToRegion + * @brief Seek in BamFileIn using an index. + * + * You provide a region [pos, posEnd) on the reference refID that you want to jump to and the function + * jumps to the first alignment in this region, if any. + * + * @signature bool jumpToRegion(bamFileIn, hasAlignments, refID, pos, posEnd, index); + * + * @param[in,out] bamFileIn The @link BamFileIn @endlink to jump with. + * @param[out] hasAlignments A bool that is set true if the region [pos, posEnd) has any + * alignments. + * @param[in] refID The reference id to jump to (int32_t). + * @param[in] pos The begin of the region to jump to (int32_t). + * @param[in] posEnd The end of the region to jump to (int32_t). + * @param[in] index The @link BamIndex @endlink to use for the jumping. + * + * @return bool true if seeking was successful, false if not. + * + * @section Remarks + * + * This function fails if refID/pos are invalid. + */ + +static inline void +_baiReg2bins(String & list, uint32_t beg, uint32_t end) +{ + unsigned k; + if (beg >= end) return; + if (end >= 1u<<29) end = 1u<<29; + --end; + appendValue(list, 0); + for (k = 1 + (beg>>26); k <= 1 + (end>>26); ++k) appendValue(list, k); + for (k = 9 + (beg>>23); k <= 9 + (end>>23); ++k) appendValue(list, k); + for (k = 73 + (beg>>20); k <= 73 + (end>>20); ++k) appendValue(list, k); + for (k = 585 + (beg>>17); k <= 585 + (end>>17); ++k) appendValue(list, k); + for (k = 4681 + (beg>>14); k <= 4681 + (end>>14); ++k) appendValue(list, k); +} + +template +inline bool +jumpToRegion(FormattedFile & bamFile, + bool & hasAlignments, + int32_t refId, + int32_t pos, + int32_t posEnd, + BamIndex const & index) +{ + if (!isEqual(format(bamFile), Bam())) + return false; + + hasAlignments = false; + if (refId < 0) + return false; // Cannot seek to invalid reference. + if (static_cast(refId) >= length(index._binIndices)) + return false; // Cannot seek to invalid reference. + + // ------------------------------------------------------------------------ + // Compute offset in BGZF file. + // ------------------------------------------------------------------------ + uint64_t offset = MaxValue::VALUE; + + // Retrieve the candidate bin identifiers for [pos, posEnd). + String candidateBins; + _baiReg2bins(candidateBins, pos, posEnd); + + // Retrieve the smallest required offset from the linear index. + unsigned windowIdx = pos >> 14; // Linear index consists of 16kb windows. + uint64_t linearMinOffset = 0; + if (windowIdx >= length(index._linearIndices[refId])) + { + // TODO(holtgrew): Can we simply always take case 1? + + // This is the case were we want to jump in a non-existing window. + // + // If there are no linear indices for this reference then we use the linear min offset of the next + // reference that has an linear index. + if (empty(index._linearIndices[refId])) + { + for (unsigned i = refId; i < length(index._linearIndices); ++i) + { + if (!empty(index._linearIndices[i])) + { + linearMinOffset = front(index._linearIndices[i]); + if (linearMinOffset != 0u) + break; + for (unsigned j = 1; j < length(index._linearIndices[i]); ++j) + { + if (index._linearIndices[i][j] > linearMinOffset) + { + linearMinOffset = index._linearIndices[i][j]; + break; + } + } + if (linearMinOffset != 0u) + break; + } + } + } + else + { + linearMinOffset = back(index._linearIndices[refId]); + } + } + else + { + linearMinOffset = index._linearIndices[refId][windowIdx]; + } + + // Combine candidate bins and smallest required offset from linear index into candidate offset. + typedef std::set TOffsetCandidates; + TOffsetCandidates offsetCandidates; + typedef typename Iterator, Rooted>::Type TCandidateIter; + for (TCandidateIter it = begin(candidateBins, Rooted()); !atEnd(it); goNext(it)) + { + typedef typename std::map::const_iterator TMapIter; + TMapIter mIt = index._binIndices[refId].find(*it); + if (mIt == index._binIndices[refId].end()) + continue; // Candidate is not in index! + + typedef typename Iterator > const, Rooted>::Type TBegEndIter; + for (TBegEndIter it2 = begin(mIt->second.chunkBegEnds, Rooted()); !atEnd(it2); goNext(it2)) + if (it2->i2 >= linearMinOffset) + offsetCandidates.insert(it2->i1); + } + + // Search through candidate offsets, find rightmost possible. + // + // Note that it is not necessarily the first. + // + // TODO(holtgrew): Can this be optimized similar to how bamtools does it? + typedef typename TOffsetCandidates::const_iterator TOffsetCandidateIter; + BamAlignmentRecord record; + for (TOffsetCandidateIter candIt = offsetCandidates.begin(); candIt != offsetCandidates.end(); ++candIt) + { + setPosition(bamFile, *candIt); + + readRecord(record, bamFile); + + // std::cerr << "record.beginPos == " << record.beginPos << "\n"; + // int32_t endPos = record.beginPos + getAlignmentLengthInRef(record); + if (record.rID != refId) + continue; // Wrong contig. + if (!hasAlignments || record.beginPos <= pos) + { + // Found a valid alignment. + hasAlignments = true; + offset = *candIt; + } + + if (record.beginPos >= posEnd) + break; // Cannot find overlapping any more. + } + + if (offset != MaxValue::VALUE) + setPosition(bamFile, offset); + + // Finding no overlapping alignment is not an error, hasAlignments is false. + return true; +} + +// ---------------------------------------------------------------------------- +// Function jumpToOrphans() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamFileIn#jumpToOrphans + * @brief Seek to orphans block in BamFileIn using an index. + * + * @signature bool jumpToOrphans(bamFileIn, hasAlignments, index); + * + * @param[in,out] bamFileIn The @link BamFileIn @endlink object to jump with. + * @param[out] hasAlignments A bool that is set to true if there are any orphans. + * @param[in] index The @link BamIndex @endlink to use for jumping. + */ + +template +bool jumpToOrphans(FormattedFile & bamFile, + bool & hasAlignments, + BamIndex const & index) +{ + if (!isEqual(format(bamFile), Bam())) + return false; + + hasAlignments = false; + + // Search linear indices for the largest entry of all references. + uint64_t aliOffset = MaxValue::VALUE; + for (int i = length(index._linearIndices) - 1; i >= 0; --i) + if (!empty(index._linearIndices[i])) + { + aliOffset = back(index._linearIndices[i]); + break; + } + if (aliOffset == MaxValue::VALUE) + return false; // No offset found. + + // Get index of the first orphan alignment by seeking from linear index bucket. + BamAlignmentRecord record; + uint64_t offset = MaxValue::VALUE; + uint64_t result = 0; + if (!setPosition(bamFile, aliOffset)) + return false; // Error while seeking. + while (!atEnd(bamFile)) + { + result = position(bamFile); + readRecord(record, bamFile); + if (record.rID == -1) + { + // Found alignment. + hasAlignments = true; + offset = result; + break; + } + } + + // Jump back to the first alignment. + if (offset != MaxValue::VALUE) + { + if (!setPosition(bamFile, offset)) + return false; // Error while seeking. + } + + // Finding no orphan alignment is not an error, hasAilgnments is false then. + return true; +} + +// ---------------------------------------------------------------------------- +// Function getUnalignedCount() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamIndex#getUnalignedCount + * @brief Query index for number of unaligned reads. + * + * @signature uint64_t getUnalignedCount(index); + * + * @param[in] index Index to query. + * @return uint64_t The number of unaligned reads. + */ + +inline uint64_t +getUnalignedCount(BamIndex const & index) +{ + return index._unalignedCount; +} + +// ---------------------------------------------------------------------------- +// Function open() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamIndex#open + * @brief Load a BAM index from a given file name. + * @signature bool open(index, filename); + + * @param[in,out] index Target data structure. + * @param[in] filename Path to file to load. Types: char const * + * + * @return bool Returns true on success, false otherwise. + */ + +inline bool +open(BamIndex & index, char const * filename) +{ + std::fstream fin(filename, std::ios::binary | std::ios::in); + if (!fin.good()) + return false; // Could not open file. + + // Read magic number. + CharString buffer; + resize(buffer, 4); + fin.read(&buffer[0], 4); + if (!fin.good()) + return false; + if (buffer != "BAI\1") + return false; // Magic number is wrong. + + int32_t nRef = 0; + fin.read(reinterpret_cast(&nRef), 4); + if (!fin.good()) + return false; + + resize(index._linearIndices, nRef); + resize(index._binIndices, nRef); + + for (int i = 0; i < nRef; ++i) // For each reference. + { + // Read bin index. + int32_t nBin = 0; + fin.read(reinterpret_cast(&nBin), 4); + if (!fin.good()) + return false; + index._binIndices[i].clear(); + BaiBamIndexBinData_ data; + for (int j = 0; j < nBin; ++j) // For each bin. + { + clear(data.chunkBegEnds); + + uint32_t bin = 0; + fin.read(reinterpret_cast(&bin), 4); + if (!fin.good()) + return false; + + int32_t nChunk = 0; + fin.read(reinterpret_cast(&nChunk), 4); + if (!fin.good()) + return false; + reserve(data.chunkBegEnds, nChunk); + for (int k = 0; k < nChunk; ++k) // For each chunk; + { + uint64_t chunkBeg = 0; + uint64_t chunkEnd = 0; + fin.read(reinterpret_cast(&chunkBeg), 8); + fin.read(reinterpret_cast(&chunkEnd), 8); + if (!fin.good()) + return false; + appendValue(data.chunkBegEnds, Pair(chunkBeg, chunkEnd)); + } + + // Copy bin data into index. + index._binIndices[i][bin] = data; + } + + // Read linear index. + int32_t nIntv = 0; + fin.read(reinterpret_cast(&nIntv), 4); + if (!fin.good()) + return false; + clear(index._linearIndices[i]); + reserve(index._linearIndices[i], nIntv); + for (int j = 0; j < nIntv; ++j) + { + uint64_t ioffset = 0; + fin.read(reinterpret_cast(&ioffset), 8); + if (!fin.good()) + return false; + appendValue(index._linearIndices[i], ioffset); + } + } + + if (!fin.good()) + return false; + + // Read (optional) number of alignments without coordinate. + uint64_t nNoCoord = 0; + fin.read(reinterpret_cast(&nNoCoord), 8); + if (!fin.good()) + { + fin.clear(); + nNoCoord = 0; + } + index._unalignedCount = nNoCoord; + + return true; +} + +// TODO(holtgrew): This is only here because of the read() function with TSequence in old file.h. + +inline bool +open(BamIndex & index, char * filename) +{ + return open(index, static_cast(filename)); +} + +// --------------------------------------------------------------------------- +// Function save() +// --------------------------------------------------------------------------- + +/*! + * @fn BamIndex#save + * @brief Save a BamIndex object. + * + * @signature bool save(baiIndex, baiFileName); + * + * @param[in] baiIndex The BamIndex to write out. + * @param[in] baiFileName The name of the BAI file to write to. + * + * @return bool true on success, false otherwise. + */ + +inline bool save(BamIndex const & index, char const * baiFilename) +{ + // Open output file. + std::ofstream out(baiFilename, std::ios::binary | std::ios::out); + + SEQAN_ASSERT_EQ(length(index._binIndices), length(index._linearIndices)); + + // Write header. + out.write("BAI\1", 4); + int32_t numRefSeqs = length(index._binIndices); + out.write(reinterpret_cast(&numRefSeqs), 4); + + // Write out indices. + typedef BamIndex const TBamIndex; + typedef TBamIndex::TBinIndex_ const TBinIndex; + typedef TBinIndex::const_iterator TBinIndexIter; + typedef TBamIndex::TLinearIndex_ TLinearIndex; + for (int i = 0; i < numRefSeqs; ++i) + { + TBinIndex const & binIndex = index._binIndices[i]; + TLinearIndex const & linearIndex = index._linearIndices[i]; + + // Write out binning index. + int32_t numBins = binIndex.size(); + out.write(reinterpret_cast(&numBins), 4); + for (TBinIndexIter itB = binIndex.begin(), itBEnd = binIndex.end(); itB != itBEnd; ++itB) + { + // Write out bin id. + out.write(reinterpret_cast(&itB->first), 4); + // Write out number of chunks. + uint32_t numChunks = length(itB->second.chunkBegEnds); + out.write(reinterpret_cast(&numChunks), 4); + // Write out all chunks. + typedef Iterator > const, Rooted>::Type TChunkIter; + for (TChunkIter itC = begin(itB->second.chunkBegEnds); !atEnd(itC); goNext(itC)) + { + out.write(reinterpret_cast(&itC->i1), 8); + out.write(reinterpret_cast(&itC->i2), 8); + } + } + + // Write out linear index. + int32_t numIntervals = length(linearIndex); + out.write(reinterpret_cast(&numIntervals), 4); + typedef Iterator const, Rooted>::Type TLinearIndexIter; + for (TLinearIndexIter it = begin(linearIndex, Rooted()); !atEnd(it); goNext(it)) + out.write(reinterpret_cast(&*it), 8); + } + + // Write the number of unaligned reads if set. + //std::cerr << "UNALIGNED\t" << index._unalignedCount << std::endl; + if (index._unalignedCount != maxValue()) + out.write(reinterpret_cast(&index._unalignedCount), 8); + + return out.good(); // false on error, true on success. +} + + +inline void _baiAddAlignmentChunkToBin(BamIndex & index, + uint32_t currBin, + uint32_t currOffset, + uint64_t prevOffset) +{ + // If this is not the first reference sequence then add previous reference data. + Pair newChunk(currOffset, prevOffset); + + // If no interest exists yet for this bin, create one and store alignment chunk. + BamIndex::TBinIndex_::iterator binIter = back(index._binIndices).find(currBin); + if (binIter == back(index._binIndices).end()) + { + BaiBamIndexBinData_ binData; + appendValue(binData.chunkBegEnds, newChunk); + back(index._binIndices).insert(std::make_pair(currBin, binData)); + } + else + { + // Otherwise, just append alignment chunk. + appendValue(binIter->second.chunkBegEnds, newChunk); + } +} + +// --------------------------------------------------------------------------- +// Function build() +// --------------------------------------------------------------------------- +// TODO(dadi): uncomment when BamIndex.build index is fixed. DOX commented out +/* + * @fn BamIndex#build + * @brief Create a BamIndex from BAM file. + * + * @signature bool build(baiIndex, bamFileName); + * + * @param[out] baiIndex The BamIndex to build into. + * @param[in] bamFileName Path to the BAM file to build an index for. Type: char const *. + * + * @return bool true on success, false otherwise. + */ +inline bool build(BamIndex & index, char const * bamFilename) +{ + // SEQAN_FAIL("This does not work yet!"); + + index._unalignedCount = 0; + clear(index._binIndices); + clear(index._linearIndices); + + // Open BAM file for reading. + BamFileIn bamFile; + if (!open(bamFile, bamFilename)) + return false; // Could not open BAM file. + + // Read BAM header. + BamHeader header; + readHeader(header, bamFile); + + uint32_t numRefSeqs = length(contigNames(context(bamFile))); + + // Scan over BAM file and create index. + BamAlignmentRecord record; + uint32_t currBin = maxValue(); + uint32_t prevBin = maxValue(); + int32_t currRefId = BamAlignmentRecord::INVALID_REFID; + int32_t prevRefId = BamAlignmentRecord::INVALID_REFID; + uint64_t currOffset = position(bamFile); + uint64_t prevOffset = currOffset; + int32_t prevPos = minValue(); + + while (!atEnd(bamFile)) + { + // Load next record. + readRecord(record, bamFile); + + // Check ordering. + if (prevRefId == record.rID && prevPos > record.beginPos) + return false; + + // The reference sequence changed, close bins for previous reference. + if (prevRefId != record.rID) + { + if (prevRefId != BamAlignmentRecord::INVALID_REFID) + { + _baiAddAlignmentChunkToBin(index, currBin, currOffset, prevOffset); + + // Add an index for all empty references between prevRefId (excluded) and record.rID (included). + for (int i = prevRefId + 1; i < record.rID; ++i) + { + BamIndex::TBinIndex_ binIndex; + appendValue(index._binIndices, binIndex); + BamIndex::TLinearIndex_ linearIndex; + appendValue(index._linearIndices, linearIndex); + } + + // Update bin book keeping. + currOffset = prevOffset; + currBin = record.bin; + prevBin = record.bin; + currRefId = record.rID; + } + else + { + // Otherwise, this is the first pass. Create an index for all empty references up to and including + // current refId. + for (int i = 0; i < record.rID; ++i) + { + BamIndex::TBinIndex_ binIndex; + appendValue(index._binIndices, binIndex); + BamIndex::TLinearIndex_ linearIndex; + appendValue(index._linearIndices, linearIndex); + } + } + + // Update reference book keeping. + prevRefId = record.rID; + prevBin = minValue(); + } + + // If the alignment's reference id is valid and its bin is not a leaf. + if (record.rID >= 0 && record.bin < 4681) + { + int32_t beginOffset = record.beginPos >> BamIndex::BAM_LIDX_SHIFT; + int32_t endPos = getAlignmentLengthInRef(record); + int32_t endOffset = (endPos - 1) >> BamIndex::BAM_LIDX_SHIFT; + + // Resize linear index if necessary. + unsigned oldSize = length(index._linearIndices); + unsigned newSize = endOffset + 1; + if (oldSize < newSize) + resize(back(index._linearIndices), newSize, 0); + + // Store offset. + for (int i = beginOffset + 1; i <= endOffset; ++i) + if (back(index._linearIndices)[i] == 0u) + back(index._linearIndices)[i] = prevOffset; + } + + // Handle the case if we changed to a new BAI bin. + if (record.bin != prevBin) + { + // If not first bin of reference, save previous bin data. + if (currBin != maxValue()) + _baiAddAlignmentChunkToBin(index, currBin, currOffset, prevOffset); + + // Update markers. + currOffset = prevOffset; + currBin = record.bin; + prevBin = record.bin; + currRefId = record.rID; + + // If the reference id is invalid then break out. + if (currRefId < 0) + break; + } + + // Make sure that the current file pointer is beyond prevOffset. + if (position(bamFile) <= static_cast(prevOffset)) + return false; // Calculating offsets failed. + + // Update prevOffset and prevPos. + prevOffset = position(bamFile); + prevPos = record.beginPos; + } + + // Count remaining unaligned records. + while (!atEnd(bamFile)) + { + SEQAN_ASSERT_GT(index._unalignedCount, 0u); + + readRecord(record, bamFile); + if (record.rID >= 0) + return false; // Could not read record. + + index._unalignedCount += 1; + } + + // After loading all alignments, if any data was read, perform checks. + if (currRefId >= 0) + { + // Store last alignment chunk to its bin and then write last reference entry with data. + _baiAddAlignmentChunkToBin(index, currBin, currOffset, prevOffset); + + // Finally, write any empty references remaining at end of file. + SEQAN_ASSERT_GEQ(numRefSeqs, length(index._binIndices)); + BamIndex::TBinIndex_ binIndex; + resize(index._binIndices, numRefSeqs, binIndex); // TODO(holtgrew): binIndex is unnecessary if resize used T() as default value as vector.resize() does. + } + + // Merge small bins if possible. + // SEQAN_FAIL("TODO: Merge bins!"); + return true; +} + + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_BAM_INDEX_BAI_H_ diff --git a/seqan/bam_io/bam_io_context.h b/seqan/bam_io/bam_io_context.h new file mode 100644 index 0000000..3bdf2e3 --- /dev/null +++ b/seqan/bam_io/bam_io_context.h @@ -0,0 +1,353 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Class BamIOContext, accessor functions. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_BAM_IO_CONTEXT_H_ +#define INCLUDE_SEQAN_BAM_IO_BAM_IO_CONTEXT_H_ + +namespace seqan { + +// ============================================================================ +// Tags +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Tag NameStoreMember +// ---------------------------------------------------------------------------- + +/*! + * @defgroup BamIOContextMemberTag BamIOContext Member Tags + * @brief Defines standard tags used to get the type of the members of the @link BamIOContext @endlink using the @link Member @endlink metafunction. + */ + +/*! + * @tag BamIOContextMemberTag#NameStoreMember + * @brief Tag used to get the type for the NameStore. + * @headerfile + * + * @signature typedef Tag NameStoreMember; + */ + +struct NameStoreMember_; +typedef Tag NameStoreMember; + +// ---------------------------------------------------------------------------- +// Tag NameStoreCacheMember +// ---------------------------------------------------------------------------- + +/*! + * @tag BamIOContextMemberTag#NameStoreCacheMember + * @brief Tag used to get the type for the NameStoreCache. + * @headerfile + * + * @signature typedef Tag NameStoreCacheMember; + */ + +struct NameStoreCacheMember_; +typedef Tag NameStoreCacheMember; + +// ---------------------------------------------------------------------------- +// Tag LengthStoreMember +// ---------------------------------------------------------------------------- + +/*! + * @tag BamIOContextMemberTag#LengthStoreMember + * @brief Tag used to get the type for the LengthStore. + * @headerfile + * + * @signature typedef Tag LengthStoreMember; + */ + +struct LengthStoreMember_; +typedef Tag LengthStoreMember; + +// ============================================================================ +// Classes +// ============================================================================ + +/*! + * @class BamIOContext + * @headerfile + * @brief The I/O context to use for BAM I/O. + * + * @signature template + * class BamIOContext; + * + * @tparam TNameStore The type used to represent the names. + * @tparam TNameStoreCache The type used to cache the names. Defaults to @link NameStoreCache @endlink <TNameStore>l;. + * + * BamIOContext objects store the names of (and provide a cache for) reference contig names. + * + * @section Examples + * + * Creating a @link BamIOContext @endlink for a raw @link StringSet @endlink of @link CharString @endlink. + * + * @code{.cpp} + * StringSet contigNames; + * NameStoreCache > contigNamesCache(contigNames); + * BamIOContext > bamIOContext(contigNames, contigNamesCache); + * // ... + * @endcode + * + * Using a @link BamIOContext @endlink with a @link FragmentStore @endlink. + * + * @code{.cpp} + * typedef FragmentStore<>::TContigNameStore TNameStore; + * typedef NameStoreCache TNameStoreCache; + * FragmentStore<> store; + * // Optionally, do something with store. + * typedef BamIOContext TBamIOContext; + * TBamIOContext bamIOContext(store.contigNameStore, store.contigNameStoreCache); + * // ... + * @endcode + */ + +/*! + * @fn BamIOContext::BamIOContext + * @headerfile + * @brief Constructor. + * + * @signature BamIOContext::BamIOContext(); + * @signature BamIOContext::BamIOContext(contigNameStore, contigNamesStoreCache); + * + * Default constructor or construction with references to sequence and sample names. + */ + +template , + typename TNameStoreCache_ = NameStoreCache, + typename TStorageSpec = void> +class BamIOContext +{ +public: + typedef typename Member::Type TNameStore; + typedef typename Member::Type TNameStoreCache; + typedef typename Member::Type TLengthStore; + + typedef typename If, + Dependent<>, TStorageSpec>::Type TNSStorageSpec; + typedef typename If, + Owner<>, TStorageSpec>::Type TSLStorageSpec; + + typedef typename StorageSwitch::Type TNameStoreMember; + typedef typename StorageSwitch::Type TNameStoreCacheMember; + typedef typename StorageSwitch::Type TLengthStoreMember; + + TNameStoreMember _contigNames; + TNameStoreCacheMember _contigNamesCache; + TLengthStoreMember _contigLengths; + CharString buffer; + String buffers; + String translateFile2GlobalRefId; + + BamIOContext() : + _contigNames(TNameStoreMember()), + _contigNamesCache(ifSwitch(typename IsPointer::Type(), + (TNameStoreCache*)NULL, + _contigNames)), + _contigLengths(TLengthStoreMember()) + {} + + BamIOContext(TNameStore & contigNames_, TNameStoreCache & contigNamesCache_) : + _contigNames(_referenceCast::Type>(contigNames_)), + _contigNamesCache(ifSwitch(typename IsPointer::Type(), + &contigNamesCache_, + _contigNames)), + _contigLengths(TLengthStoreMember()) + {} + + template + BamIOContext(BamIOContext & other) : + _contigNames(_referenceCast::Type>(contigNames(other))), + _contigNamesCache(ifSwitch(typename IsPointer::Type(), + &contigNamesCache(other), + _contigNames)), + _contigLengths(_referenceCast::Type>(contigLengths(other))) + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction NameStore +// ---------------------------------------------------------------------------- + +template +struct Member, + NameStoreMember> +{ + typedef TNameStore Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction NameStoreCache +// ---------------------------------------------------------------------------- + +template +struct Member, + NameStoreCacheMember> +{ + typedef TNameStoreCache Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction LengthStore +// ---------------------------------------------------------------------------- + +template +struct Member, + LengthStoreMember> +{ + typedef String Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function contigNames() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamIOContext#contigNames + * @brief Return reference to contig names from @link BamIOContext @endlink. + * + * @signature TNameStoreRef contigNames(context); + * + * @param[in] context The @link BamIOContext @endlink to query. + * + * @return TNameStoreRef A reference to the TNameStore of the context. + */ + +template +inline TNameStore & +contigNames(BamIOContext & context) +{ + return _referenceCast(context._contigNames); +} + +template +inline TNameStore const & +contigNames(BamIOContext const & context) +{ + return _referenceCast(context._contigNames); +} + +template +inline void +setContigNames(BamIOContext > & context, TNameStore & contigNames) +{ + context._contigNames = &contigNames; +} + +// ---------------------------------------------------------------------------- +// Function contigLengths() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamIOContext#contigLengths + * @brief Return reference to contig lengths from @link BamIOContext @endlink. + * + * @signature TLengthStoreRef contigLengths(context); + * + * @param[in] context The @link BamIOContext @endlink to query. + * + * @return TLengthStoreRef A reference to the TLengthStore of the context. + */ + +template +inline typename BamIOContext::TLengthStore & +contigLengths(BamIOContext & context) +{ + typedef typename BamIOContext::TLengthStore TLengthStore; + return _referenceCast(context._contigLengths); +} + +template +inline typename BamIOContext::TLengthStore const & +contigLengths(BamIOContext const & context) +{ + typedef typename BamIOContext::TLengthStore TLengthStore; + return _referenceCast(context._contigLengths); +} + +template +inline void +setContigLengths(BamIOContext > & context, TLengthStore & contigLengths) +{ + context._contigLengths = &contigLengths; +} + +// ---------------------------------------------------------------------------- +// Function contigNamesCache() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamIOContext#contigNamesCache + * @brief Return reference to contig names cache from @link BamIOContext @endlink. + * + * @signature TNameStoreCacheRef contigNamesCache(context); + * + * @param[in] context The @link BamIOContext @endlink to query. + * + * @return TNameStoreCacheRef A reference to the TNameStoreCache of the context. + */ + +template +inline TNameStoreCache & +contigNamesCache(BamIOContext & context) +{ + return _referenceCast(context._contigNamesCache); +} + +template +inline TNameStoreCache const & +contigNamesCache(BamIOContext const & context) +{ + return _referenceCast(context._contigNamesCache); +} + +template +inline void +setContigNamesCache(BamIOContext > & context, TNameStoreCache & contigNamesCache) +{ + context._contigNamesCache = &contigNamesCache; +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_BAM_IO_CONTEXT_H_ diff --git a/seqan/bam_io/bam_sam_conversion.h b/seqan/bam_io/bam_sam_conversion.h new file mode 100644 index 0000000..4cec8de --- /dev/null +++ b/seqan/bam_io/bam_sam_conversion.h @@ -0,0 +1,369 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// Author: David Weese +// ========================================================================== +// Code to convert between SAM and BAM format tags (textual <-> binary). +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_BAM_SAM_CONVERSION_H_ +#define INCLUDE_SEQAN_BAM_IO_BAM_SAM_CONVERSION_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function assignTagsSamToBam() +// ---------------------------------------------------------------------------- + +template +struct AppendTagsSamToBamOneTagHelper_ +{ + TTarget ⌖ + TBuffer buffer; + char typeC; + + AppendTagsSamToBamOneTagHelper_(TTarget &target, TBuffer buffer, char typeC): + target(target), + buffer(buffer), + typeC(typeC) + {} + + template + bool operator() (Type) + { + if (BamTypeChar::VALUE != typeC) + return false; + + appendRawPod(target, lexicalCast(buffer)); + return true; + } +}; + +template +void _appendTagsSamToBamOneTag(TTarget & target, TForwardIter & iter, CharString & buffer) +{ + write(target, iter, 2); + + clear(buffer); + write(buffer, iter, 3); + SEQAN_ASSERT_EQ(buffer[0], ':'); + SEQAN_ASSERT_EQ(buffer[2], ':'); + + char typeC = buffer[1]; + appendValue(target, typeC); + + switch (typeC) + { + case 'Z': + case 'H': + // BAM string + // TODO(holtgrew): Could test on even length in case of 'H'. + readUntil(target, iter, OrFunctor()); + appendValue(target, '\0'); + break; + + case 'B': + { + // BAM array + + // Read type. + readOne(typeC, iter); + appendValue(target, typeC); + + // Read array contents. + clear(buffer); + readUntil(buffer, iter, OrFunctor()); + + size_t len = length(buffer); + + // Count number of entries (== number of commas after type character). + uint32_t nEntries = 0; + for (size_t i = 0; i != len; ++i) + if (buffer[i] == ',') + ++nEntries; + + // Write out array length. + appendRawPod(target, (uint32_t)nEntries); + + // Write out array values. + size_t startPos = 1; + for (unsigned i = 0; i < nEntries; ++i) + { + SEQAN_ASSERT_LT(startPos, len); + + // search end of current entry + size_t endPos = startPos; + for (; endPos < len; ++endPos) + if (buffer[endPos] == ',') + { + buffer[endPos] = '\0'; + break; + } + + AppendTagsSamToBamOneTagHelper_ func(target, + toCString(buffer) + startPos, + typeC); + if (!tagApply(func, BamTagTypes())) + SEQAN_ASSERT_FAIL("Invalid tag type: %c!", typeC); + + startPos = endPos + 1; + } + break; + } + + default: + { + // BAM simple value + clear(buffer); + readUntil(buffer, iter, OrFunctor()); + + AppendTagsSamToBamOneTagHelper_ func(target, buffer, typeC); + if (!tagApply(func, BamTagTypes())) + SEQAN_ASSERT_FAIL("Invalid tag type: %c!", typeC); + } + } +} + +/*! + * @fn assignTagsSamToBam + * @headerfile + * @brief Assign tags in SAM format to tags in BAM format. + * + * @signature void assignTagsBamToSam(bamTags, samTags); + * + * @param[out] bamTags A sequence of char (e.g. @link CharString @endlink) for the target BAM tags. + * @param[in] samTags A sequence of char (e.g. @link CharString @endlink) for the source SAM tags. + * + * @see assignTagsBamToSam + */ + +template +void appendTagsSamToBam(TTarget & target, TSource const & source) +{ + // Handle case of empty source sequence. + if (empty(source)) + return; + + typedef typename Iterator::Type TSourceIter; + TSourceIter it = begin(source, Rooted()); + + CharString buffer; + + while (!atEnd(it)) + { + if (value(it) == '\t') + skipOne(it); + + _appendTagsSamToBamOneTag(target, it, buffer); + } +} + +template +void assignTagsSamToBam(TTarget & target, TSource const & source) +{ + clear(target); + appendTagsSamToBam(target, source); +} + +// ---------------------------------------------------------------------------- +// Function assignTagsBamToSam() +// ---------------------------------------------------------------------------- + +template +struct AssignTagsBamToSamOneTagHelper_ +{ + TTarget ⌖ + TSourceIter ⁢ + char typeC; + + AssignTagsBamToSamOneTagHelper_(TTarget &target, TSourceIter &it, char typeC): + target(target), + it(it), + typeC(typeC) + {} + + template + bool operator() (Type) + { + if (BamTypeChar::VALUE != typeC) + return false; + + appendNumber(target, reinterpret_cast(*it)); + it += sizeof(Type); + return true; + } + + bool operator() (char) + { + if (BamTypeChar::VALUE != typeC) + return false; + + writeValue(target, getValue(it)); + ++it; + return true; + } +}; + +template +void _appendTagsBamToSamOneTag(TTarget & target, TSourceIter & it) +{ + // Copy tag name. + SEQAN_ASSERT_NOT(atEnd(it)); + writeValue(target, *it++); + SEQAN_ASSERT_NOT(atEnd(it)); + writeValue(target, *it++); + + // Add ':'. + writeValue(target, ':'); + + char typeC = *it++; + char c = FunctorLowcase()(typeC); + + // The only integer type supported is a 32bit signed int (SAM Format Spec, 28 Feb 2014, Section 1.5) + // This sucks as this projection is not identically reversible + if (c == 'c' || c == 's' || c == 'i') + writeValue(target, 'i'); + else + writeValue(target, typeC); + + // Add ':'. + writeValue(target, ':'); + + switch (typeC) + { + case 'Z': + case 'H': + // BAM string + SEQAN_ASSERT_NOT(atEnd(it)); + while (*it != '\0') + { + writeValue(target, *it); + ++it; + SEQAN_ASSERT_NOT(atEnd(it)); + } + ++it; + break; + + case 'B': + { + // BAM array + typeC = *it++; + writeValue(target, typeC); + AssignTagsBamToSamOneTagHelper_ func(target, it, typeC); + + // Read array length. + union { + char raw[4]; + unsigned len; + } tmp; + for (unsigned i = 0; i < 4; ++i) + { + SEQAN_ASSERT_NOT(atEnd(it)); + tmp.raw[i] = *it++; + } + for (unsigned i = 0; i < tmp.len; ++i) + { + writeValue(target, ','); + if (!tagApply(func, BamTagTypes())) + SEQAN_ASSERT_FAIL("Invalid tag type: %c!", typeC); + } + break; + } + + default: + { + // BAM simple value + AssignTagsBamToSamOneTagHelper_ func(target, it, typeC); + if (!tagApply(func, BamTagTypes())) + SEQAN_ASSERT_FAIL("Invalid tag type: %c!", typeC); + } + } +} + +/*! + * @fn assignTagsBamToSam + * @headerfile + * @brief Assign tags in BAM format to tags in SAM format. + * + * @signature void assignTagsBamToSam(samTags, bamTags); + * + * @param[out] samTags A sequence of char (e.g. @link CharString @endlink) for the target SAM tags. + * @param[in] bamTags A sequence of char (e.g. @link CharString @endlink) for the source BAM tags. + * + * @see assignTagsSamToBam + */ + +template +inline void +appendTagsBamToSam(TTarget & target, TSource const & source) +{ + if (empty(source)) + return; + + typedef typename Iterator::Type TSourceIter; + TSourceIter it = begin(source, Rooted()); + + while (true) + { + _appendTagsBamToSamOneTag(target, it); + if (atEnd(it)) + return; + writeValue(target, '\t'); + } +} + +template +void assignTagsBamToSam(TTarget & target, TSource const & source) +{ + clear(target); + appendTagsBamToSam(target, source); +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_BAM_SAM_CONVERSION_H_ diff --git a/seqan/bam_io/bam_scanner_cache.h b/seqan/bam_io/bam_scanner_cache.h new file mode 100644 index 0000000..bbc1f42 --- /dev/null +++ b/seqan/bam_io/bam_scanner_cache.h @@ -0,0 +1,309 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_BAM_SCANNER_CACHE_H_ +#define INCLUDE_SEQAN_BAM_IO_BAM_SCANNER_CACHE_H_ + +#include +#include + +namespace seqan { + +using namespace std; + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +struct BamScannerCacheKey_ +{ + int32_t rID; + int32_t beginPos; + uint64_t qnameHash; + + bool operator== (BamScannerCacheKey_ const &other) const + { + return rID == other.rID && beginPos == other.beginPos && qnameHash == other.qnameHash; + } +}; + +struct BamScannerCacheSearchKey_ +{ + typedef uint16_t TFlag; + + BamScannerCacheKey_ cacheKey; + TFlag flags; + TFlag flagsMask; +}; + +struct BamScannerCacheHash_ : + std::unary_function +{ + size_t operator()(BamScannerCacheKey_ const &v) const + { + return std::hash()(v.rID) ^ std::hash()(v.beginPos) ^ std::hash()(v.qnameHash); + } +}; + +class BamScannerCache +{ +public: + // The Key is a pair of (genomic pos, name) where genomic pos is a pair of (rId, pos). + typedef String TRecords; + typedef Size::Type TRecordId; + typedef BamScannerCacheKey_ TKey; + + // A mapping from the key type to the BamAlignmentRecord at this position. + typedef unordered_multimap TMap; + typedef TMap::const_iterator TMapIter; + + TRecords records; + String unusedIds; + TMap map; + BamAlignmentRecord tmpRecord; + + static const TRecordId INVALID_ID = (TRecordId)-1; +}; + + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +template +uint64_t _suffixHash(TSequence const &sequence) +{ + typedef typename Iterator::Type TIter; + typedef typename Value::Type TValue; + typedef typename Size::Type TSize; + + const uint64_t ALPH_SIZE = ValueSize::VALUE; + const unsigned MAX_LEN = LogN<~(ALPH_SIZE - 1) / ALPH_SIZE, ALPH_SIZE>::VALUE + 1; + + TSize len = length(sequence); + TIter itEnd = end(sequence, Standard()); + + if (len > 2 && (sequence[len - 2] == ':' || sequence[len - 2] == '/')) + { + len -= 2; + itEnd -= 2; + } + + if (len > MAX_LEN) + len = MAX_LEN; + + TIter it = itEnd - len; + + uint64_t hash = 0; + for (; it != itEnd; ++it) + hash = hash * ALPH_SIZE + ordValue(*it); + return hash; +} + +inline void +insertRecord(BamScannerCache &cache, seqan::BamAlignmentRecord const &record) +{ + int _id; + if (empty(cache.unusedIds)) + { + _id = length(cache.records); + appendValue(cache.records, record); + } + else + { + _id = back(cache.unusedIds); + eraseBack(cache.unusedIds); + cache.records[_id] = record; + } + + BamScannerCache::TKey key = { record.rID, record.beginPos, _suffixHash(record.qName) }; + cache.map.insert(std::make_pair(key, _id)); +} + +template +inline bool +_qNamesEqual(TQName1 const &name1, TQName2 const &name2) +{ + unsigned len1 = length(name1); + unsigned len2 = length(name2); + + if (len1 != len2) + return false; + + if (len1 > 2 && len2 > 2) + { + if (name1[len1 - 2] == ':' || name1[len1 - 2] == '/') + return prefix(name1, len1 - 1) == prefix(name2, len2 - 1); + } + return name1 == name2; +} + + +// search a certain segment that might refer to lastRecord +// if recursively search for a intermediate segments that might refer to lastRecord +inline bool +_recursivelyFindSegmentGraph( + String &records, + BamScannerCacheSearchKey_ &searchKey, + unsigned segmentNo, + BamScannerCache &cache) +{ + typedef BamScannerCache::TMapIter TMapIter; + typedef BamScannerCacheSearchKey_::TFlag TFlag; + + // search for segment using contigId, position + std::pair range = cache.map.equal_range(searchKey.cacheKey); + for (TMapIter iter = range.first; iter != range.second;) + { + TMapIter it = iter; + ++iter; + BamAlignmentRecord &record = cache.records[it->second]; + + // ... additionally check flags and qName + if ((record.flag & searchKey.flagsMask) == searchKey.flags && + _qNamesEqual(record.qName, records[0].qName)) + { + if (record.rNextId == records[0].rID && record.pNext == records[0].beginPos) + { + resize(records, segmentNo + 2); + records[segmentNo + 1] = records[0]; + records[segmentNo] = record; + appendValue(cache.unusedIds, it->second); + cache.map.erase(it); + return true; + } + } + } + + for (; range.first != range.second; ++range.first) + { + BamAlignmentRecord &record = cache.records[range.first->second]; + + // ... additionally check flags and qName + if ((record.flag & searchKey.flagsMask) == searchKey.flags && + _qNamesEqual(record.qName, records[0].qName)) + { + BamScannerCacheSearchKey_ newSearchKey = { + { record.rNextId, record.pNext, searchKey.cacheKey.qnameHash }, + static_cast((record.flag & BAM_FLAG_MULTIPLE) | ((record.flag & BAM_FLAG_NEXT_RC) >> 1)), + BAM_FLAG_MULTIPLE | BAM_FLAG_RC + }; + if (_recursivelyFindSegmentGraph(records, newSearchKey, segmentNo + 1, cache)) + { + records[segmentNo] = record; + appendValue(cache.unusedIds, range.first->second); + cache.map.erase(range.first); + return true; + } + } + } + + return false; +} + + +inline void +readMultiRecords(String &records, BamFileIn &bamFile, BamScannerCache &cache) +{ + typedef BamScannerCacheSearchKey_::TFlag TFlag; + + if (empty(records)) + resize(records, 1); + + while (!atEnd(bamFile)) + { + // read next record + BamAlignmentRecord &record = records[0]; + readRecord(record, bamFile); + + // is this a single-end read or single alignment? + if (!hasFlagMultiple(record) || + record.rID == BamAlignmentRecord::INVALID_REFID || + record.beginPos == BamAlignmentRecord::INVALID_POS || + record.rNextId == BamAlignmentRecord::INVALID_REFID || + record.pNext == BamAlignmentRecord::INVALID_POS) + { + resize(records, 1); + return; + } + + if (record.rID < record.rNextId || (record.rID == record.rNextId && record.beginPos < record.pNext)) + { + // store record to retrieve it later + insertRecord(cache, record); + continue; + } + + // search mates in case of multiple templates + BamScannerCacheSearchKey_ searchKey = { + { record.rNextId, record.pNext, _suffixHash(record.qName) }, + static_cast((record.flag & BAM_FLAG_MULTIPLE) | ((record.flag & BAM_FLAG_NEXT_RC) >> 1)), + BAM_FLAG_MULTIPLE | BAM_FLAG_RC + }; + if (_recursivelyFindSegmentGraph(records, searchKey, 0, cache)) + { + // order paired-end reads by first and second segment in the template +// if (length(records) == 2) +// { +// if (hasFlagLast(records[0])) +// std::swap(records[0], records[1]); +// } + return; + } + else + { + // we could get here if both mates align to same position and we are the first + // hence, insert our record to be retrieved by the second. + if (records[0].beginPos != records[0].pNext) + { + std::cerr << "WARNING: Mate could not be found for:\n"; + write(std::cerr, records[0], context(bamFile), seqan::Sam()); + } + insertRecord(cache, records[0]); + } + } + clear(records); +} + +} // namespace seqan; + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_BAM_SCANNER_CACHE_H_ diff --git a/seqan/bam_io/bam_tags_dict.h b/seqan/bam_io/bam_tags_dict.h new file mode 100644 index 0000000..05ddae5 --- /dev/null +++ b/seqan/bam_io/bam_tags_dict.h @@ -0,0 +1,890 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// Author: David Weese +// ========================================================================== +// Code for read/write access to BAM tag dicts. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_BAM_TAGS_DICT_H_ +#define INCLUDE_SEQAN_BAM_IO_BAM_TAGS_DICT_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +class BamTagsDict; + +inline bool hasIndex(BamTagsDict const & bamTags); +inline void buildIndex(BamTagsDict const & bamTags); + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Host +// ---------------------------------------------------------------------------- + +template <> +struct Host +{ + typedef CharString Type; +}; + +template <> +struct Host +{ + typedef CharString const Type; +}; + +template <> +struct Size +{ + typedef unsigned Type; +}; + +template <> +struct Position +{ + typedef unsigned Type; +}; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @class BamTagsDict + * @headerfile + * @brief Indexes start positions of BAM tags in a @link CharString @endlink and provides a dict-like API. + * + * @signature class BamTagsDict; + * + * @section Example + * + * @include demos/dox/bam_io/bam_tags_dict.cpp + * + * Output is: + * + * @include demos/dox/bam_io/bam_tags_dict.cpp.stdout + * + * @see getBamTypeSize + * @see getBamTypeChar + */ + +/*! + * @fn BamTagsDict::BamTagsDict + * @brief Constructor + * + * @signature BamTagsDict::BamTagsDict(); + * @signature BamTagsDict::BamTagsDict(tags); + * + * @param[in,out] tags The tags string of a @link BamAlignmentRecord @endlink to be indexed and or modified. + * + * Note, the second constructor stores a reference to tags using a @link Holder @endlink. + * In case of modifying the BamTagsDict by adding or removing tags those changes will be transparently transferred + * to the origin of tags. + */ + +class BamTagsDict +{ +public: + typedef Host::Type TBamTagsSequence; + typedef RemoveConst::Type TBamTagsSeqNonConst; + typedef Position::Type TPos; + + Holder _host; + mutable String _positions; + + BamTagsDict() {} + + explicit + BamTagsDict(TBamTagsSeqNonConst & tags) : _host(tags) {} + + explicit + BamTagsDict(TBamTagsSeqNonConst const & tags) : _host(tags) {} + + template + inline Infix::Type>::Type + operator[] (TPos pos) const + { + if (!hasIndex(*this)) + buildIndex(*this); + return infix(host(*this), _positions[pos], _positions[pos + 1]); + } +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function host() +// ---------------------------------------------------------------------------- + +inline Host::Type & +host(BamTagsDict & bamTags) +{ + return value(bamTags._host); +} + +inline Host::Type & +host(BamTagsDict const & bamTags) +{ + return value(bamTags._host); +} + +// ---------------------------------------------------------------------------- +// Function hasIndex() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamTagsDict#hasIndex + * @brief Returns whether the BamTagsDict has an index. + * + * @signature bool hasIndex(tagsDict); + * + * @param[in] tagsDict The @link BamTagsDict @endlink to query. + * + * @return bool true if dict has an index and false otherwise. + */ + +inline bool +hasIndex(BamTagsDict const & bamTags) +{ + return !empty(bamTags._positions) || empty(host(bamTags)); +} + +// ---------------------------------------------------------------------------- +// Function getBamTypeSize() +// ---------------------------------------------------------------------------- + +/*! + * @fn getBamTypeSize + * @headerfile + * @brief Return size of the type identified by a type char. + * + * @signature int getBamTypeSize(c); + * + * @param[in] c A char that identifies a type. + * + * @return int The size of the type in bytes, -1 for variable-length types, -2 for invalid paramters. + * + * @see BamTagsDict + * @see getBamTypeChar + */ + +// Return sizeof() of the type identified with the given char. Returns -2 if not +// valid, -1 if of variable length. + +struct GetBamTypeSizeHelper_ +{ + int &resultSize; + char typeC; + + GetBamTypeSizeHelper_(int &resultSize, char typeC) : + resultSize(resultSize), + typeC(typeC) + {} + + template + bool operator() (Type) const + { + if (BamTypeChar::VALUE != typeC) + return false; + + resultSize = sizeof(Type); + return true; + } +}; + + +inline int +getBamTypeSize(char c) +{ + switch (toUpperValue(c)) + { + case 'Z': + case 'H': + case 'B': + return -1; + + default: + int result = -2; + GetBamTypeSizeHelper_ func(result, c); + tagApply(func, BamTagTypes()); + return result; + } +} + +// ---------------------------------------------------------------------------- +// Function buildIndex() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamTagsDict#buildIndex + * @brief Build index for a BamTagsDict object. + * + * @signature void buildIndex(tagsDict); + * + * @param[in,out] tagsDict The BamTagsDict object to build the index for. + */ + +inline void +buildIndex(BamTagsDict const & bamTags) +{ + typedef Host::Type TTagString; + typedef Iterator::Type TIter; + + clear(bamTags._positions); + if (empty(host(bamTags))) + return; // Done. + + appendValue(bamTags._positions, 0); + TIter itBegin = begin(host(bamTags), Standard()); + TIter itEnd = end(host(bamTags), Standard()); + for (TIter it = itBegin; it != itEnd; ) + { + SEQAN_ASSERT(it < itEnd); + // skip tag name (e.g. "NM") + it += 2; + + // get tag type (e.g. 'I') + char c = *(it++); + if (c == 'H' || c == 'Z') + { + // skip string and its end-of-string marker + while (*it != '\0') + { + ++it; + SEQAN_ASSERT(it != itEnd); + } + ++it; + } + else if (c == 'B') + { + // skip array of PODs + c = *(it++); + union { + char raw[4]; + uint32_t len; + } tmp; + arrayCopyForward(it, it + 4, tmp.raw); + it += 4 + tmp.len * getBamTypeSize(c); + } + else + { + // skip POD type (e.g. byte, int) + it += getBamTypeSize(c); + } + appendValue(bamTags._positions, it - itBegin); + } + // if (!empty(value(bamTags._host))) + // appendValue(bamTags._positions, length(host(bamTags)) + 1); // +1 since there is not tab at the end +} + +// ---------------------------------------------------------------------------- +// Function _dataHost() +// ---------------------------------------------------------------------------- + +inline Holder::Type> & +_dataHost(BamTagsDict & bamTags) +{ + return bamTags._host; +} + +inline Holder::Type> const & +_dataHost(BamTagsDict const & bamTags) +{ + return bamTags._host; +} + +// ---------------------------------------------------------------------------- +// Function setHost() +// ---------------------------------------------------------------------------- + +template +inline void +setHost(BamTagsDict & me, THost && host_) +{ + setValue(_dataHost(me), std::forward(host_)); + clear(me._positions); +} + +// ---------------------------------------------------------------------------- +// Function length() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamTagsDict#length + * @brief Returns the number of entries in a BamTagsDict. + * + * @signature unsigned length(tagsDict); + * + * @param[in] tagsDict The BamTagsDict object to query for its length. + * + * @return TSize The number of entries in the BamTagsDict. TSize is the result of + * Size<BamTagsDict>::Type. + */ + +inline Size::Type +length(BamTagsDict const & tags) +{ + if (empty(host(tags))) + return 0; + if (!hasIndex(tags)) + buildIndex(tags); + return length(tags._positions) - 1; +} + +// ---------------------------------------------------------------------------- +// Function getTagType() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamTagsDict#getTagType + * @brief Returns the tag type char for an entry of a BamTagsDict. + * + * @signature char getTagType(tagsDict, id); + * + * @param[in] tagsDict The BamTagsDict to query. + * @param[in] id The id of the tag for which to determine the type. See @link BamTagsDict#findTagKey @endlink. + * + * @return char A char that identifies the tag type. + */ + +template +inline char +getTagType(BamTagsDict const & tags, TId id) +{ + return tags[id][2]; +} + +// ---------------------------------------------------------------------------- +// Function getTagKey() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamTagsDict#getTagKey + * @brief Return key of a tag by index. + * + * @signature TKey getTagKey(tagsDict, id); + * + * @param[in] tagsDict The BamTagsDict to query. + * @param[in] id The index of the dict entry. + * + * @return TKey An infix of a @link CharString @endlink. Will be a two-character char sequence. + */ + +template +inline Infix::Type>::Type +getTagKey(BamTagsDict const & tags, TId id) +{ + return prefix(tags[id], 2); +} + +// ---------------------------------------------------------------------------- +// Function findTagKey() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamTagsDict#findTagKey + * @brief Find a tag by its key for a @link BamTagsDict @endlink object. + * + * @signature bool findTagKey(id, tagsDict, key); + * + * @param[out] id The id of the found tag. + * @param[in] tagsDict The BamTagsDict to query. + * @param[in] key The key to query for: @link CharString @endlink. + * + * @return bool true if the key could be found and false otherwise. + */ + +template +inline bool +findTagKey(TId & id, BamTagsDict const & tags, TKey const & key) +{ + for (id = 0; id < (TId)length(tags); ++id) + if (getTagKey(tags, id) == key) + return true; + return false; +} + +// ---------------------------------------------------------------------------- +// Function extractTagValue() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamTagsDict#extractTagValue + * @brief Extract and cast "atomic" value from tags string with index id. + * + * @signature bool extractTagValue(dest, tagsDict, id) + * + * @param[out] dest The variable to write the value to.The value is first copied in a variable of the type indicated in + * the BAM file. Then it is cast into the type of dest. + * + * @param[in] tagsDict The BamTagsDict object to query. + * @param[in] id The id of the tag to extract the value from. See @link BamTagsDict#findTagKey @endlink. + * + * @return bool true if the value could be extracted. + * + * @section Remarks + * + * The function only works for atomic types such as int, not for char* or arrays. + * + * See @link BamTagsDict @endlink for an example. + */ + +template +struct ExtractTagValueHelper_ +{ + TResultType &result; + TIter rawIter; + char typeC; + + ExtractTagValueHelper_(TResultType &result, char typeC, TIter rawIter) : + result(result), + rawIter(rawIter), + typeC(typeC) + {} + + template + bool operator() (Type) const + { + if (BamTypeChar::VALUE != typeC) + return false; + + union { + char raw[sizeof(Type)]; + Type i; + } tmp; + + arrayCopyForward(rawIter, rawIter + sizeof(Type), tmp.raw); + result = static_cast(tmp.i); + return true; + } +}; + +template +SEQAN_FUNC_ENABLE_IF(Is >, bool) +extractTagValue(TResultValue & val, BamTagsDict const & tags, TId id) +{ + typedef Infix::Type>::Type TInfix; + typedef Iterator::Type TIter; + + TInfix inf = tags[id]; + if (length(inf) < 4 || inf[2] == 'Z') + return false; + + TIter it = begin(inf, Standard()) + 2; + char typeC = getValue(it++); + ExtractTagValueHelper_ func(val, typeC, it); + + return tagApply(func, BamTagTypes()); +} + +template +SEQAN_FUNC_ENABLE_IF(IsSequence, bool) +extractTagValue(TResultValue & val, BamTagsDict const & tags, TId id) +{ + typedef Infix::Type>::Type TInfix; + + TInfix inf = tags[id]; + if (length(inf) < 4 || inf[2] != 'Z') + return false; + + val = infix(inf, 3, length(inf) - 1); + return true; +} + +// ---------------------------------------------------------------------------- +// Function getBamTypeChar() +// ---------------------------------------------------------------------------- + +/*! + * @fn getBamTypeChar + * @headerfile + * @brief Return char identifying the type of the argument type. + * + * @signature char getBamTypeChar(); + * @signature BamTypeChar::VALUE + * + * @tparam T The type to query for its type char. + * + * @section Remarks + * + * Note that this function is defined for the int16_t, uint16_t etc. but not for the types + * short, int etc. An exception are 8-bit characters/char, where it is defined for int8_t, + * uint8_t, and char unless char is equal to one of the other two types. This is important + * when used in @link BamTagsDict#setTagValue @endlink etc. since BAM gives type chars for printable characters, signed + * 8-bit numbers and unsigned 8-bit numbers. + * + * If int8_t and uint8_t are not identical to char, we can make this decision from the type, + * otherwise we cannot and we will give the integer types a higher precedence. + * + * In your programs, this should not make any difference, only the written SAM/BAM will differ. + * + * @see BamTagsDict + * @see getBamTypeSize + */ + +template +struct BamTypeChar : + BamTypeChar {}; + +template +inline char getBamTypeChar(T const &) +{ + return BamTypeChar::VALUE; +} + +// ---------------------------------------------------------------------------- +// Function setTagValue() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Test me! + +/*! + * @fn BamTagsDict#setTagValue + * + * @headerfile + * + * @brief Set the value of a tag through a @link BamTagsDict @endlink. + * + * @signature bool setTagValue(tagsDict, key, val[, typeC]); + * + * @param[in,out] tagsDict The BamTagsDict to modify. + * @param[in] key The key of the tag. Must be a sequence of length 2. + * @param[in] val The value to set the tag to. + * @param[in] typeC BAM type char to use. For portability (so the generated files are the same on all platforms), use + * a signed/unsigned qualified type for val or give typeC. Also see the remarks + * for @link getBamTypeChar @endlink. Types: getBamTypeChar@. + * + * @return bool true on success, false on failure. This function can fail if the key is not a valid tag id (e.g. does + * not have length 2) or if the type of val is not an atomic value or a string (anything but + * char *, char const *, a character, integer or float type is invalid). + * + * @section Remarks + * + * Note that setTagValue does not cast the type, so typeC only influences the type character written + * out but val is written out in binary without modification. + * + * @section Examples + * + * An example setting some atomic tag values. + * + * @code{.cpp} + * CharString rawTagsText; + * BamTagsDict tags(rawTagsText); + * setTagValue(tags, "XA", 9); // int + * setTagValue(tags, "XB", 9u); // unsigned int + * setTagValue(tags, "XC", 'X'); // char + * @endcode + * + * If char is equal to int8_t or uint8_t then the last line produces an entry with type 'c' + * or 'C'. To make sure that the type char 'A' (for "printable character") is written to the file, give it explicitely: + * + * @code{.cpp} + * setTagValue(tags, "XC", 'X', 'A'); // Overrwrite XC, enforce type 'printable character'. + * @endcode + * + * Note that on most systems ints have a width of 32 bytes, but the C++ standard leaves this open. For all + * types but characters, you should not give an explicit type char but use one of the types with explicit width and + * signed/unsigned qualifier such as int32_t, uint32_t etc. + * + * @code{.cpp} + * // The following is not recommended since the type of x is not "unsigned 32 bit int." + * int32_t x = -1; + * setTagValue(tags, "XB", x, 'I'); + * // Instead, explicitely use an unsigned type if you need one. Note that your compiler + * // might warn you about assigning -1 to an unsigned variable so you know that you are + * // probably doing something unintended. + * uint32_t y = -1; + * setTagValue(tags, "XB", y); + * + * // Do not do this! + * setTagValue(tags, "XA", 9, 'f'); // BOGUS since 9 is not a floating point number. + * @endcode + * + * @see getBamTypeChar + */ + +template +struct ToBamTagValueHelper_ +{ + TBamValueSequence &result; + TValue val; + char typeC; + + ToBamTagValueHelper_(TBamValueSequence &result, char typeC, TValue val) : + result(result), + val(val), + typeC(typeC) + {} + + template + bool operator() (Type) const + { + if (BamTypeChar::VALUE != typeC) + return false; + + union { + char raw[sizeof(Type)]; + Type i; + } tmp; + + tmp.i = static_cast(val); + append(result, toRange(&tmp.raw[0], &tmp.raw[sizeof(Type)])); + return true; + } +}; + +// Convert "atomic" value to BAM tag. Return whether val was atomic. +template +SEQAN_FUNC_ENABLE_IF(Is >, bool) +_toBamTagValue(TBamValueSequence & result, TValue const & val, char typeC) +{ + if (typeC == 'Z') + return false; + + appendValue(result, typeC); + ToBamTagValueHelper_ func(result, typeC, val); + if (tagApply(func, BamTagTypes())) + return true; + + resize(result, length(result) - 1); + return false; +} + +template +SEQAN_FUNC_ENABLE_IF(IsSequence, bool) +_toBamTagValue(TBamValueSequence & result, TValue const & val, char typeC) +{ + if (typeC != 'Z') + return false; + + appendValue(result, typeC); + append(result, val); + appendValue(result, '\0'); + return true; +} + + +// Sets an atomic value in a BamTagsDict. +// Returns true successful, can fail if val not atomic or key is not a valid tag id (2 chars). + +template +inline bool +setTagValue(BamTagsDict & tags, TKey const & key, TValue const & val, char typeC) +{ + if (!hasIndex(tags)) + buildIndex(tags); + + // Build value to insert/append. + if (length(key) != 2u) + return false; + + Position::Type id = 0; + if (findTagKey(id, tags, key)) + { + CharString bamTagVal; + if (!_toBamTagValue(bamTagVal, val, typeC)) + return false; + + replace(host(tags), tags._positions[id] + 2, tags._positions[id + 1], bamTagVal); + clear(tags._positions); + } + else + { + append(host(tags), key); + if (!_toBamTagValue(host(tags), val, typeC)) + { + resize(host(tags), length(host(tags)) - length(key)); + return false; + } + appendValue(tags._positions, length(host(tags))); + } + + return true; +} + +template +inline bool +setTagValue(BamTagsDict & tags, TKey const & key, TValue const & val) +{ + return setTagValue(tags, key, val, BamTypeChar::VALUE); +} + +/*! + * @fn BamTagsDict#appendTagValue + * + * @headerfile + * + * @brief Append a tag/value pair to a @link BamTagsDict @endlink. + * + * @signature bool appendTagValue(tagsDict, key, val[, typeC]); + * + * @param[in,out] tagsDict The BamTagsDict to modify. + * @param[in] key The key of the tag. Must be a sequence of length 2. + * @param[in] val The value to set the tag to. + * @param[in] typeC BAM type char to use. For portability (so the generated files are the same on all platforms), use + * a signed/unsigned qualified type for val or give typeC. Also see the remarks + * for @link getBamTypeChar @endlink. Types: getBamTypeChar@. + * + * @return bool true on success, false on failure. This function can fail if the key is not a valid tag id (e.g. does + * not have length 2) or if the type of val is not an atomic value or a string (anything but + * char *, char const *, a character, integer or float type is invalid). + * + * @section Remarks + * + * @link BamTagsDict#setTagValue @endlink behaves like appendTagValue if key was not part of tags + * before. However, in this case appendTagValue is faster. + */ + +template +inline bool +appendTagValue(TSequence & tags, TKey const & key, TValue const & val, char typeC) +{ + // Build value to insert/append. + if (length(key) != 2u) + return false; + + append(tags, key); + return _toBamTagValue(tags, val, typeC); +} + +template +inline bool +appendTagValue(BamTagsDict & tags, TKey const & key, TValue const & val, char typeC) +{ + if (appendTagValue(host(tags), key, val, typeC)) + { + appendValue(tags._positions, length(host(tags))); + return true; + } + return false; +} + + +template +inline bool +appendTagValue(TDictOrString & tags, TKey const & key, TValue const & val) +{ + return appendTagValue(tags, key, val, BamTypeChar::VALUE); +} + + +// ---------------------------------------------------------------------------- +// Function eraseTag() +// ---------------------------------------------------------------------------- + +/*! + * @fn BamTagsDict#eraseTag + * @brief Erase a tag from BamTagsDict. + * + * @signature bool eraseTag(tagsDict, key); + * + * @param[in,out] tagsDict The BamTagsDict to erase the tag from. + * @param[in] key The key of the tag to erase. + * + * @return bool true if the tag could be erased, false if the key wasn't present. + */ + +template +inline SEQAN_FUNC_DISABLE_IF(Is >, bool) +eraseTag(BamTagsDict & tags, TKey const & key) +{ + if (!hasIndex(tags)) + buildIndex(tags); + + Position::Type id = 0; + if (!findTagKey(id, tags, key)) + return false; + + erase(host(tags), tags._positions[id], tags._positions[id + 1]); + clear(tags._positions); + return true; +} + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, bool) +eraseTag(BamTagsDict & tags, TId const & id) +{ + typedef typename Iterator, Standard>::Type TIter; + if (!hasIndex(tags)) + buildIndex(tags); + + typename BamTagsDict::TPos delta = tags._positions[id + 1] - tags._positions[id]; + erase(host(tags), tags._positions[id], tags._positions[id + 1]); + erase(tags._positions, id); + TIter it = begin(tags._positions, Standard()) + id; + TIter itEnd = end(tags._positions, Standard()); + for (; it != itEnd; ++it) + *it -= delta; + return true; +} + +// ---------------------------------------------------------------------------- +// Function tagsToBamRecord(); +// ---------------------------------------------------------------------------- + +/*! + * @fn BamTagsDict#tagsToBamRecord + * @brief Writes bam tags to the tags field of the given @link BamAlignmentRecord @endlink. + * + * @signature void tagsToBamRecord(record, tagsDict) + * + * @param[out] record The @link BamAlignmentRecord @endlink whose tags field is overwritten. + * @param[in] tagsDict The @link BamTagsDict @endlink to get the tags from. + * + * This is semantically the same as: + * @code{.cpp} + * record.tags = host(tagsDict); + * @endcode + * + * See @link BamTagsDict @endlink for an example. + */ + + +inline void +tagsToBamRecord(BamAlignmentRecord & record, + BamTagsDict const & dict) +{ + record.tags = host(dict); +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_BAM_TAGS_DICT_H_ diff --git a/seqan/bam_io/cigar.h b/seqan/bam_io/cigar.h new file mode 100644 index 0000000..8a61fef --- /dev/null +++ b/seqan/bam_io/cigar.h @@ -0,0 +1,696 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_CIGAR_H_ +#define INCLUDE_SEQAN_BAM_IO_CIGAR_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// struct CigarElement +// ---------------------------------------------------------------------------- + +/*! + * @class CigarElement + * @headerfile + * @brief One entry of a CIGAR string. + * + * @signature template <[typename TOperation[, typename TCount]]> + * class CigarElement; + * + * @tparam TOperation Type to use for storing operations, defaults to char. + * @tparam TCount Type to use for storing counts, defaults to unsigned. + */ + +/*! + * @fn CigarElement::CigarElement + * @brief Constructor + * + * @signature CigarElement::CigarElement(); + * @signature CigarElement::CigarElement(operation, count); + * + * @param[in] operation The operation to use, of type TOperation. + * @param[in] count The operation count, of type TCount. + * + * @section Remarks + * + * The default constructor initialized both @link CigarElement::operation @endlink and @link CigarElement::count + * @endlink with 0. + */ + +/*! + * @var TCount CigarElement::count; + * + * @brief The number of operations. + */ + +/*! + * @var TOperation CigarElement::operation; + * + * @brief The described operation. + */ + +template +struct CigarElement +{ + typedef TOperation_ TOperation; + typedef TCount_ TCount; + + TOperation operation; + TCount count; + + CigarElement() : operation(0), count(0) {} + + CigarElement(TOperation o, TCount c): + operation(o), + count(c) {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +template +struct Size > +{ + typedef TCount Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +template +inline bool operator>(CigarElement const & lhs, + CigarElement const & rhs) +{ + return lhs.operation > rhs.operation || (lhs.operation == rhs.operation && (lhs.count) > (rhs.count)); +} + +template +inline bool operator<(CigarElement const & lhs, + CigarElement const & rhs) +{ + return lhs.operation < rhs.operation || (lhs.operation == rhs.operation && (lhs.count) < (rhs.count)); +} + +template +inline bool operator==(CigarElement const & lhs, + CigarElement const & rhs) +{ + return lhs.operation == rhs.operation && (lhs.count) == (rhs.count); +} + +// ---------------------------------------------------------------------------- +// toBamCigarElement() +// ---------------------------------------------------------------------------- + +template +[[deprecated("The behavior is not clear. This function should not be used anymore.")]] +uint32_t toBamCigarElement(CigarElement const & cigarElement) +{ + char operation = 0; + switch (cigarElement.operation) { + case 'X': operation += 1; SEQAN_FALLTHROUGH + case '=': operation += 1; SEQAN_FALLTHROUGH + case 'P': operation += 1; SEQAN_FALLTHROUGH + case 'H': operation += 1; SEQAN_FALLTHROUGH + case 'S': operation += 1; SEQAN_FALLTHROUGH + case 'N': operation += 1; SEQAN_FALLTHROUGH + case 'D': operation += 1; SEQAN_FALLTHROUGH + case 'I': operation += 1; SEQAN_FALLTHROUGH + case 'M': break; + } + return (cigarElement.count << 4) | operation; +} + +// ---------------------------------------------------------------------------- +// getMDString() +// ---------------------------------------------------------------------------- + +template < + typename TMDString, + typename TGaps1, + typename TGaps2> +inline unsigned +getMDString( + TMDString &md, + TGaps1 &gaps1, // typically reference + TGaps2 &gaps2) // typically read +{ + typedef typename Value::Type TMDChar; + typedef typename Value::Type>::Type TVal1; + typedef typename Value::Type>::Type TVal2; + + typename Iterator::Type it1 = begin(gaps1); + typename Iterator::Type it2 = begin(gaps2); + char op, lastOp = ' '; + unsigned numOps = 0; + unsigned errors = 0; + + clear(md); + for (; !atEnd(it1) && !atEnd(it2); goNext(it1), goNext(it2)) + { + if (isGap(it1)) + { + if (!isGap(it2)) + ++errors; + continue; // insertion to the reference (gaps1) +// op = 'I'; // ignore insertions completely + } + if (isGap(it2)) + { + ++errors; +// if (op == 'I') // ignore paddings +// continue; + op = 'D'; // deletion from the reference (gaps1) + } + else + { + if ((TVal1)*it1 == (TVal2)*it2) + { + op = 'M'; + } + else + { + op = 'R'; + ++errors; + } + } + + // append match run + if (lastOp != op) + { + if (lastOp == 'M') + { + std::stringstream num; + num << numOps; + append(md, num.str()); + } + numOps = 0; + } + + // append deleted/replaced reference character + if (op != 'M') + { + // add ^ for deleted reference bases (from non-deletion to deletion) + if (op == 'D' && lastOp != 'D') + appendValue(md, '^'); + // add 0 for each replaced base that doesn't follow a match (for samtools/BWA compatibility) + else if (op == 'R' && lastOp != 'M') + appendValue(md, '0'); + appendValue(md, convert(*it1)); + } + + lastOp = op; + ++numOps; + } + SEQAN_ASSERT_EQ(atEnd(it1), atEnd(it2)); + if (lastOp == 'M') + { + std::stringstream num; + num << numOps; + append(md, num.str()); + } + return errors; +} + +// ---------------------------------------------------------------------------- +// getCigarString() +// ---------------------------------------------------------------------------- + +template < + typename TCigar, + typename TGaps1, + typename TGaps2, + typename TThresh> +inline void +getCigarString( + TCigar &cigar, + TGaps1 &gaps1, // typically reference + TGaps2 &gaps2, // typically read + TThresh splicedGapThresh) +{ + typename Iterator::Type it1 = begin(gaps1); + typename Iterator::Type it2 = begin(gaps2); +// typedef typename Value::Type>::Type TVal1; +// typedef typename Value::Type>::Type TVal2; + + clear(cigar); + char op, lastOp = ' '; + unsigned numOps = 0; + + // std::cout << "gaps1\t" << gaps1 << std::endl; + // std::cout << "gaps2\t" << gaps2 << "\t" << clippedBeginPosition(gaps2) << std::endl; + for (; !atEnd(it1) && !atEnd(it2); goNext(it1), goNext(it2)) + { + if (isGap(it1)) + { + if (isGap(it2)) + op = 'P'; + else if (isClipped(it2)) + op = '?'; + else + op = 'I'; + } + else if (isClipped(it1)) + { + op = '?'; + } + else + { + if (isGap(it2)) + op = 'D'; + else if (isClipped(it2)) + op = 'S'; + else + op = 'M'; +// op = ((TVal1)*it1 == (TVal2)*it2)? '=': 'X'; + } + + // append CIGAR operation + if (lastOp != op) + { + if (lastOp == 'D' && numOps >= (unsigned)splicedGapThresh) + lastOp = 'N'; + if (numOps > 0) + { + std::stringstream num; + num << numOps; + append(cigar, num.str()); + appendValue(cigar, lastOp); + } + numOps = 0; + lastOp = op; + } + ++numOps; + } +// if (atEnd(it1) != atEnd(it2)) +// std::cerr << "Invalid pairwise alignment:" << std::endl << gaps1 << std::endl << gaps2 << std::endl; + SEQAN_CHECK(atEnd(it1) == atEnd(it2), "Cannot get CIGAR from invalid pairwise alignment!"); + if (lastOp == 'D' && numOps >= (unsigned)splicedGapThresh) + lastOp = 'N'; + if (numOps > 0) + { + std::stringstream num; + num << numOps; + append(cigar, num.str()); + appendValue(cigar, lastOp); + } +} + +template < + typename TCigar, + typename TGaps1, + typename TGaps2> +inline void +getCigarString( + TCigar &cigar, + TGaps1 &gaps1, // typically reference + TGaps2 &gaps2) // typically read +{ + return getCigarString(cigar, gaps1, gaps2, 20); +} + +template < + typename TOperation, + typename TCount, + typename TSpec, + typename TGaps1, + typename TGaps2, + typename TThresh> +inline void +getCigarString( + String, TSpec> &cigar, + TGaps1 &gaps1, + TGaps2 &gaps2, + TThresh splicedGapThresh) +{ + typename Iterator::Type it1 = begin(gaps1); + typename Iterator::Type it2 = begin(gaps2); +// typedef typename Value::Type>::Type TVal1; +// typedef typename Value::Type>::Type TVal2; + + clear(cigar); + char op = '?', lastOp = ' '; + unsigned numOps = 0; + +// std::cout << gaps1 << std::endl; +// std::cout << gaps2 << std::endl; + for (; !atEnd(it1) && !atEnd(it2); goNext(it1), goNext(it2)) + { + if (isGap(it1)) + { + if (isGap(it2)) + op = 'P'; + else if (isClipped(it2)) + op = '?'; + else + op = 'I'; + } + else if (isClipped(it1)) + { + op = '?'; + } + else + { + if (isGap(it2)) + op = 'D'; + else if (isClipped(it2)) + op = 'S'; + else +// op = ((TVal1)*it1 == (TVal2)*it2)? '=': 'X'; + op = 'M'; + } + if (lastOp != op) + { + if (lastOp == 'D' && numOps >= (unsigned)splicedGapThresh) + lastOp = 'N'; + if (numOps > 0) + appendValue(cigar, CigarElement<>(lastOp, numOps)); + numOps = 0; + lastOp = op; + } + ++numOps; + } + SEQAN_ASSERT_EQ(atEnd(it1), atEnd(it2)); + if (lastOp == 'D' && numOps >= (unsigned)splicedGapThresh) + lastOp = 'N'; + if (numOps > 0) + appendValue(cigar, CigarElement<>(op, numOps)); +} + +// ---------------------------------------------------------------------------- +// alignAndGetCigarString() +// ---------------------------------------------------------------------------- + +template < + typename TCigar, typename TMDString, typename TContig, typename TReadSeq, + typename TAlignedRead, typename TErrors > +inline void +alignAndGetCigarString( + TCigar &cigar, TMDString &md, TContig &, TReadSeq &, + TAlignedRead &, TErrors &, Nothing const &) +{ + cigar = "*"; + clear(md); +} + +struct BamAlignFunctorEditDistance +{ + typedef String > TGapAnchors; + + TGapAnchors contigAnchors, readAnchors; + + template + inline int + align(TGaps1 &gaps1, TGaps2 &gaps2, TErrors maxErrors) + { + return -globalAlignment( + gaps1, gaps2, + Score(), + -(int)maxErrors, (int)maxErrors + ); + } +}; + +struct BamAlignFunctorSemiGlobalGotoh +{ + typedef String > TGapAnchors; + + Score score; + TGapAnchors contigAnchors, readAnchors; + + BamAlignFunctorSemiGlobalGotoh(Score score_) : + score(score_) + {} + + template + inline int + align(TGaps1 &gaps1, TGaps2 &gaps2, TErrors maxErrors) + { + return globalAlignment( + gaps1, gaps2, score, + AlignConfig(), + -(int)maxErrors, (int)maxErrors, + Gotoh() + ) / scoreMismatch(score); + } +}; + +struct BamAlignFunctorDefault +{ +}; + +template < + typename TCigar, typename TMDString, typename TContigInfix, typename TReadSeq, + typename TAlignedRead, typename TErrors, typename TAlignFunctor> +inline void +_alignAndGetCigarString( + TCigar &cigar, TMDString &md, TContigInfix const &contigInfix, TReadSeq const &fwdReadSeq, + TAlignedRead &, TErrors &errors, TAlignFunctor &functor) +{ + typedef Gaps > TContigGaps; + typedef Gaps > TReadGaps; + + clear(functor.contigAnchors); + clear(functor.readAnchors); + + TContigGaps contigGaps(contigInfix, functor.contigAnchors); + TReadGaps readGaps(fwdReadSeq, functor.readAnchors); + + // if there is already an alignment between contigInfix and fwdReadSeq with 0 or 1 error then + // we don't to realign as it contains no gaps + if (!(errors == 0 || (errors == 1 && length(contigInfix) == length(fwdReadSeq)))) + errors = functor.align(contigGaps, readGaps, errors); + + getCigarString(cigar, contigGaps, readGaps); + TErrors mdErrors = getMDString(md, contigGaps, readGaps); + + ignoreUnusedVariableWarning(mdErrors); + SEQAN_ASSERT_EQ(errors, mdErrors); +} + +template < + typename TCigar, typename TMDString, typename TContig, typename TReadSeq, + typename TAlignedRead, typename TErrors, typename TAlignFunctor> +inline void +alignAndGetCigarString( + TCigar &cigar, TMDString &md, TContig const &contig, TReadSeq const &readSeq, + TAlignedRead &alignedRead, TErrors &errors, TAlignFunctor &functor) +{ + typedef typename TContig::TContigSeq TContigSeq; + typedef typename Infix::Type TContigInfix; + + TContigInfix contigInfix; + + if (alignedRead.beginPos <= alignedRead.endPos) + { + contigInfix = infix(contig.seq, alignedRead.beginPos, alignedRead.endPos); + _alignAndGetCigarString(cigar, md, contigInfix, readSeq, alignedRead, errors, functor); + } + else + { + contigInfix = infix(contig.seq, alignedRead.endPos, alignedRead.beginPos); + _alignAndGetCigarString(cigar, md, contigInfix, reverseComplementString(readSeq), alignedRead, errors, functor); + } +} + +template < + typename TCigar, typename TMDString, typename TContig, typename TReadSeq, + typename TAlignedRead, typename TErrors> +inline void +alignAndGetCigarString( + TCigar &cigar, TMDString &md, TContig const &contig, TReadSeq const &readSeq, + TAlignedRead &alignedRead, TErrors &errors, BamAlignFunctorDefault &) +{ + typedef typename TContig::TContigSeq TContigSeq; + typedef Gaps > TContigGaps; + typedef typename ReverseComplementString::Type TRefCompReadSeq; + typedef Gaps > TReadGaps; + typedef Gaps > TRCReadGaps; + + TContigGaps contigGaps(contig.seq, contig.gaps); + + if (alignedRead.beginPos <= alignedRead.endPos) + { + setClippedBeginPosition(contigGaps, alignedRead.beginPos); + setClippedEndPosition(contigGaps, alignedRead.endPos); + + TReadGaps readGaps(readSeq, alignedRead.gaps); + + getCigarString(cigar, contigGaps, readGaps); + errors = getMDString(md, contigGaps, readGaps); + } + else + { + setClippedBeginPosition(contigGaps, alignedRead.endPos); + setClippedEndPosition(contigGaps, alignedRead.beginPos); + + TRCReadGaps readGaps(reverseComplementString(readSeq), alignedRead.gaps); + + getCigarString(cigar, contigGaps, readGaps); + errors = getMDString(md, contigGaps, readGaps); + } +} + +// ---------------------------------------------------------------------------- +// _getClippedLength() +// ---------------------------------------------------------------------------- + +template +inline void _getClippedLength(TNum & sum, TCigarString const & cigar) +{ + typedef typename Iterator::Type TCigarIter; + + TCigarIter it = begin(cigar, Standard()); + TCigarIter itEnd = end(cigar, Standard()); + + sum = 0; + for (; it != itEnd; ++it) + if (getValue(it).operation != 'S' && getValue(it).operation != 'H') + sum += getValue(it).count; +} + +// ---------------------------------------------------------------------------- +// _getLengthInRef() +// ---------------------------------------------------------------------------- + +template +inline void _getLengthInRef(TNum & sum, TCigarString const & cigar) +{ + typedef typename Iterator::Type TCigarIter; + + TCigarIter it = begin(cigar, Standard()); + TCigarIter itEnd = end(cigar, Standard()); + + sum = 0; + for (; it != itEnd; ++it) + if (getValue(it).operation != 'S' && getValue(it).operation != 'H' && getValue(it).operation != 'I') + sum += getValue(it).count; +} + +// ---------------------------------------------------------------------------- +// _getQueryLength() +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type>::Type +_getQueryLength(TCigarString const & cigar) +{ + typedef typename Iterator::Type TCigarIter; + typedef typename Size::Type>::Type TSize; + TCigarIter it = begin(cigar, Standard()); + TCigarIter itEnd = end(cigar, Standard()); + + TSize len = 0; + for (; it != itEnd; ++it) + if (getValue(it).operation != 'D' && getValue(it).operation != 'H' && getValue(it).operation != 'N' && getValue(it).operation != 'P') + len += getValue(it).count; + return len; +} + +// ---------------------------------------------------------------------------- +// cigarToGapAnchorRead() +// ---------------------------------------------------------------------------- + +template +unsigned cigarToGapAnchorRead(TGaps & gaps, TCigarString const & cigar) +{ + typename Iterator::Type it = begin(gaps); + bool atBegin = true; + unsigned beginGaps = 0; + for (unsigned i = 0; i < length(cigar); ++i) + { + switch (cigar[i].operation) + { + case 'D': + case 'N': + case 'P': + if (atBegin) + beginGaps += cigar[i].count; + insertGaps(it, cigar[i].count); + SEQAN_FALLTHROUGH + case 'I': + case 'M': + case 'S': + it += cigar[i].count; + atBegin = false; + } + } + return beginGaps; +} + +// ---------------------------------------------------------------------------- +// cigarToGapAnchorContig() +// ---------------------------------------------------------------------------- + +template +unsigned cigarToGapAnchorContig(TGaps & gaps, TCigarString const & cigar) +{ + typename Iterator::Type it = begin(gaps); + bool atBegin = true; + unsigned beginGaps = 0; + for (unsigned i = 0; i < length(cigar); ++i) + { + switch (cigar[i].operation) + { + case 'I': + case 'P': + if (atBegin) + beginGaps += cigar[i].count; + insertGaps(it, cigar[i].count); + SEQAN_FALLTHROUGH + case 'D': + case 'M': + case 'N': + case 'S': + it += cigar[i].count; + atBegin = false; + } + } + return beginGaps; +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_CIGAR_H_ diff --git a/seqan/bam_io/read_bam.h b/seqan/bam_io/read_bam.h new file mode 100644 index 0000000..71059c8 --- /dev/null +++ b/seqan/bam_io/read_bam.h @@ -0,0 +1,279 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Code for reading Bam. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_READ_BAM_H_ +#define INCLUDE_SEQAN_BAM_IO_READ_BAM_H_ + +namespace seqan { + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @tag FileFormats#Bam + * @brief Identify the BAM format. + * + * @tag FileFormats#Sam + * @brief Identify the SAM format. + */ + +struct Bam_; +typedef Tag Bam; + + +template +struct FileExtensions +{ + static char const * VALUE[1]; // default is one extension +}; + +template +char const * FileExtensions::VALUE[1] = +{ + ".bam" // default output extension +}; + + +template +struct MagicHeader +{ + static unsigned char const VALUE[4]; +}; + +template +unsigned char const MagicHeader::VALUE[4] = { 'B', 'A', 'M', '\1' }; // BAM's magic header + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function readHeader() BamHeader +// ---------------------------------------------------------------------------- + +template +inline void +readHeader(BamHeader & header, + BamIOContext & context, + TForwardIter & iter, + Bam const & /*tag*/) +{ + clear(header); + // Read BAM magic string. + String > magic; + read(magic, iter, 4); + if (magic != "BAM\1") + SEQAN_THROW(ParseError("Not in BAM format.")); + + // Read header text, including null padding. + int32_t lText; + readRawPod(lText, iter); + + CharString samHeader; + write(samHeader, iter, lText); + + // Truncate to first position of '\0'. + cropAfterFirst(samHeader, EqualsChar<'\0'>()); + + // Parse out header records. + BamHeaderRecord headerRecord; + Iterator::Type it = begin(samHeader); + while (!atEnd(it)) + { + clear(headerRecord); + readRecord(headerRecord, context, it, Sam()); + appendValue(header, headerRecord); + } + + // Read # reference sequences. + int32_t nRef; + readRawPod(nRef, iter); + CharString name; + + clear(context.translateFile2GlobalRefId); + resize(context.translateFile2GlobalRefId, nRef, -1); + + for (int32_t i = 0; i < nRef; ++i) + { + // Read length of the reference name. + int32_t nName; + readRawPod(nName, iter); + clear(name); + write(name, iter, nName); + resize(name, nName - 1); + // Read length of the reference sequence. + int32_t lRef; + readRawPod(lRef, iter); + + // Add entry to name store and sequenceInfos if necessary. + // Compute translation from local ids (used in the BAM file) to corresponding ids in the name store + size_t globalRefId = nameToId(contigNamesCache(context), name); + context.translateFile2GlobalRefId[i] = globalRefId; + if (length(contigLengths(context)) <= globalRefId) + resize(contigLengths(context), globalRefId + 1, 0); + contigLengths(context)[globalRefId] = lRef; + } +} + +// ---------------------------------------------------------------------------- +// Function readRecord() BamAlignmentRecord +// ---------------------------------------------------------------------------- + +template +inline int32_t +_readBamRecordWithoutSize(TBuffer & rawRecord, TForwardIter & iter) +{ + int32_t recordLen = 0; + readRawPod(recordLen, iter); + + // fail, if we read "BAM\1" (did you miss to call readRecord(header, bamFile) first?) + if (recordLen == 0x014D4142) + SEQAN_THROW(ParseError("Unexpected BAM header encountered.")); + + clear(rawRecord); + write(rawRecord, iter, (size_t)recordLen); + return recordLen; +} + +template +inline void +_readBamRecord(TBuffer & rawRecord, TForwardIter & iter, Bam) +{ + int32_t recordLen = 0; + readRawPod(recordLen, iter); + + // fail, if we read "BAM\1" (did you miss to call readRecord(header, bamFile) first?) + if (recordLen == 0x014D4142) + SEQAN_THROW(ParseError("Unexpected BAM header encountered.")); + + clear(rawRecord); + appendRawPod(rawRecord, recordLen); + write(rawRecord, iter, (size_t)recordLen); +} + +template +inline void +readRecord(BamAlignmentRecord & record, + BamIOContext & context, + TForwardIter & iter, + Bam const & /* tag */) +{ + typedef typename Iterator::Type TCharIter; + typedef typename Iterator >, Standard>::Type SEQAN_RESTRICT TCigarIter; + typedef typename Iterator::Type SEQAN_RESTRICT TSeqIter; + typedef typename Iterator::Type SEQAN_RESTRICT TQualIter; + + // Read size and data of the remaining block in one chunk (fastest). + int32_t remainingBytes = _readBamRecordWithoutSize(context.buffer, iter); + TCharIter it = begin(context.buffer, Standard()); + + // BamAlignmentRecordCore. + arrayCopyForward(it, it + sizeof(BamAlignmentRecordCore), reinterpret_cast(&record)); + it += sizeof(BamAlignmentRecordCore); + + remainingBytes -= sizeof(BamAlignmentRecordCore) + record._l_qname + + record._n_cigar * 4 + (record._l_qseq + 1) / 2 + record._l_qseq; + SEQAN_ASSERT_GEQ(remainingBytes, 0); + + // Translate file local rID into a global rID that is compatible with the context contigNames. + if (record.rID >= 0 && !empty(context.translateFile2GlobalRefId)) + record.rID = context.translateFile2GlobalRefId[record.rID]; + if (record.rID >= 0) + SEQAN_ASSERT_LT(static_cast(record.rID), length(contigNames(context))); + + // ... the same for rNextId + if (record.rNextId >= 0 && !empty(context.translateFile2GlobalRefId)) + record.rNextId = context.translateFile2GlobalRefId[record.rNextId]; + if (record.rNextId >= 0) + SEQAN_ASSERT_LT(static_cast(record.rNextId), length(contigNames(context))); + + // query name. + resize(record.qName, record._l_qname - 1, Exact()); + arrayCopyForward(it, it + record._l_qname - 1, begin(record.qName, Standard())); + it += record._l_qname; + + // cigar string. + resize(record.cigar, record._n_cigar, Exact()); + static char const * CIGAR_MAPPING = "MIDNSHP=X*******"; + TCigarIter cigEnd = end(record.cigar, Standard()); + for (TCigarIter cig = begin(record.cigar, Standard()); cig != cigEnd; ++cig) + { + unsigned opAndCnt; + readRawPod(opAndCnt, it); + SEQAN_ASSERT_LEQ(opAndCnt & 15, 8u); + cig->operation = CIGAR_MAPPING[opAndCnt & 15]; + cig->count = opAndCnt >> 4; + } + + // query sequence. + resize(record.seq, record._l_qseq, Exact()); + TSeqIter sit = begin(record.seq, Standard()); + TSeqIter sitEnd = sit + (record._l_qseq & ~1); + while (sit != sitEnd) + { + unsigned char ui = getValue(it); + ++it; + assignValue(sit, Iupac(ui >> 4)); + ++sit; + assignValue(sit, Iupac(ui & 0x0f)); + ++sit; + } + if (record._l_qseq & 1) + *sit++ = Iupac((uint8_t)*it++ >> 4); + + // phred quality + resize(record.qual, record._l_qseq, Exact()); + // If qual is a sequence of 0xff (heuristic same as samtools: Only look at first byte) then we clear it, to get the + // representation of '*'; + TQualIter qitEnd = end(record.qual, Standard()); + for (TQualIter qit = begin(record.qual, Standard()); qit != qitEnd;) + *qit++ = '!' + *it++; + if (!empty(record.qual) && record.qual[0] == '\xff') + clear(record.qual); + + // tags + resize(record.tags, remainingBytes, Exact()); + arrayCopyForward(it, it + remainingBytes, begin(record.tags, Standard())); +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_READ_BAM_H_ diff --git a/seqan/bam_io/read_sam.h b/seqan/bam_io/read_sam.h new file mode 100644 index 0000000..ad30a46 --- /dev/null +++ b/seqan/bam_io/read_sam.h @@ -0,0 +1,399 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Code for reading SAM. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_READ_SAM_H_ +#define INCLUDE_SEQAN_BAM_IO_READ_SAM_H_ + +namespace seqan { + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +struct Sam_; +typedef Tag Sam; + + +template +struct FileExtensions +{ + static char const * VALUE[1]; // default is one extension +}; + +template +char const * FileExtensions::VALUE[1] = +{ + ".sam" // default output extension +}; + + +template +struct MagicHeader +{ + static unsigned char const * VALUE; +}; + +template +unsigned char const * MagicHeader::VALUE = NULL; // SAM has no magic header + + +enum SamTokenizeErrors_ +{ + SAM_INVALID_RECORD = 2048 +}; + +struct SamHeader_; +typedef Tag SamHeader; + +struct SamAlignment_; +typedef Tag SamAlignment; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function nextIs() SamHeader +// ---------------------------------------------------------------------------- + +template +inline bool nextIs(TForwardIter & iter, SamHeader const & /*tag*/) +{ + if (atEnd(iter)) + return false; + return value(iter) == '@'; +} + +//// ---------------------------------------------------------------------------- +//// Function skipRecord() SamHeader +//// ---------------------------------------------------------------------------- +// +//template +//inline void skipRecord(TForwardIter & iter, +// SamHeader const & /*tag*/) +//{ +// skipOne(iter, EqualsChar<'@'>()); +// skipLine(iter); +// return 0; +//} +// +//// ---------------------------------------------------------------------------- +//// Function skipRecord() SamAlignment +//// ---------------------------------------------------------------------------- +// +//template +//inline void skipRecord(TForwardIter & iter, +// SamAlignment const & /*tag*/) +//{ +// skipOne(iter, EqualsChar<'@'>()); +// skipLine(iter); +// return 0; +//} + +// ---------------------------------------------------------------------------- +// Function readRecord() BamHeaderRecord +// ---------------------------------------------------------------------------- + +template +inline void +readRecord(BamHeaderRecord & record, + BamIOContext & context, + TForwardIter & iter, + Sam const & /*tag*/) +{ + clear(record); + + // Make sure the first character is '@'. + skipOne(iter, EqualsChar<'@'>()); + + // Read the header tag. + char c1, c2; + readOne(c1, iter); + readOne(c2, iter); + + // Determine header type. + if (c1 == 'H' && c2 == 'D') + record.type = BAM_HEADER_FIRST; + else if (c1 == 'S' && c2 == 'Q') + record.type = BAM_HEADER_REFERENCE; + else if (c1 == 'R' && c2 == 'G') + record.type = BAM_HEADER_READ_GROUP; + else if (c1 == 'P' && c2 == 'G') + record.type = BAM_HEADER_PROGRAM; + else if (c1 == 'C' && c2 == 'O') + record.type = BAM_HEADER_COMMENT; + else + SEQAN_THROW(ParseError("Unknown SAM header type!")); + + CharString &buffer = context.buffer; + + if (record.type == BAM_HEADER_COMMENT) + { + skipOne(iter, IsTab()); + + appendValue(record.tags, Pair(), Exact()); + + clear(buffer); + readLine(buffer, iter); + assign(back(record.tags).i2, buffer, Exact()); + } + else + { + // Read the rest of the line into the tag field of record. + while (!atEnd(iter) && value(iter) == '\t') + { + skipOne(iter, IsTab()); + + appendValue(record.tags, Pair(), Exact()); + + clear(buffer); + readUntil(buffer, iter, EqualsChar<':'>()); + assign(back(record.tags).i1, buffer, Exact()); + + skipOne(iter, EqualsChar<':'>()); + + clear(buffer); + readUntil(buffer, iter, OrFunctor()); + assign(back(record.tags).i2, buffer, Exact()); + } + // Skip remaining line break + skipLine(iter); + } +} + +// ---------------------------------------------------------------------------- +// Function readRecord() BamHeader +// ---------------------------------------------------------------------------- + +template +inline void +readHeader(BamHeader & header, + BamIOContext & context, + TForwardIter & iter, + Sam const & tag) +{ + BamHeaderRecord record; + while (nextIs(iter, SamHeader())) + { + clear(record); + readRecord(record, context, iter, tag); + appendValue(header, record); + + // Get sequence information from @SQ header. + if (record.type == BAM_HEADER_REFERENCE) + { + CharString name; + unsigned lRef = 0; + for (unsigned i = 0; i < length(record.tags); ++i) + { + if (record.tags[i].i1 == "SN") + name = record.tags[i].i2; + else if (record.tags[i].i1 == "LN") + lexicalCast(lRef, record.tags[i].i2); + } + + // Add entry to name store and sequenceInfos if necessary. + size_t globalRefId = nameToId(contigNamesCache(context), name); + if (length(contigLengths(context)) <= globalRefId) + resize(contigLengths(context), globalRefId + 1, 0); + contigLengths(context)[globalRefId] = lRef; + } + } +} + +// ---------------------------------------------------------------------------- +// Function _readBamRecord() +// ---------------------------------------------------------------------------- + +template +inline void +_readBamRecord(TBuffer & rawRecord, TForwardIter & iter, Sam) +{ + clear(rawRecord); + readLine(rawRecord, iter); +} + +// ---------------------------------------------------------------------------- +// Function readRecord() BamAlignmentRecord +// ---------------------------------------------------------------------------- + +template +inline void +readRecord(BamAlignmentRecord & record, + BamIOContext & context, + TForwardIter & iter, + Sam const & /*tag*/) +{ + // fail, if we read "@" (did you miss to call readRecord(header, bamFile) first?) + if (nextIs(iter, SamHeader())) + SEQAN_THROW(ParseError("Unexpected SAM header encountered.")); + + OrFunctor, ParseError, Sam> > nextEntry; + + clear(record); + CharString &buffer = context.buffer; + + // QNAME + readUntil(record.qName, iter, nextEntry); + skipOne(iter, IsTab()); + + // FLAG + // TODO(holtgrew): Interpret hex and char as c-samtools -X does? + clear(buffer); + readUntil(buffer, iter, nextEntry); + record.flag = lexicalCast(buffer); + skipOne(iter, IsTab()); + + // RNAME + clear(buffer); + readUntil(buffer, iter, nextEntry); + if (buffer == "*") + record.rID = BamAlignmentRecord::INVALID_REFID; + else + record.rID = nameToId(contigNamesCache(context), buffer); + skipOne(iter, IsTab()); + + // POS + clear(buffer); + SEQAN_ASSERT_EQ((int32_t)0 - 1, (int32_t)BamAlignmentRecord::INVALID_POS); + readUntil(buffer, iter, nextEntry); + record.beginPos = (int32_t)lexicalCast(buffer) - 1; + skipOne(iter, IsTab()); + + // MAPQ + clear(buffer); + if (value(iter) == '*') + { + record.mapQ = 255; + skipOne(iter); + } + else + { + readUntil(buffer, iter, nextEntry); + record.mapQ = lexicalCast(buffer); + } + skipOne(iter, IsTab()); + + // CIGAR + CigarElement<> element; + if (value(iter) == '*') + skipOne(iter); + else + { + do + { + clear(buffer); + readUntil(buffer, iter, OrFunctor, AssertFunctor, ParseError, Sam> >()); + element.count = lexicalCast(buffer); + element.operation = value(iter); + skipOne(iter); + appendValue(record.cigar, element); + } while (value(iter) != '\t'); + } + skipOne(iter, IsTab()); + + // RNEXT + clear(buffer); + readUntil(buffer, iter, nextEntry); + if (buffer == "*") + record.rNextId = BamAlignmentRecord::INVALID_REFID; + else if (buffer == "=") + record.rNextId = record.rID; + else + record.rNextId = nameToId(contigNamesCache(context), buffer); + skipOne(iter, IsTab()); + + // PNEXT + if (value(iter) == '*') + { + record.pNext = BamAlignmentRecord::INVALID_POS; + skipOne(iter); + } + else + { + clear(buffer); + readUntil(buffer, iter, nextEntry); + record.pNext = (int32_t)lexicalCast(buffer) - 1; + } + skipOne(iter, IsTab()); + + // TLEN + if (value(iter) == '*') + { + record.tLen = MaxValue::VALUE; + skipOne(iter); + } + else + { + clear(buffer); + readUntil(buffer, iter, nextEntry); + record.tLen = lexicalCast(buffer); + } + skipOne(iter, IsTab()); + + // SEQ + readUntil(record.seq, iter, nextEntry); + // Handle case of missing sequence: Clear seq string as documented. + if (record.seq == "*") + clear(record.seq); + skipOne(iter, IsTab()); + + // QUAL + readUntil(record.qual, iter, OrFunctor()); + + // Handle case of missing quality: Clear qual string as documented. + if (record.qual == "*") + clear(record.qual); + + // The following list of tags is optional. A line break or EOF could also follow. + if (atEnd(iter)) + return; + if (value(iter) != '\t') + { + skipLine(iter); + return; + } + skipOne(iter, IsTab()); + + // TAGS + clear(buffer); + readLine(buffer, iter); + appendTagsSamToBam(record.tags, buffer); +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_READ_SAM_H_ diff --git a/seqan/bam_io/write_bam.h b/seqan/bam_io/write_bam.h new file mode 100644 index 0000000..6eb1e1c --- /dev/null +++ b/seqan/bam_io/write_bam.h @@ -0,0 +1,276 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// Author: David Weese +// ========================================================================== +// Code for writing BAM. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_WRITE_BAM_H_ +#define INCLUDE_SEQAN_BAM_IO_WRITE_BAM_H_ + +namespace seqan { + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function writeRecord() BamHeader +// ---------------------------------------------------------------------------- + +template +void write(TTarget & target, + BamHeader const & header, + BamIOContext & context, + Bam const & /*tag*/) +{ + write(target, "BAM\1"); + clear(context.buffer); + + // Create text of header. + for (unsigned i = 0; i < length(header); ++i) + write(context.buffer, header[i], context, Sam()); + + // Note that we do not write out a null-character to terminate the header. This would be valid by the SAM standard + // but the samtools do not expect this and write out the '\0' when converting from BAM to SAM. + // appendValue(context.buffer, '\0'); + + // Write text header. + appendRawPod(target, static_cast(length(context.buffer))); + write(target, context.buffer); + + // Write references. + if (!empty(context._contigNames)) + { + int32_t nRef = _max(length(contigNames(context)), length(contigLengths(context))); + appendRawPod(target, nRef); + + for (int32_t i = 0; i < nRef; ++i) + { + if (i < (int32_t)length(contigNames(context))) + { + appendRawPod(target, static_cast(length(contigNames(context)[i]) + 1)); + write(target, contigNames(context)[i]); + } + else + { + appendRawPod(target, static_cast(1)); + } + writeValue(target, '\0'); + int32_t lRef = 0; + if (i < (int32_t)length(contigLengths(context))) + lRef = contigLengths(context)[i]; + appendRawPod(target, lRef); + } + } +} + +// ---------------------------------------------------------------------------- +// Function writeRecord() BamAlignmentRecord +// ---------------------------------------------------------------------------- + +static inline int _reg2Bin(uint32_t beg, uint32_t end) +{ + --end; + if (beg >> 14 == end >> 14) + return 4681 + (beg >> 14); + + if (beg >> 17 == end >> 17) + return 585 + (beg >> 17); + + if (beg >> 20 == end >> 20) + return 73 + (beg >> 20); + + if (beg >> 23 == end >> 23) + return 9 + (beg >> 23); + + if (beg >> 26 == end >> 26) + return 1 + (beg >> 26); + + return 0; +} + +inline uint32_t +updateLengths(BamAlignmentRecord const & record) +{ + // update internal lengths. + record._l_qname = length(record.qName) + 1; + record._n_cigar = length(record.cigar); + record._l_qseq = length(record.seq); + + return sizeof(BamAlignmentRecordCore) + record._l_qname + + record._n_cigar * 4 + (record._l_qseq + 1) / 2 + record._l_qseq + + length(record.tags); +} + + +template +inline void +_writeBamRecord(TTarget & target, + BamAlignmentRecord const & record, + Bam const & /*tag*/) +{ + typedef typename Iterator > const, Standard>::Type SEQAN_RESTRICT TCigarIter; + typedef typename Iterator::Type SEQAN_RESTRICT TSeqIter; + typedef typename Iterator::Type SEQAN_RESTRICT TQualIter; + + // bin_mq_nl + unsigned l = 0; + _getLengthInRef(l, record.cigar); + record.bin =_reg2Bin(record.beginPos, record.beginPos + std::max(1u, l)); + + // Write fixed-size BamAlignmentRecordCore. + appendRawPod(target, (BamAlignmentRecordCore &)record); + + // read_name + write(target, record.qName); + writeValue(target, '\0'); + + // cigar + static unsigned char const MAP[256] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 2, 0, 0, 0, 5, 1, 0, 0, 0, 0, 3, 0, + 6, 0, 0, 4, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + TCigarIter citEnd = end(record.cigar, Standard()); + for (TCigarIter cit = begin(record.cigar, Standard()); cit != citEnd; ++cit) + appendRawPod(target, ((uint32_t)cit->count << 4) | MAP[(unsigned char)cit->operation]); + + // seq + TSeqIter sit = begin(record.seq, Standard()); + TSeqIter sitEnd = sit + (record._l_qseq & ~1); + while (sit != sitEnd) + { + unsigned char x = (ordValue(getValue(sit++)) << 4); + writeValue(target, x | ordValue(getValue(sit++))); + } + if (record._l_qseq & 1) + writeValue(target, ordValue(getValue(sit++)) << 4); + + // qual + SEQAN_ASSERT_LEQ(length(record.qual), length(record.seq)); + TQualIter qit = begin(record.qual, Standard()); + TQualIter qitEnd = end(record.qual, Standard()); + TQualIter qitVirtEnd = qit + record._l_qseq; + while (qit != qitEnd) + writeValue(target, *qit++ - '!'); + for (; qit != qitVirtEnd; ++qit) + writeValue(target, '\xff'); // fill with zero qualities + + // tags + write(target, record.tags); +} + +template +inline void +_writeBamRecordWrapper(TTarget & target, + BamAlignmentRecord const & record, + Nothing & /* range */, + uint32_t size, + Bam const & tag) +{ + appendRawPod(target, size); + _writeBamRecord(target, record, tag); +} + +template +inline void +_writeBamRecordWrapper(TTarget & target, + BamAlignmentRecord const & record, + Range & range, + uint32_t size, + Bam const & tag) +{ + if (SEQAN_LIKELY(size + 4 <= length(range))) + { + appendRawPod(range.begin, size); + _writeBamRecord(range.begin, record, tag); + advanceChunk(target, size + 4); + } + else + { + appendRawPod(target, size); + _writeBamRecord(target, record, tag); + } +} + +template +void write(TTarget & target, + BamAlignmentRecord const & record, + BamIOContext & context, + Bam const & tag) +{ +#ifdef SEQAN_DEBUG_OR_TEST_ + // Check for valid IO Context. + if (record.rID != BamAlignmentRecord::INVALID_REFID) + { + SEQAN_ASSERT_LT_MSG(record.rID, static_cast(length(contigNames(context))), + "BAM IO Assertion: Unknown REF ID!"); + } + if (record.rNextId != BamAlignmentRecord::INVALID_REFID) + { + SEQAN_ASSERT_LT_MSG(record.rNextId, static_cast(length(contigNames(context))), + "BAM IO Assertion: Unknown NEXT REF ID!"); + } +#endif + ignoreUnusedVariableWarning(context); + + // Update internal lengths + uint32_t size = updateLengths(record); + + // Reserve chunk memory + reserveChunk(target, 4 + size, Output()); + + // Write length and record + typename Chunk::Type ochunk; + getChunk(ochunk, target, Output()); + _writeBamRecordWrapper(target, record, ochunk, size, tag); +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_WRITE_BAM_H_ diff --git a/seqan/bam_io/write_sam.h b/seqan/bam_io/write_sam.h new file mode 100644 index 0000000..3191e9a --- /dev/null +++ b/seqan/bam_io/write_sam.h @@ -0,0 +1,221 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Code for writing SAM. +// ========================================================================== + +#ifndef INCLUDE_SEQAN_BAM_IO_WRITE_SAM_H_ +#define INCLUDE_SEQAN_BAM_IO_WRITE_SAM_H_ + +namespace seqan { + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function write() BamHeaderRecord +// ---------------------------------------------------------------------------- + +template +inline void write(TTarget & target, + BamHeaderRecord const & header, + BamIOContext const & /*context*/, + Sam const & /*tag*/) +{ + char const * headerTypes[] = {"@HD", "@SQ", "@RG", "@PG", "@CO"}; + write(target, headerTypes[header.type]); + + if (header.type == BAM_HEADER_COMMENT && !empty(header.tags)) + { + writeValue(target, '\t'); + write(target, header.tags[0].i2); + } + else + { + for (unsigned i = 0; i < length(header.tags); ++i) + { + writeValue(target, '\t'); + write(target, header.tags[i].i1); + writeValue(target, ':'); + write(target, header.tags[i].i2); + } + } + + writeValue(target, '\n'); +} + +// ---------------------------------------------------------------------------- +// Function write() BamHeader +// ---------------------------------------------------------------------------- + +template +inline void write(TTarget & target, + BamHeader const & header, + BamIOContext const & context, + Sam const & tag) +{ + String writtenSeqInfos; + resize(writtenSeqInfos, length(contigNames(context)), false); + + size_t globalRefId = 0; + for (unsigned i = 0; i < length(header); ++i) + { + BamHeaderRecord const & record = header[i]; + if (record.type == BAM_HEADER_REFERENCE) + for (unsigned j = 0; j < length(record.tags); ++j) + if (record.tags[j].i1 == "SN") + { + if (getIdByName(globalRefId, contigNamesCache(context), record.tags[j].i2)) + writtenSeqInfos[globalRefId] = true; + break; + } + + write(target, record, context, tag); + } + + // Write missing @SQ header records. + SEQAN_ASSERT_LEQ(length(contigLengths(context)), length(contigNames(context))); + for (unsigned i = 0; i < length(contigLengths(context)); ++i) + { + if (writtenSeqInfos[i]) + continue; + write(target, "@SQ\tSN:"); + write(target, contigNames(context)[i]); + write(target, "\tLN:"); + appendNumber(target, contigLengths(context)[i]); + writeValue(target, '\n'); + } +} + +// ---------------------------------------------------------------------------- +// Function write() BamAlignmentRecord +// ---------------------------------------------------------------------------- + +template +inline void write(TTarget & target, + BamAlignmentRecord const & record, + BamIOContext const & context, + Sam const & /*tag*/) +{ +#ifdef SEQAN_DEBUG_OR_TEST_ + // Check for valid IO Context. + if (record.rID != BamAlignmentRecord::INVALID_REFID) + { + SEQAN_ASSERT_LT_MSG(record.rID, static_cast(length(contigNames(context))), + "SAM IO Assertion: Unknown REF ID!"); + } + if (record.rNextId != BamAlignmentRecord::INVALID_REFID) + { + SEQAN_ASSERT_LT_MSG(record.rNextId, static_cast(length(contigNames(context))), + "SAM IO Assertion: Unknown NEXT REF ID!"); + } +#endif + + write(target, record.qName); + writeValue(target, '\t'); + + appendNumber(target, record.flag); + writeValue(target, '\t'); + + if (record.rID == BamAlignmentRecord::INVALID_REFID) + writeValue(target, '*'); + else + write(target, contigNames(context)[record.rID]); + + writeValue(target, '\t'); + + SEQAN_ASSERT_EQ((int32_t)BamAlignmentRecord::INVALID_POS + 1, (int32_t)0); + appendNumber(target, record.beginPos + 1); + + writeValue(target, '\t'); + + appendNumber(target, static_cast(record.mapQ)); + writeValue(target, '\t'); + + if (empty(record.cigar)) + writeValue(target, '*'); + else + for (unsigned i = 0; i < length(record.cigar); ++i) + { + appendNumber(target, record.cigar[i].count); + writeValue(target, record.cigar[i].operation); + } + + writeValue(target, '\t'); + + if (record.rNextId == BamAlignmentRecord::INVALID_REFID) + writeValue(target, '*'); + else if (record.rID == record.rNextId) + writeValue(target, '='); + else + write(target, contigNames(context)[record.rNextId]); + + writeValue(target, '\t'); + + appendNumber(target, record.pNext + 1); + + writeValue(target, '\t'); + + if (record.tLen == BamAlignmentRecord::INVALID_LEN) + writeValue(target, '0'); + else + appendNumber(target, record.tLen); + + writeValue(target, '\t'); + + if (empty(record.seq)) + writeValue(target, '*'); // Case of empty seq string / "*". + else + write(target, record.seq); + + writeValue(target, '\t'); + + + if (empty(record.qual)) // Case of empty quality string / "*". + writeValue(target, '*'); + else + write(target, record.qual); + + if (!empty(record.tags)) + { + writeValue(target, '\t'); + appendTagsBamToSam(target, record.tags); + } + + writeValue(target, '\n'); +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BAM_IO_WRITE_SAM_H_ diff --git a/seqan/basic.h b/seqan/basic.h new file mode 100644 index 0000000..0cf12db --- /dev/null +++ b/seqan/basic.h @@ -0,0 +1,112 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Umbrella header for the basic module. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_H_ + +// -------------------------------------------------------------------------- +// Prerequisites +// -------------------------------------------------------------------------- + +#include + +// -------------------------------------------------------------------------- +// Include Sub Modules +// -------------------------------------------------------------------------- + +// Code for debugging and testing (assertions, test system) and profiling. +#include + +// C++ Metaprogramming Support Code, generally independent of SeqAn. +#include + +// Basic functors. +#include + +// Fundamental meta and global functions. This is what makes SeqAn SeqAn. +#include + +// Basic exceptions. +#include + +// More advanced debug system constructs. +// TODO(holtgrew): Move into basic_debug subsystem, some stuff from metaprogramming and fundamental required, those should not depend on debug system. +#include + +// SeqAn Concept Checking Library (ported from Boost). +#include + +// Container concept and supporting code. +#include + +// Memory allocation code. +#include + +// High level parallelism support. +#include + +// Mathematical functions and utilities. +#include + +// Smart pointers, including Holder<> class hierarchy. +#include + +// Iterator concept and implementation. +#include + +// Functions to efficiently move data between containers/iterators/streams +#include + +// Alphabet concept and biological implementations. +#include + +// Proxy class and supporting code. +#include + +// Aggregate data types (pairs, triples, tuples). +#include + +// Remaining code with cyclic dependencies. +#include + +// Basic views functions and metafunctions. +#include + +// Basic device metafunctions. +#include + +// Basic SIMD vector implementation using intrinsics. +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_H_ diff --git a/seqan/basic/aggregate_concept.h b/seqan/basic/aggregate_concept.h new file mode 100644 index 0000000..f79a7d1 --- /dev/null +++ b/seqan/basic/aggregate_concept.h @@ -0,0 +1,132 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_AGGREGATE_CONCEPT_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_AGGREGATE_CONCEPT_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @concept AggregateConcept + * + * @brief Aggregate types contain a fixed number of fixed-size values (pairs, triples, tuples). + * + * Stream output operators are not shown in the function list below, but required. + * + * Comparison operators are not shown in the function list below, but required. + */ + +/*! + * @fn AggregateConcept#operator<< + * @brief Stream output operator. + * + * @signature TStream AggregateConcept::operator<<(stream, aggregate); + * + * @param[in,out] stream The std::ostream to write to. + * @param[in] aggregate The aggregate type to write to the stream. + * + * @return TStream Reference to stream after writing aggregate to it. + */ + +/*! + * @defgroup AggregateTags Aggregate Tags + * @brief Tags to use in aggregate (e.g. Pair, Triple, and Tuple) types. + */ + +/*! + * @tag AggregateTags#Pack + * @headerfile + * @brief Tag to mark a packed specialization that disables address alignment for members. + * + * @signature typedef Tag Pack; + */ + +struct Pack_; +typedef Tag Pack; + +// TODO(holtgrew): We need @tparam for tag in the Dox system. + +/*! + * @tag AggregateTags#BitPacked + * @headerfile + * @brief Tag to mark a bit-packed specialization that avoids to waste bits. + * + * @signature template <[unsinged BITSIZE1[, unsigned BITSIZE2]]> + * struct BitPacked; + * + * BITSIZE1 The number of bits for the first entry. + * + * BITSIZE2 The number of bits for the second entry. + */ + +template +struct BitPacked; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +/*! + * @mfn MakePacked + * @headerfile + * @brief Return the corresponding packed type for a type. + * + * @signature MakePacked::Type; + * + * @tparam TAggregate The aggregate type to transform. + * + * @return Type The resulting packed type. + */ + +template +struct MakePacked +{ + typedef T Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_AGGREGATE_CONCEPT_H_ diff --git a/seqan/basic/allocator_chunkpool.h b/seqan/basic/allocator_chunkpool.h new file mode 100644 index 0000000..d41f433 --- /dev/null +++ b/seqan/basic/allocator_chunkpool.h @@ -0,0 +1,245 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// Allocator that pools one or more consecutive memory blocks of a specific +// size. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_CHUNKPOOL_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_CHUNKPOOL_H_ + +#include + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +template < + size_t SIZE, + size_t MAX_COUNT = 26, + typename TParentAllocator = Allocator > > +struct ChunkPool; + +template +struct Allocator > +{ + enum + { + STORAGE_SIZE_1 = 0x1000UL, + STORAGE_SIZE_2 = SIZE * MAX_COUNT * 8, + STORAGE_SIZE_UPPER = (STORAGE_SIZE_1 > STORAGE_SIZE_2) ? STORAGE_SIZE_1 : STORAGE_SIZE_2, + ITEMS_PER_STORAGE = STORAGE_SIZE_UPPER / SIZE, + STORAGE_SIZE = ITEMS_PER_STORAGE * SIZE, + + STORAGE_SIZE_MIN = SIZE * MAX_COUNT //minimal storage size + }; + + char * data_recycled_blocks [MAX_COUNT]; + char * data_current_begin; + char * data_current_end; + char * data_current_free; + Holder data_parent_allocator; + + Allocator() + { + std::memset(data_recycled_blocks, 0, sizeof(data_recycled_blocks)); + data_current_end = data_current_free = 0; + //dont need to initialize data_current_begin + } + + Allocator(size_t reserve_item_count) + { + std::memset(data_recycled_blocks, 0, sizeof(data_recycled_blocks)); + + size_t storage_size = (reserve_item_count * SIZE > STORAGE_SIZE_MIN) ? reserve_item_count * SIZE : STORAGE_SIZE_MIN; + allocate( parentAllocator( *this ), data_current_begin, storage_size ); + data_current_end = data_current_begin + storage_size; + data_current_free = data_current_begin; + } + + Allocator(TParentAllocator & parent_alloc) + { + std::memset(data_recycled_blocks, 0, sizeof(data_recycled_blocks)); + data_current_end = data_current_free = 0; + //dont need to initialize data_current_begin + + setValue(data_parent_allocator, parent_alloc); + } + + Allocator(size_t reserve_item_count, TParentAllocator & parent_alloc) + { + std::memset(data_recycled_blocks, 0, sizeof(data_recycled_blocks)); + + setValue(data_parent_allocator, parent_alloc); + + size_t storage_size = (reserve_item_count * SIZE > STORAGE_SIZE_MIN) ? reserve_item_count * SIZE : STORAGE_SIZE_MIN; + allocate( parentAllocator( *this ), data_current_begin, storage_size ); + data_current_end = data_current_begin + storage_size; + data_current_free = data_current_begin; + } + + //Dummy copy + Allocator(Allocator const &) + { + std::memset(data_recycled_blocks, 0, sizeof(data_recycled_blocks)); + data_current_end = data_current_free = 0; + //dont need to initialize data_current_begin + } + inline Allocator & + operator=(Allocator const &) + { + clear(*this); + return *this; + } + + ~Allocator() + { + clear(*this); + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function parentAllocator() +// ---------------------------------------------------------------------------- + +template +inline TParentAllocator & +parentAllocator(Allocator > & me) +{ + return value(me.data_parent_allocator); +} + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +template +void +clear(Allocator > & me) +{ + std::memset(me.data_recycled_blocks, 0, sizeof(me.data_recycled_blocks)); + me.data_current_end = me.data_current_free = 0; + + clear(parentAllocator(me)); +} + +// ---------------------------------------------------------------------------- +// Function allocate() +// ---------------------------------------------------------------------------- + +template +inline void +allocate(Allocator > & me, + TValue * & data, + TSize count, + Tag const tag_) +{ + SEQAN_ASSERT_GT(count, static_cast(0)); + + typedef Allocator > TAllocator; + + char * ptr; + + if ((sizeof(TValue) != SIZE) || ((size_t) count > MAX_COUNT)) + {//no blocking + return allocate(parentAllocator(me), data, count, tag_); + } + + size_t bytes_needed = count * SIZE; + if (me.data_recycled_blocks[count - 1]) + {//use recycled + ptr = me.data_recycled_blocks[count - 1]; + me.data_recycled_blocks[count - 1] = * reinterpret_cast(ptr); + } + else + {//use new + ptr = me.data_current_free; + if (ptr + bytes_needed > me.data_current_end) + {//not enough free space in current storage: allocate new + size_t rest_block_number = (me.data_current_end - me.data_current_free) / SIZE; + if (ptr && rest_block_number) + {//link rest to recycle list + *reinterpret_cast(ptr) = me.data_recycled_blocks[rest_block_number - 1]; + me.data_recycled_blocks[rest_block_number - 1] = reinterpret_cast(ptr); + } + + allocate(parentAllocator(me), ptr, (size_t) TAllocator::STORAGE_SIZE, tag_); + me.data_current_begin = ptr; + me.data_current_end = ptr + TAllocator::STORAGE_SIZE; + } + me.data_current_free = ptr + bytes_needed; + } + + data = reinterpret_cast(ptr); +} + +// ---------------------------------------------------------------------------- +// Function deallocate() +// ---------------------------------------------------------------------------- + +template +inline void +deallocate(Allocator > & me, + TValue * data, + TSize count, + Tag const tag_) +{ + SEQAN_ASSERT_GT(count, 0); + + if ((sizeof(TValue) != SIZE) || (static_cast(count) > MAX_COUNT)) + {//no blocking + return deallocate(parentAllocator(me), data, count, tag_); + } + + //link in recycling list + *reinterpret_cast(data) = me.data_recycled_blocks[count - 1]; + me.data_recycled_blocks[count - 1] = reinterpret_cast(data); +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_CHUNKPOOL_H_ diff --git a/seqan/basic/allocator_interface.h b/seqan/basic/allocator_interface.h new file mode 100644 index 0000000..41d7169 --- /dev/null +++ b/seqan/basic/allocator_interface.h @@ -0,0 +1,432 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// Allocator class definition and generic interface. +// ========================================================================== + +// TODO(holtgrew): Perform some benchmarks and use a better malloc, e.g. tcmalloc and see whether our allocator infrastructure is worth keeping around. +// TODO(holtgrew): Rename to allocator_base.h? + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_INTERFACE_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_INTERFACE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +struct Tristate_; +typedef Tag Tristate; +template struct Holder; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @defgroup AllocatorUsageTags Allocator Usage Tags + * @brief The purpose of an allocated memory block. + * + * @tag AllocatorUsageTags#TagAllocateUnspecified + * @headerfile + * @brief Not specified. + * + * @tag AllocatorUsageTags#TagAllocateTemp + * @headerfile + * @brief Temporary memory. + * + * @tag AllocatorUsageTags#TagAllocateStorage + * @headerfile + * @brief Memory for storing container content. + */ + +// TODO(holtgrew): ANY use/difference? + +struct AllocateUnspecified_; +typedef Tag TagAllocateUnspecified; + +struct AllocateTemp_; +typedef Tag TagAllocateTemp; + +struct AllocateStorage_; +typedef Tag TagAllocateStorage; + +struct AllocateAlignedMalloc_; +typedef Tag TagAllocateAlignedMalloc; + +/*! + * @class Allocator + * @headerfile + * @brief Manager for allocated memory. + * + * @signature template + * class Allocator; + * + * @tparam TSpec The specializing type. + * + * @section Remarks + * + * There are two reasons for using non-trivial allocators: + * + *
    + *
  1. Allocators support the function @link Allocator#clear @endlink for a fast deallocation of all allocated + * memory blocks.
  2. + *
  3. Some allocators are faster in allocating an deallocating memory. Pool allocators like e.g. + * @link SinglePoolAllocator @endlink or @link MultiPoolAllocator @endlink speed up + * @link Allocator#allocate @endlink, @link Allocator#deallocate * @endlink, and + * @link Allocator#clear @endlink for pooled memory blocks.
  4. + *
+ */ + +template +struct Allocator; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +//.Metafunction.Spec.param.T.type:Class.Allocator + +template +struct Spec > +{ + typedef TSpec Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function allocate() +// ---------------------------------------------------------------------------- + +/*! + * @fn Allocator#allocate + * @headerfile + * @brief Allocates memory from heap. + * + * @signature void allocate(allocator, data, count[, usageTag]); + * + * @param[in] count Number of items that could be stored in the allocated memory. The type of the allocated + * items is given by the type of data. + * @param[in] usageTag A tag the specifies the purpose for the allocated memory. Values: + * @link AllocatorUsageTags @endlink. + * @param[in,out] allocator Allocator object. allocator is conceptually the "owner" of the allocated + * memory. Objects of all types can be used as allocators. If no special behavior is + * implemented, default functions allocation/deallocation are applied that uses standard + * new and delete operators. Types: Allocator + * + * @section Remarks + * + * The function allocates at least count*sizeof(data) bytes. The allocated memory is large enough to hold + * count objects of type T, where T * is type of data. + * + * These objects are not constructed by allocate. + * + * Use e.g. one of the functions @link valueConstruct @endlink, @link arrayConstruct @endlink, @link arrayConstructCopy + * @endlink or @link arrayFill @endlink to construct the objects. A new operator which is part of the C++ + * standard (defined in <new>) can also be used to construct objects at a given memory address. + * + * @section Remarks + * + * All allocated memory blocks should be deallocated by the corresponding function @link Allocator#deallocate @endlink. + */ + +template +inline void +allocate(T const & me, + TValue * & data, + TSize count) +{ + allocate(me, data, count, TagAllocateUnspecified()); +} + +template +inline void +allocate(T & me, + TValue * & data, + TSize count) +{ + allocate(me, data, count, TagAllocateUnspecified()); +} + +template +inline void +allocate(T const &, + TValue * & data, + TSize count, + Tag const &) +{ +// data = (TValue *) operator new(count * sizeof(TValue)); +#ifdef STDLIB_VS + data = (TValue *) _aligned_malloc(count * sizeof(TValue), __alignof(TValue)); +#else +/*#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 + const size_t align = (__alignof__(TValue) < sizeof(void*)) ? sizeof(void*): __alignof__(TValue); + if (posix_memalign(&(void* &)data, align, count * sizeof(TValue))) + data = NULL; +#else + data = (TValue *) malloc(count * sizeof(TValue)); +#endif*/ + data = (TValue *) operator new(count * sizeof(TValue)); +#endif + +#ifdef SEQAN_PROFILE + if (data) + SEQAN_PROADD(SEQAN_PROMEMORY, count * sizeof(TValue)); +#endif +} + +template +inline void +allocate(T &, + TValue * & data, + TSize count, + Tag const &) +{ +// data = (TValue *) operator new(count * sizeof(TValue)); +#ifdef STDLIB_VS + data = (TValue *) _aligned_malloc(count * sizeof(TValue), __alignof(TValue)); +#else +/*#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 + const size_t align = (__alignof__(TValue) < sizeof(void*)) ? sizeof(void*) : __alignof__(TValue); + if (posix_memalign(&(void* &)data, align, count * sizeof(TValue))) + data = NULL; +#else + data = (TValue *) malloc(count * sizeof(TValue)); +#endif*/ + data = (TValue *) operator new(count * sizeof(TValue)); +#endif + +#ifdef SEQAN_PROFILE + if (data) + SEQAN_PROADD(SEQAN_PROMEMORY, count * sizeof(TValue)); +#endif +} + +// NOTE(rrahn): Currently *new* does not support aligned memory, but we need it for dynamically +// allocated SimdVector class, so we overload the allocation to use mem_alloc for simd vector types. +// See following discussion: http://stackoverflow.com/questions/6973995/dynamic-aligned-memory-allocation-in-c11 +template +inline void +allocate(T const &, + TValue * & data, + TSize count, + TagAllocateAlignedMalloc const &) +{ +#ifdef PLATFORM_WINDOWS_VS + data = (TValue *) _aligned_malloc(count * sizeof(TValue), __alignof(TValue)); +#else + #if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 + const size_t align = (__alignof__(TValue) < sizeof(void*)) ? sizeof(void*): __alignof__(TValue); + if (posix_memalign(&(void* &)data, align, count * sizeof(TValue))) + data = NULL; + #else + data = (TValue *) malloc(count * sizeof(TValue)); + #endif +#endif +} + +template +inline void +allocate(T &, + TValue * & data, + TSize count, + TagAllocateAlignedMalloc const &) +{ +#ifdef PLATFORM_WINDOWS_VS + data = (TValue *) _aligned_malloc(count * sizeof(TValue), __alignof(TValue)); +#else + #if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 + const size_t align = (__alignof__(TValue) < sizeof(void*)) ? sizeof(void*) : __alignof__(TValue); + if (posix_memalign(&(void* &)data, align, count * sizeof(TValue))) + data = NULL; + #else + data = (TValue *) malloc(count * sizeof(TValue)); + #endif +#endif +} + +// ---------------------------------------------------------------------------- +// Function deallocate() +// ---------------------------------------------------------------------------- + +/*! + * @fn Allocator#deallocate + * @headerfile + * @brief Deallocates memory. + * + * @signature void deallocate(object, data, count[, usageTag]) + * + * @param[in,out] object Allocator object.object is conceptually the "owner" of the allocated memory. + * Objects of all types can be used as allocators. If no special behavior is implemented, + * default functions allocation/deallocation are applied that uses standard new + * and delete operators. Types: Allocator + * @param[out] data Pointer to allocated memory that was allocated by allocate. + * @param[in] count Number of items that could be stored in the allocated memory. + * @param[in] usageTag A tag the specifies the purpose for the allocated memory. + * Values: @link AllocatorUsageTags @endlink. + * + * The values for object, count and usageTag should be the same that was used when + * allocate was called. The value of data should be the same that was returned by allocate. + * + * deallocate does not destruct objects. + * + * Use e.g. one of the functions @link valueDestruct @endlink or @link arrayDestruct @endlink to destruct the objects. + * delete and delete [] operators which are part of the C++ standard (defined in <new>) + * can also be used to destruct objects at a given memory address. + */ + +template +inline void +deallocate(T const & me, + TValue * data, + TSize const count) +{ + deallocate(me, data, count, TagAllocateUnspecified()); +} + +template +inline void +deallocate(T & me, + TValue * data, + TSize const count) +{ + deallocate(me, data, count, TagAllocateUnspecified()); +} + +template +inline void +deallocate( + T const & /*me*/, + TValue * data, +#ifdef SEQAN_PROFILE + TSize count, +#else + TSize, +#endif + Tag const) +{ +#ifdef SEQAN_PROFILE + if (data && count) // .. to use count if SEQAN_PROFILE is not defined + SEQAN_PROSUB(SEQAN_PROMEMORY, count * sizeof(TValue)); +#endif +// operator delete ((void *) data); +#ifdef STDLIB_VS + _aligned_free((void *) data); +#else +// free((void *) data); + operator delete ((void *) data); +#endif +} + +template +inline void +deallocate( + T & /*me*/, + TValue * data, +#ifdef SEQAN_PROFILE + TSize count, +#else + TSize, +#endif + Tag const) +{ +#ifdef SEQAN_PROFILE + if (data && count) // .. to use count if SEQAN_PROFILE is not defined + SEQAN_PROSUB(SEQAN_PROMEMORY, count * sizeof(TValue)); +#endif +// operator delete ((void *) data); +#ifdef STDLIB_VS + _aligned_free((void *) data); +#else +// free((void *) data); + operator delete ((void *) data); +#endif +} + +// NOTE(rrahn): Currently *new* does not support aligned memory, but we need it for dynamically +// allocated SimdVector class, so we overload the allocation to use mem_alloc for simd vector types. +// See following discussion: http://stackoverflow.com/questions/6973995/dynamic-aligned-memory-allocation-in-c11 +template +inline void +deallocate( + T const & /*me*/, + TValue * data, +#ifdef SEQAN_PROFILE + TSize count, +#else + TSize, +#endif + TagAllocateAlignedMalloc const) +{ +#ifdef SEQAN_PROFILE + if (data && count) // .. to use count if SEQAN_PROFILE is not defined + SEQAN_PROSUB(SEQAN_PROMEMORY, count * sizeof(TValue)); +#endif +#ifdef PLATFORM_WINDOWS_VS + _aligned_free((void *) data); +#else + free((void *) data); +#endif +} + +template +inline void +deallocate( + T & /*me*/, + TValue * data, +#ifdef SEQAN_PROFILE + TSize count, +#else + TSize, +#endif + TagAllocateAlignedMalloc const) +{ +#ifdef SEQAN_PROFILE + if (data && count) // .. to use count if SEQAN_PROFILE is not defined + SEQAN_PROSUB(SEQAN_PROMEMORY, count * sizeof(TValue)); +#endif + // operator delete ((void *) data); +#ifdef PLATFORM_WINDOWS_VS + _aligned_free((void *) data); +#else + free((void *) data); +#endif +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_INTERFACE_H_ diff --git a/seqan/basic/allocator_multipool.h b/seqan/basic/allocator_multipool.h new file mode 100644 index 0000000..a93cbd1 --- /dev/null +++ b/seqan/basic/allocator_multipool.h @@ -0,0 +1,262 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// Allocator that pools blocks up to a given size. +// ========================================================================== + +#ifndef SEQAN_BASIC_BASIC_ALLOCATOR_MULTIPOOL_H_ +#define SEQAN_BASIC_BASIC_ALLOCATOR_MULTIPOOL_H_ + +#include + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @class MultiPoolAllocator + * @extends Allocator + * @headerfile + * @brief Allocator that pools memory blocks. + * + * @signature template + * class Allocator >; + * + * @tparam TParentAllocator The parent allocator. + * @tparam BLOCKING_LIMIT The maximum size for memory blocks to be pooled (default is 256). + * + * Freed blocks are not immediately deallocated but recycled in subsequential allocations. This way, the number of + * calls to the heap manager is reduced and that might speed up memory management. + * + * Note that memory block larger than BLOCKING_LIMIT are not pooled but immediately allocated and deallocated + * using ParentAllocator. + */ + +template >, unsigned int BLOCKING_LIMIT = 0x100> +struct MultiPool; + +typedef Allocator >, 0x100> > PoolAllocator; + +template +struct Allocator > +{ + enum + { + BLOCKING_LIMIT = BLOCKING_LIMIT_, + GRANULARITY_BITS = 2, + BLOCKING_COUNT = BLOCKING_LIMIT >> GRANULARITY_BITS, + STORAGE_SIZE = 0xf80 + }; + + char * data_recycled_blocks [BLOCKING_COUNT]; + char * data_current_begin [BLOCKING_COUNT]; + char * data_current_free [BLOCKING_COUNT]; + Holder data_parent_allocator; + + Allocator() + { + // TODO(holtrew): Why not SeqAn's memset? or use using? + std::memset(data_recycled_blocks, 0, sizeof(data_recycled_blocks)); + std::memset(data_current_begin, 0, sizeof(data_current_begin)); + std::memset(data_current_free, 0, sizeof(data_current_free)); + } + + Allocator(TParentAllocator & parent_alloc) + { + // TODO(holtrew): Why not SeqAn's memset? or use using? + std::memset(data_recycled_blocks, 0, sizeof(data_recycled_blocks)); + std::memset(data_current_begin, 0, sizeof(data_current_begin)); + std::memset(data_current_free, 0, sizeof(data_current_free)); + + setValue(data_parent_allocator, parent_alloc); + } + + //Dummy copy + Allocator(Allocator const &) + { + // TODO(holtrew): Why not SeqAn's memset? or use using? + std::memset(data_recycled_blocks, 0, sizeof(data_recycled_blocks)); + std::memset(data_current_begin, 0, sizeof(data_current_begin)); + std::memset(data_current_free, 0, sizeof(data_current_free)); + } + + inline Allocator & + operator=(Allocator const &) + { + clear(*this); + return *this; + } + + ~Allocator() + { + clear(*this); + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function parentAllocator() +// ---------------------------------------------------------------------------- + +template +inline TParentAllocator & +parentAllocator(Allocator > & me) +{ + return value(me.data_parent_allocator); +} + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +template +void +clear(Allocator > & me) +{ + std::memset(me.data_recycled_blocks, 0, sizeof(me.data_recycled_blocks)); + std::memset(me.data_current_begin, 0, sizeof(me.data_current_begin)); + std::memset(me.data_current_free, 0, sizeof(me.data_current_free)); + + clear(parentAllocator(me)); +} + +// ---------------------------------------------------------------------------- +// Helper function _allocatorBlockNumber() +// ---------------------------------------------------------------------------- + +template +inline unsigned int +_allocatorBlockNumber(Allocator > &, + size_t size_) +{ + typedef Allocator > TAllocator; + + SEQAN_ASSERT_GT(size_, 0u); + + if (size_ < BLOCKING_LIMIT) + {//blocks + return size_ >> TAllocator::GRANULARITY_BITS; + } + else + {//no blocking + return TAllocator::BLOCKING_COUNT; + } +} + +// ---------------------------------------------------------------------------- +// Function allocate() +// ---------------------------------------------------------------------------- + +template +inline void +allocate(Allocator > & me, + TValue * & data, + TSize count, + Tag const & tag_) +{ + typedef Allocator > TAllocator; + + size_t bytes_needed = count * sizeof(TValue); + char * ptr; + + unsigned int block_number = _allocatorBlockNumber(me, bytes_needed); + if (block_number == TAllocator::BLOCKING_COUNT) + {//no blocking + return allocate(parentAllocator(me), data, count, tag_); + } + + bytes_needed = (block_number + 1) << TAllocator::GRANULARITY_BITS; + + if (me.data_recycled_blocks[block_number]) + {//use recycled + ptr = me.data_recycled_blocks[block_number]; + me.data_recycled_blocks[block_number] = * reinterpret_cast(ptr); + } + else + {//use new + ptr = me.data_current_free[block_number]; + if (!ptr || (ptr + bytes_needed > me.data_current_begin[block_number] + TAllocator::STORAGE_SIZE)) + {//not enough free space in current storage: allocate new + allocate(parentAllocator(me), ptr, (size_t) TAllocator::STORAGE_SIZE, tag_); + me.data_current_begin[block_number] = ptr; + } + me.data_current_free[block_number] = ptr + bytes_needed; + } + + data = reinterpret_cast(ptr); +} + +// ---------------------------------------------------------------------------- +// Function deallocate() +// ---------------------------------------------------------------------------- + +template +inline void +deallocate(Allocator > & me, + TValue * data, + TSize count, + Tag const tag_) +{ + typedef Allocator > TAllocator; + + size_t bytes_needed = count * sizeof(TValue); + + unsigned int block_number = _allocatorBlockNumber(me, bytes_needed); + if (block_number == TAllocator::BLOCKING_COUNT) + {//no blocking + return deallocate(parentAllocator(me), data, count, tag_); + } + + bytes_needed = (block_number + 1) << TAllocator::GRANULARITY_BITS; + + //link in recycling list + *reinterpret_cast(data) = me.data_recycled_blocks[block_number]; + me.data_recycled_blocks[block_number] = reinterpret_cast(data); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_BASIC_BASIC_ALLOCATOR_MULTIPOOL_H_ diff --git a/seqan/basic/allocator_simple.h b/seqan/basic/allocator_simple.h new file mode 100644 index 0000000..37d45ce --- /dev/null +++ b/seqan/basic/allocator_simple.h @@ -0,0 +1,239 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// General purpose allocator. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_SIMPLE_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_SIMPLE_H_ + +#include + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @class SimpleAllocator + * @extends Allocator + * @headerfile + * @brief General purpose allocator. + * + * @signature template + * class Allocator >; + * + * @tparam TParentAllocator An allocator that is used by the simple allocator to allocate memory. + * + * The tag Default used as TparentAllocator means that the default implementations of allocate and + * deallocate are used. + */ + +template +struct SimpleAlloc; + +typedef Allocator > SimpleAllocator; + +template +struct Allocator > +{ + struct Header + { + Header * left; + Header * right; + size_t size; + }; + + Header * data_storages; + Holder data_parent_allocator; + + Allocator() + : data_storages(0) + { + } + + Allocator(TParentAllocator & parent_alloc) + : data_storages(0) + { + setValue(data_parent_allocator, parent_alloc); + } + + //Dummy copy + Allocator(Allocator const &) + : data_storages(0) + { + } + + inline Allocator & + operator = (Allocator const &) + { + clear(*this); + return *this; + } + + ~Allocator() + { + clear(*this); + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function parentAllocator() +// ---------------------------------------------------------------------------- + +template +inline TParentAllocator & +parentAllocator(Allocator > & me) +{ + return value(me.data_parent_allocator); +} + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +/*! + * @fn Allocator#clear + * @brief Deallocates all memory blocks. + * + * @signature void clear(allocator); + * + * @param[in,out] The allocator to clear. + * + * @section Remarks + * + * This function deallocates all memory block sthat were allocated using allocate() for allocator. + * The memory is not pooled but directly passed back to the heap manager. + */ + +// TODO(holtgrew): Using #-functions messes up search results. +template +void +clear(Allocator > & me) +{ + typedef Allocator > TAllocator; + + while (me.data_storages) + { + typename TAllocator::Header * next_storage = me.data_storages->right; + deallocate(parentAllocator(me), reinterpret_cast(me.data_storages), me.data_storages->size); + me.data_storages = next_storage; + } +} + +// ---------------------------------------------------------------------------- +// Function allocate() +// ---------------------------------------------------------------------------- + +template +inline void +allocate(Allocator > & me, + TValue * & data, + TSize count, + Tag const &) +{ + typedef Allocator > TAllocator; + typedef typename TAllocator::Header THeader; + + //compute needed bytes + size_t bytes_needed = count * sizeof(TValue) + sizeof(THeader); + + //allocate storage from parent + char * ptr; + allocate(parentAllocator(me), ptr, bytes_needed, TagAllocateStorage()); + + THeader * new_block = reinterpret_cast(ptr); + new_block->left = 0; + new_block->right = me.data_storages; + new_block->size = bytes_needed; + + if (me.data_storages) + { + me.data_storages->left = new_block; + } + me.data_storages = new_block; + + //return data + data = reinterpret_cast(ptr + sizeof(THeader)); +} + +// ---------------------------------------------------------------------------- +// Function deallocate() +// ---------------------------------------------------------------------------- + +template +inline void +deallocate(Allocator > & me, + TValue * data, + TSize, + Tag const &) +{ + typedef Allocator > TAllocator; + typedef typename TAllocator::Header THeader; + + //update links + THeader & header = *(reinterpret_cast(data) - 1); + if (header.left) + { + header.left->right = header.right; + } + else + { + me.data_storages = header.right; + } + if (header.right) + { + header.right->left = header.left; + } + + //deallocate storage using parent + char * ptr = reinterpret_cast(& header); + deallocate(parentAllocator(me), ptr, header.size); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_SIMPLE_H_ diff --git a/seqan/basic/allocator_singlepool.h b/seqan/basic/allocator_singlepool.h new file mode 100644 index 0000000..314cdab --- /dev/null +++ b/seqan/basic/allocator_singlepool.h @@ -0,0 +1,250 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// Allocator that pools blocks of a given size; Different-sized blocks are +// not pooled. +// ========================================================================== + +#ifndef SEQAN_BASIC_BASIC_ALLOCATOR_SINGLE_POOL_H_ +#define SEQAN_BASIC_BASIC_ALLOCATOR_SINGLE_POOL_H_ + +#include + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @class SinglePoolAllocator + * @extends Allocator + * @headerfile + * @brief Allocator that pools memory blocks of a specific size. + * + * @signature template + * class Allocator; + * + * @tparam SIZE The size of the blocks. + * @tparam TParentAllocator The parent allocator to use. + * + * A pool allocator allocates several memory blocks at once. Freed blocks are not immediately deallocated but + * recycled in subsequential allocations. This way, the number of calls to the heap manager is reduced, and that + * might speed up memory management. + * + * The single pool allocator only pools memory blocks of size at most $SIZE$. Blocks of other sizes are allocated and + * deallocated using an allocator of type $ParentAllocator$. Using the single pool allocator for blocksizes larger + * than a few KB is not advised. + */ + +template +struct SinglePool; + +template +struct Allocator > +{ + enum + { + // item must be large enough to keep a pointer to the next free item + SIZE_PER_ITEM = SIZE < sizeof(void*)? sizeof(void*) : SIZE, + ITEMS_PER_BLOCK = (SIZE_PER_ITEM < 0x0100) ? 0x01000 / SIZE_PER_ITEM : 16, + STORAGE_SIZE = SIZE_PER_ITEM * ITEMS_PER_BLOCK, + STORAGE_SIZE_MIN = SIZE_PER_ITEM + }; + + char * data_recycled_blocks; + char * data_current_begin; + char * data_current_end; + char * data_current_free; + Holder data_parent_allocator; + + Allocator() : data_recycled_blocks(), data_current_begin(), data_current_end(), data_current_free() + {} + + Allocator(size_t reserve_item_count) : data_recycled_blocks() + { + size_t storage_size = std::max(reserve_item_count * SIZE_PER_ITEM, STORAGE_SIZE_MIN); + allocate(parentAllocator(*this), data_current_begin, storage_size); + data_current_end = data_current_begin + storage_size; + data_current_free = data_current_begin; + } + + Allocator(TParentAllocator & parent_alloc) + { + setValue(data_parent_allocator, parent_alloc); + + data_recycled_blocks = data_current_end = data_current_free = 0; + //dont need to initialize data_current_begin + } + + Allocator(size_t reserve_item_count, TParentAllocator & parent_alloc) + { + data_recycled_blocks = 0; + + setValue(data_parent_allocator, parent_alloc); + + size_t storage_size = std::max(reserve_item_count * SIZE_PER_ITEM, STORAGE_SIZE_MIN); + allocate(parentAllocator(*this), data_current_begin, storage_size); + data_current_end = data_current_begin + storage_size; + data_current_free = data_current_begin; + } + + // Dummy copy + Allocator(Allocator const &) : + data_recycled_blocks(), data_current_begin(), data_current_end(), + data_current_free() + { + data_recycled_blocks = data_current_end = data_current_free = 0; + } + + inline Allocator & + operator=(Allocator const &) + { + clear(*this); + return *this; + } + + ~Allocator() + { + clear(*this); + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function parentAllocator() +// ---------------------------------------------------------------------------- + +template +inline TParentAllocator & +parentAllocator(Allocator > & me) +{ + return value(me.data_parent_allocator); +} + +// ---------------------------------------------------------------------------- +// Function clear() +// ---------------------------------------------------------------------------- + +template +void +clear(Allocator > & me) +{ + me.data_recycled_blocks = me.data_current_end = me.data_current_free = 0; + clear(parentAllocator(me)); +} + +// ---------------------------------------------------------------------------- +// Function allocate() +// ---------------------------------------------------------------------------- + +template +inline void +allocate(Allocator > & me, + TValue * & data, + TSize count, + Tag const tag_) +{ + typedef Allocator > TAllocator; + size_t bytes_needed = count * sizeof(TValue); + + if (bytes_needed > TAllocator::SIZE_PER_ITEM) + {//no blocking + allocate(parentAllocator(me), data, count, tag_); + return; + } + + if (bytes_needed < TAllocator::SIZE_PER_ITEM) + bytes_needed = TAllocator::SIZE_PER_ITEM; + + char * ptr; + if (me.data_recycled_blocks) + {//use recycled + ptr = me.data_recycled_blocks; + me.data_recycled_blocks = * reinterpret_cast(ptr); + } + else + {//use new + ptr = me.data_current_free; + if (ptr + bytes_needed > me.data_current_end) + {//not enough free space in current storage: allocate new + allocate(parentAllocator(me), ptr, (size_t) TAllocator::STORAGE_SIZE, tag_); + me.data_current_begin = ptr; + me.data_current_end = ptr + TAllocator::STORAGE_SIZE; + } + me.data_current_free = ptr + bytes_needed; + } + + data = reinterpret_cast(ptr); +} + +// ---------------------------------------------------------------------------- +// Function deallocate() +// ---------------------------------------------------------------------------- + +template +inline void +deallocate(Allocator > & me, + TValue * data, + TSize count, + Tag const tag_) +{ + typedef Allocator > TAllocator; + + size_t bytes_needed = count * sizeof(TValue); + + if (bytes_needed > TAllocator::SIZE_PER_ITEM) + {//no blocking + deallocate(parentAllocator(me), data, count, tag_); + return; + } + + //link in recycling list + *reinterpret_cast(data) = me.data_recycled_blocks; + me.data_recycled_blocks = reinterpret_cast(data); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_BASIC_BASIC_ALLOCATOR_SINGLE_POOL_H_ diff --git a/seqan/basic/allocator_to_std.h b/seqan/basic/allocator_to_std.h new file mode 100644 index 0000000..b7d07a5 --- /dev/null +++ b/seqan/basic/allocator_to_std.h @@ -0,0 +1,206 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// Wrapper that adapts SeqAn allocators to STL allocators. +// ========================================================================== + +// TODO(holtgrew): Rename STD to STL? +// TODO(holtgrew): Rename to allocator_to_stl.h, remove basic_ prefix of all other allocator headers. + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_TO_STD_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_TO_STD_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @class ToStdAllocator + * @headerfile + * @brief Emulates standard conform allocator. + * + * @signature template + * class ToStdAllocator; + * + * @tparam TValue Type of allocated items. + * @tparam THost Type of the host allocator object.This object is used to call @link Allocator#allocate @endlink and + * @link Allocator#deallocate @endlink. + * + * The member functions allocate and deallocate of ToStdAllocator call the (globale) + * functions @link Allocator#allocate @endlink and @link Allocator#deallocate @endlink, respectively. The globale + * functions get an allocator object as their first arguments. This allocator object is not the ToStdAllocator + * object itself, but the host object that was given to the constructor. + * + * @fn ToStdAllocator#ToStdAllocator + * @brief Constructor + * + * @signature ToStdAllocator::ToStdAllocator(host); + * + * @param[in] host The host object that is used as allocator for @link Allocator#allocate @endlink and @link + * Allocator#deallocate @endlink. + */ + +template +struct ToStdAllocator +{ + typedef TValue value_type; // nolint + typedef value_type * pointer; // nolint + typedef value_type & reference; // nolint + typedef value_type const * const_pointer; // nolint + typedef value_type const & const_reference; // nolint + + typedef size_t size_type; // nolint + typedef ptrdiff_t difference_type; // nolint + + ToStdAllocator(THost & host): m_host(& host) + {} + + template + ToStdAllocator(ToStdAllocator const & alloc) + : m_host(alloc.m_host) + {} + + ToStdAllocator & operator= (ToStdAllocator const & alloc) + { + m_host = alloc.m_host; + return *this; + } + + pointer allocate(size_type count) + { + value_type * ptr; + seqan::allocate(*m_host, ptr, count); + return pointer(ptr); + } + + pointer allocate(size_type count, const void *) + { + value_type * ptr; + seqan::allocate(*m_host, ptr, count); + return pointer(ptr); + } + + void deallocate(pointer data, size_type count) + { + seqan::deallocate(*m_host, data, count); + } + + void construct(pointer ptr, const_reference data) + { + new(ptr) TValue(data); + } + + void destroy(pointer ptr) + { + ptr->~TValue(); + } + + pointer address(reference value) const + { + return (&value); + } + + const_pointer address(const_reference value) const + { + return (&value); + } + + size_type max_size() const + { + return ~0UL / sizeof(value_type); + } + + template + struct rebind // nolint + { + typedef ToStdAllocator other; // nolint + }; + + template + friend + struct ToStdAllocator; + +private: + THost * m_host; +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction ToStdAllocator() +// ---------------------------------------------------------------------------- + +template +struct StdAllocator +{ + typedef ToStdAllocator Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function host() +// ---------------------------------------------------------------------------- + +/*! + * @fn ToStdAllocator#host + * @headerfile + * @brief The object a given object depends on. + * + * @signature THost host(allocator); + * + * @param[in] allocator The allocator to query. + * + * @return THost The host object. + */ + +template +THost & +host(ToStdAllocator & me) +{ + return *me.m_host; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALLOCATOR_TO_STD_H_ diff --git a/seqan/basic/alphabet_adapt_builtins.h b/seqan/basic/alphabet_adapt_builtins.h new file mode 100644 index 0000000..a5db639 --- /dev/null +++ b/seqan/basic/alphabet_adapt_builtins.h @@ -0,0 +1,236 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Döring +// ========================================================================== +// Adaptions of builting types such as bool, int, but also "builtin-level" +// user defined types such as wchar_t, int64_t, uint64_t to the alphabet +// concepts they are in. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_BASIC_ALPHABET_ADAPT_BUILTINS_H_ +#define SEQAN_INCLUDE_BASIC_ALPHABET_ADAPT_BUILTINS_H_ + +#include + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunctions MaxValue_, MinValue_ +// ---------------------------------------------------------------------------- + +// We would want to have this here, however this is not possible with the +// current implementation. + +// ---------------------------------------------------------------------------- +// Metafunction BitsPerValue +// ---------------------------------------------------------------------------- + +template <> +struct BitsPerValue +{ + typedef int Type; + enum { VALUE = 1 }; +}; + +// ---------------------------------------------------------------------------- +// Metafunction IsCharType +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): This should probably become a concept. + +/*! + * @mfn IsCharType + * @headerfile + * + * @brief Return whether the argument is char, wchar_t, char const, or wchar_t + * const. + * + * @signature IsCharType::Type; + * @signature IsCharType::VALUE; + * + * @tparam T Type to check type of. + * + * This metafunction is used to enable and disable templated adaptions of arrays to sequences for builtin character + * types only. + * + * The return value is True/true for char, wchar_t, char const, and + * wchar_t const. + */ + +template +struct IsCharType; + +template +struct IsCharType +{ + typedef False Type; + enum { VALUE = 0 }; +}; + +template +struct IsCharType + : IsCharType {}; + +template <> +struct IsCharType +{ + typedef True Type; + enum { VALUE = 1 }; +}; + +template <> +struct IsCharType +{ + typedef True Type; + enum { VALUE = 1 }; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function gapValueImpl() [char] +// ---------------------------------------------------------------------------- + +inline char const & +gapValueImpl(char *) +{ + static char const _gap = '-'; + return _gap; +} + +inline char const & +gapValueImpl(char const *) +{ + static char const _gap = '-'; + return _gap; +} + +// ---------------------------------------------------------------------------- +// Function unknownValueImpl() [char] +// ---------------------------------------------------------------------------- + +inline char const & +unknownValueImpl(char *) +{ + static char const _unknown = 'N'; + return _unknown; +} + +inline char const & +unknownValueImpl(char const *) +{ + static char const _unknown = 'N'; + return _unknown; +} + +// ---------------------------------------------------------------------------- +// Function supremumValueImpl() +// ---------------------------------------------------------------------------- + +template +inline T const & +supremumValueImpl(T *) +{ + static T const x = MaxValue::VALUE; + return x; +} + +inline long double const & +supremumValueImpl(long double *) +{ + static long double const _value = std::numeric_limits::infinity( ); + return _value; +} + +inline double const & +supremumValueImpl(double *) +{ + static double const _value = std::numeric_limits::infinity( ); + return _value; +} +inline float const & +supremumValueImpl(float *) +{ + static float const _value = std::numeric_limits::infinity( ); + return _value; +} + +// ---------------------------------------------------------------------------- +// Function infimumValueImpl() +// ---------------------------------------------------------------------------- + +template +inline T const & +infimumValueImpl(T *) +{ + static T const x = MinValue::VALUE; + return x; +} + +inline float const & +infimumValueImpl(float *) +{ + static float const _value = -std::numeric_limits::infinity( ); + return _value; +} + +inline double const & +infimumValueImpl(double *) +{ + static double const _value = -std::numeric_limits::infinity( ); + return _value; +} + +inline long double const & +infimumValueImpl(long double *) +{ + static long double const _value = -std::numeric_limits::infinity( ); + return _value; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_BASIC_ALPHABET_ADAPT_BUILTINS_H_ diff --git a/seqan/basic/alphabet_bio.h b/seqan/basic/alphabet_bio.h new file mode 100644 index 0000000..0339e34 --- /dev/null +++ b/seqan/basic/alphabet_bio.h @@ -0,0 +1,101 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// Author: Manuel Holtgrewe +// ========================================================================== +// Alphabet concepts stemming from biological applications. +// ========================================================================== + +// TODO(holtgrew): Where is the documentation, shouldnt it be here? + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_BIO_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_BIO_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function gapValueImpl +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): This looks wrong. + +template +inline T +gapValueImpl(T *) +{ + static T const _gap = T(); + return _gap; +} + +// ---------------------------------------------------------------------------- +// Function gapValue +// ---------------------------------------------------------------------------- + +template +inline T +gapValue() +{ + static T * _tag = 0; + return gapValueImpl(_tag); +} + +// ---------------------------------------------------------------------------- +// Function unknownValue +// ---------------------------------------------------------------------------- + +template +inline T +unknownValue() +{ + static T * _tag = 0; + return unknownValueImpl(_tag); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_BIO_H_ diff --git a/seqan/basic/alphabet_concept.h b/seqan/basic/alphabet_concept.h new file mode 100644 index 0000000..50e5164 --- /dev/null +++ b/seqan/basic/alphabet_concept.h @@ -0,0 +1,586 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// Author: Manuel Holtgrewe +// ========================================================================== +// Concept definitions for alphabets. +// ========================================================================== + +// SEQAN_NO_GENERATED_FORWARDS + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_CONCEPT_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_CONCEPT_H_ + +namespace seqan { + +// ============================================================================ +// Concepts for generic alphabets +// ============================================================================ + +/*! + * @concept AlphabetConcept + * @extends AssignableConcept + * @extends DefaultConstructibleConcept + * @extends CopyConstructibleConcept + * @headerfile + * @brief Natural container value. + * + * @signature concept AlphabetConcept; + * + * @section Examples + * + * Valid expressions (v is of type T): + * + * @code{.cpp} + * unsigned bpv = BitsPerValue::VALUE; + * @endcode + */ + +/*! + * @mfn AlphabetConcept#BitsPerValue + * @headerfile + * @brief Number of bits needed to store a value. + * + * @signature BitsPerValue::VALUE + * + * @tparam T A class. + * + * @return VALUE The number of bits needed to store a value. + */ + +// Forwards for Metafunctions and Functions. +template struct BitsPerValue; + +// minimal requirements for the alphabet of a String class +SEQAN_CONCEPT_REFINE(AlphabetConcept, (TValue), (Assignable)(DefaultConstructible)(CopyConstructible)) +{ + typedef typename BitsPerValue::Type TBitsPerValue; + + TValue val, val2; + + SEQAN_CONCEPT_USAGE(AlphabetConcept) + { + SEQAN_STATIC_ASSERT_MSG(BitsPerValue::VALUE != 0, "Alphabet types must implement the BitsPerValue metafunction with non-zero value."); + + // assign must be available as an equivalent to '=' + assign(val, val2); +// swap(val, val2); + + TBitsPerValue b = BitsPerValue::VALUE; + + ignoreUnusedVariableWarning(b); + } +}; + +// ============================================================================ +// Concepts For Alphabets From The Mathematics Domain. +// ============================================================================ + +/*! + * @concept OrderedAlphabetConcept + * @extends AlphabetConcept + * @extends ComparableConcept + * @headerfile + * + * @brief Totally strict ordered alphabet. + * + * @signature concept OrderedAlphabetConcept; + */ + +/*! + * @fn OrderedAlphabetConcept::operator< + * @brief Less-than operator. + * + * @signature bool OrderedAlphabetConcept::operator<(other); + * + * @param[in] other Object of the same type to compare to this. + * + * @return bool True in case of this object being smaller than other + */ + +/*! + * @mfn OrderedAlphabetConcept#MaxValue + * @headerfile + * @brief Supremum for a given type. + * + * @signature MaxValue::VALUE + * + * @tparam T An ordered type. + * + * @return VALUE The largest value that T can represent. + * + * @see OrderedAlphabetConcept#maxValue + */ + +/*! + * @mfn OrderedAlphabetConcept#MinValue + * @headerfile + * @brief Infimum for a given type. + * + * @signature MinValue::VALUE + * + * @tparam T An ordered type. + * + * @return VALUE The smallest value that T can represent. + * + * @see OrderedAlphabetConcept#minValue + */ + +/*! + * @fn OrderedAlphabetConcept#supremumValueImpl + * @brief Implements maxValue. + * + * @signature T supremumValueImpl(valuePointerTag); + * + * @param[in] valuePointerTag A pointer that is used as a tag to specify the value type. The pointer needs not to point + * to a valid object, so it is possible to use a null pointer here. + * + * @return T A value inf that holds: inf >= i for all values i. + * + * This function implements OrderedAlphabetConcept#maxValue. It is recommended to use OrderedAlphabetConcept#maxValue + * rather than supremumValueImpl. + * + * @section Status + * + * Deprecated, will be removed in favour of OrderedAlphabetConcept#MaxValue. + * + * @see OrderedAlphabetConcept#maxValue + */ + +/*! + * @fn OrderedAlphabetConcept#maxValue + * @brief Supremum for a given type. + * + * @signature T maxValue(); + * + * @tparam T The type to get the max value of. + * + * @return T A value inf that holds: inf >= i for all values i of type T. + * + * The function is implemented in supremumValueImpl. Do not specialize maxValue, specialize supremumValueImpl + * instead! + * + * @section Status + * + * Deprecated, will be removed in favour of MaxValue. + * + * @see OrderedAlphabetConcept#supremumValueImpl + * @see OrderedAlphabetConcept#minValue + * @see OrderedAlphabetConcept#MaxValue + */ + +/*! + * @fn OrderedAlphabetConcept#infimumValueImpl + * @brief Implements minValue. + * + * @signature T infimumValueImpl(valuePointerTag); + * + * @param[in] valuePointerTag A pointer that is used as a tag to specify the value type. The pointer needs not to point + * to a valid object, so it is possible to use a null pointer here. + * + * @return T A value inf that holds: inf <= i for all values i. + * + * This function implements minValue. It is recommended to use minValue rather than infimumValueImpl. + * + * @section Status + * + * Deprecated, will be removed in favour of MinValue. + * + * @see OrderedAlphabetConcept#minValue + */ + +/*! + * @fn OrderedAlphabetConcept#minValue + * @brief Infimum for a given type. + * + * @signature T minValue(); + * + * @tparam T An ordered type. + * + * @return T A value inf that holds: inf <= i for all values i of type T. + * + * The function is implemented in infimumValueImpl. Do not specialize minValue, specialize infimumValueImpl + * instead! + * + * @section Status + * + * Deprecated, will be removed in favour of MinValue. + * + * @see OrderedAlphabetConcept#infimumValueImpl + * @see OrderedAlphabetConcept#maxValue + * @see OrderedAlphabetConcept#MinValue + */ + +// Forwards for Metafunctions and Functions. +template struct MinValue; +template struct MaxValue; +template T const & minValue(); +template T const & minValue(T); +template T const & maxValue(); +template T const & maxValue(T); + +SEQAN_CONCEPT_REFINE(OrderedAlphabetConcept, (TValue), (AlphabetConcept)(Comparable)) +{ + TValue val; + + SEQAN_CONCEPT_USAGE(OrderedAlphabetConcept) + { + // type consistency checks + sameType(minValue(val), val); + sameType(minValue(), val); + sameType(MinValue::VALUE, val); + sameType(maxValue(val), val); + sameType(maxValue(), val); + sameType(MaxValue::VALUE, val); + + // TODO(holtgrew): This does not work in C++98, we need C++11 with constexpr. + // TODO(holtgrew): Do these tests for each alphabet in runtime tests. + // sanity checks + // SEQAN_STATIC_ASSERT_MSG(MinValue::VALUE <= MaxValue::VALUE, "Minimal alphabet value must be less or equal to the maximal value."); + + // TODO(holtgrew): This does not work in C++98, we need C++11 with constexpr, cannot cast non-integral and non-enumeration types at compile time in C++98. + // 0 must be an element of the alphabet, as we want to be able + // to initialize a TValue variable to omit uninitialized warnings. + // SEQAN_STATIC_ASSERT_MSG(MinValue::VALUE <= static_cast(0), "0 must be convertible to a valid alphabet value."); + // SEQAN_STATIC_ASSERT_MSG(static_cast(0) <= MaxValue::VALUE, "0 must be convertible to a valid alphabet value."); + } +}; + +/*! + * @concept FiniteOrderedAlphabetConcept + * @headerfile + * @extends OrderedAlphabetConcept + * @brief An type that is of finite domain and totally ordered and thus has a minimum and maximum value. + */ + +/*! + * @mfn FiniteOrderedAlphabetConcept#ValueSize + * @brief Number of different values a value type object can have. + * + * @signature ValueSize::Type; + * @signature ValueSize::VALUE; + * + * @tparam T A type to query for its value size. + * + * @return VALUE The number of different values a value of type T can have. The type is Type. + * @return Type The type of the result VALUE. + * + * This function is only defined for integral types like unsigned, int, or Dna. For floating point + * numbers and the 64 bit types int64_t and uint64_t, it returns 0 since there is no standard + * compliant way to return the number of values for these types. + * + * Note that you cannot get pointers or references to ValueSize<T>::VALUE in your program. You can use + * @link FiniteOrderedAlphabetConcept#valueSize @endlink in your programs without problems, though. When you get + * problems in your tests, use the "unary plus" workaround from the examples section. + * + * @section Examples + * + * The temporary assignment workaround. + * + * @code{.cpp} + * SEQAN_ASSERT_EQ(ValueSize::VALUE, 2u); // Linker error. + * SEQAN_ASSERT_EQ(+ValueSize::VALUE, 2u); // OK + * SEQAN_ASSERT_EQ(valueSize(), 2u); // OK + * @endcode + */ + +/*! + * @fn FiniteOrderedAlphabetConcept#ordValue + * @headerfile + * @brief Maps an alphabet 1-to-1 to the interval [0..ValueSize). + * + * @signature T ordValue(value); + * + * @param[in] value Arbitrary character value. Types: SimpleType + * + * @return T An unsigned value (result of Size<typeof(value)> between 0 and ValueSize of the type of value. + * + * This function first converts value to its unsigned value type and after that to an unsigned int. You can't + * use (unsigned int)c for a character c as on some systems char is signed and a -1 + * would be mapped to 0xffffffff instead of 0x000000ff. + */ + +/*! + * @fn FiniteOrderedAlphabetConcept#valueSize + * @brief Returns size of an alphabet. + * + * @signature T1 valueSize(); + * + * @tparam T2 Type to query for value size. + * + * @return T1 Number of values in type T2. + * + * @see FiniteOrderedAlphabetConcept#ValueSize + */ + +// Forwards for Metafunctions and Functions. +template struct ValueSize; +template typename ValueSize::Type valueSize(); +// Forwards for Metafunctions and Functions. +template inline typename ValueSize::Type ordValue(TValue const & c); + +SEQAN_CONCEPT_REFINE(FiniteOrderedAlphabetConcept, (TValue), (OrderedAlphabetConcept)) +{ + typedef typename ValueSize::Type TSize; + + TValue val; + TSize size; + + SEQAN_CONCEPT_ASSERT((UnsignedIntegerConcept)); + + SEQAN_CONCEPT_USAGE(FiniteOrderedAlphabetConcept) + { + // a finite alphabet must be countable + sameType(ordValue(val), size); + sameType(valueSize(), size); + sameType(ValueSize::VALUE, size); + + // alphabet must be non-empty + SEQAN_STATIC_ASSERT_MSG(static_cast(0) < ValueSize::VALUE, "Alphabet size be greater than zero."); + + // convert integer to alphabet value + val = 0; + val = size; + TValue val2(0); + TValue val3(size); + + ignoreUnusedVariableWarning(val2); + ignoreUnusedVariableWarning(val3); + } +}; + +// ============================================================================ +// Concepts For Alphabets From The Bioinformatics Domain. +// ============================================================================ +/*! + * @concept AlphabetWithGapsConcept + * @extends AlphabetConcept + * @headerfile + * + * @brief An alphabet that includes a specific gap character. + */ + +/*! + * @fn AlphabetWithGapsConcept#gapValueImpl + * @brief Implements gapValue. + * + * @signature T gapValueImpl(valuePointerTag); + * + * @param[in] valuePointerTag A pointer that is used as a tag to specify the value type. The pointer needs not to + * point to a valid object, so it is possible to use a null pointer here. + * + * @return T A gap character. + * + * This function implements gapValue. It is recommended to use gapValue rather than gapValueImpl. + * + * @see AlphabetWithGapsConcept#gapValue + */ + +/*! + * @fn AlphabetWithGapsConcept#gapValue + * @brief Return the "gap" value from an alphabet. + * + * @signature T gapValue(); + * + * @tparam T The alphabet type to query the gap value from. + * + * @return T The gap character. + * + * The function is implemented in gapValueImpl. Do not specialize gapValue, specialize link gapValueImpl + * instead! + * + * @see AlphabetWithGapsConcept#gapValueImpl + */ + +// Forwards for Metafunctions and Functions. +template T gapValue(); +template T gapValueImpl(T *); + +SEQAN_CONCEPT_REFINE(AlphabetWithGapsConcept, (TValue), (AlphabetConcept)) +{ + TValue val; + + SEQAN_CONCEPT_USAGE(AlphabetWithGapsConcept) + { + // Test the availability and return type of gapValue() and gapValueImpl(). + sameType(gapValue(), val); + sameType(gapValueImpl(static_cast(0)), val); + } +}; + +/*! + * @concept AlphabetWithUnknownValueConcept + * @extends AlphabetConcept + * @headerfile + * + * @brief An alphabet which includes a specific "unknown" character. + */ + +/*! + * @fn AlphabetWithUnknownValueConcept#unknownValue + * + * @brief Return the "unknown" value from an alphabet. + * + * @signature T unknownValue(); + * + * @tparam T The alphabet type to query the unknown value from. + * + * @return TReturn The "unknown" value. + * + * @see AlphabetWithUnknownValueConcept#unknownValueImpl + */ + +/*! + * @fn AlphabetWithUnknownValueConcept#unknownValueImpl + * @brief Implements unknownValue. + * + * @signature T gapValueImpl(valuePointerTag) + * + * @param[in] valuePointerTag A pointer that is used as a tag to specify the value type. The pointer needs not to + * point to a valid object, so it is possible to use a null pointer here. + * + * @return TReturn A "unknown" character. + * + * This function implements unknownValue. It is recommended to use gapValue rather than gapValueImpl. + * + * @see AlphabetWithUnknownValueConcept#unknownValue + */ + +// Forwards for Metafunctions and Functions. +template T unknownValue(); +template T unknownValueImpl(T *); + +SEQAN_CONCEPT_REFINE(AlphabetWithUnknownValueConcept, (TValue), (AlphabetConcept)) +{ + TValue val; + + SEQAN_CONCEPT_USAGE(AlphabetWithUnknownValueConcept) + { + // Test the availability and return type of unknownValue() and unknownValueImpl(). + sameType(unknownValue(), val); + sameType(unknownValueImpl(static_cast(0)), val); + } +}; + +/*! + * @concept AlphabetWithQualitiesConcept + * @extends AlphabetConcept + * @headerfile + * + * @brief An alphabet where qualities can be attached to the characters. + */ + +/*! + * @mfn AlphabetWithQualitiesConcept#HasQualities + * @headerfile + * @brief Return whether the given type stores qualities besides the alphabet. + * + * @signature HasQualities::VALUE; + * @signature HasQualities::Type; + * + * @tparam TAlphabet The alphabe to query. + * + * @return VALUE true or false + * @return Type True or False + */ + +/*! + * @mfn AlphabetWithQualitiesConcept#QualityValueSize + * @brief Return the number of quality values in characters from alphabet with qualities. + * + * @signature QualityValueSize::VALUE; + * + * @tparam TAlphabet The alphabet to query for its value size. + * + * @return VALUE The cardinality of the set of qualities. + */ + +/*! + * @fn AlphabetWithQualitiesConcept#getQualityValue + * @brief Returns the quality of a character from an alphabet with integrated quality, e.g. the quality associated with + * a specified element from a sequence. + * @signature int getQualityValue(c); + * + * @param[in] c Character to retrieve the quality from. + * + * @return int Quality value of c. The quality value is an int value between 0 and 62 (inclusive). + * + * @section Examples + * + * @code{.cpp} + * String seq = "TATA"; + * // Assign quality value to first 'T' in sequence seq + * assignQualityValue(seq[0], 35); + * // Print quality value of first 'T', and default quality value of first 'A' + * std::cout << getQualityValue(seq[0]) << std::endl; // Defined as 35 + * std::cout << getQualityValue(seq[1]) << std::endl; // Default value 60 + * @endcode + * + * @see AlphabetWithQualitiesConcept#assignQualityValue + * @see convertQuality + */ + +/*! + * @fn AlphabetWithQualitiesConcept#assignQualityValue + * @brief Assigns quality to a character from an alphabet with integrated quality, e.g. to a specified element from a + * sequence. + * + * @signature void assignQualityValue(c, q); + * + * @param[out] c Target character to assign quality to. + * @param[in] q Quality to assign to the character. The quality value is an integral value between 0 and 62 + * (inclusive). + * + * If q is a char then '!' is subtracted from q. This is useful for ASCII encoded + * PHRED scores. + * + * @see AlphabetWithQualitiesConcept#getQualityValue + * @see convertQuality + * @see assignQualities + */ + +// TODO(holtgrew): What about different quality types? Guess scaling? Look at how other packages do this. + +SEQAN_CONCEPT_REFINE(AlphabetWithQualitiesConcept, (TValue), (AlphabetConcept)) +{ + TValue val; + + SEQAN_CONCEPT_USAGE(AlphabetWithQualitiesConcept) + { + // TODO(holtgrew): Write me! + } +}; + + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_CONCEPT_H_ diff --git a/seqan/basic/alphabet_math.h b/seqan/basic/alphabet_math.h new file mode 100644 index 0000000..c77afdb --- /dev/null +++ b/seqan/basic/alphabet_math.h @@ -0,0 +1,294 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// Author: Manuel Holtgrewe +// ========================================================================== +// Math functions for alphabets. +// ========================================================================== + +#include +#include + +#ifndef SEQAN_BASIC_ALPHABET_MATH_H_ +#define SEQAN_BASIC_ALPHABET_MATH_H_ + +// TODO(holtgrew): Move actual implementations to alphabet_adapt_builtins. IF POSSIBLE + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction MaxValue +// ---------------------------------------------------------------------------- + +template +struct MaximumValueUnsigned_ { static const T VALUE; }; + +template +const T MaximumValueUnsigned_::VALUE = ~(T)0; + +template +struct MaximumValueSigned_ { static const T VALUE; }; +template +struct MaximumValueFloat_ { static const float VALUE; }; +template +struct MaximumValueDouble_ { static const double VALUE; }; + +template +const T MaximumValueSigned_::VALUE = ((((T)1 << (BitsPerValue::VALUE - 2)) - 1) << 1) + 1; +template +const float MaximumValueFloat_::VALUE = FLT_MAX; +template +const double MaximumValueDouble_::VALUE = DBL_MAX; + +template <> +struct MaximumValueSigned_ +{ + static const bool VALUE = true; +}; + +// template <> +// const char MaximumValueUnsigned_::VALUE = CHAR_MAX; +// template <> +// const char MaximumValueSigned_::VALUE = CHAR_MAX; + +template < + typename T, + typename TParent = typename IfC< + IsSameType::VALUE, + MaximumValueDouble_<>, + typename IfC< + IsSameType::VALUE, + MaximumValueFloat_<>, + typename IfC< + IsSameType::Type, T>::VALUE, + MaximumValueSigned_, + MaximumValueUnsigned_ + >::Type + >::Type + >::Type + > +struct MaxValue_ : TParent {}; + +// We use two levels here, so we can forward declare MaxValue with one +// template parameter. + +template +struct MaxValue : MaxValue_ {}; + +// ---------------------------------------------------------------------------- +// Metafunction MinValue +// ---------------------------------------------------------------------------- + +template +struct MinimumValueUnsigned_ { static const T VALUE; }; +template +struct MinimumValueSigned_ { static const T VALUE; }; + +template +struct MinimumValueFloat_ { static const float VALUE; }; +template +struct MinimumValueDouble_ { static const double VALUE; }; + +template +const T MinimumValueUnsigned_::VALUE = T(0); +template +const T MinimumValueSigned_::VALUE = ~(T)MaximumValueSigned_::VALUE; +template +const float MinimumValueFloat_::VALUE = -FLT_MAX; +template +const double MinimumValueDouble_::VALUE = -DBL_MAX; + +template <> +struct MinimumValueSigned_ +{ + static const bool VALUE = false; +}; + +// template <> +// const char MinimumValueUnsigned_::VALUE = 0; +// template <> +// const char MinimumValueSigned_::VALUE = 0; + +template < + typename T, + typename TParent = typename IfC< + IsSameType::VALUE, + MinimumValueDouble_<>, + typename IfC< + IsSameType::VALUE, + MinimumValueFloat_<>, + typename IfC< + IsSameType::Type, T>::VALUE, + MinimumValueSigned_, + MinimumValueUnsigned_ + >::Type + >::Type + >::Type + > +struct MinValue_ : TParent {}; + +// We use two levels here, so we can forward declare MinValue with one +// template parameter. + +template +struct MinValue : MinValue_ {}; + +// ============================================================================ +// Functions +// ============================================================================ + +// -------------------------------------------------------------------------- +// Function toUpperValue() +// -------------------------------------------------------------------------- + +template +inline +TValue toUpperValue(TValue c) +{ + return c; +} + +inline +char toUpperValue(char c) +{ + return c >= 'a' && c <= 'z' ? c + 'A' - 'a' : c; +} + +inline +signed char toUpperValue(signed char c) +{ + return toUpperValue(static_cast(c)); +} + +inline +unsigned char toUpperValue(unsigned char c) +{ + return toUpperValue(static_cast(c)); +} + +// ---------------------------------------------------------------------------- +// Function supremumValueImpl +// ---------------------------------------------------------------------------- + +template inline T const & supremumValueImpl(T *); + +// ---------------------------------------------------------------------------- +// Function maxValue +// ---------------------------------------------------------------------------- + +// Forward to supremumValueImpl() only. + +template +inline T const & +maxValue() +{ + T * _tag = 0; + return supremumValueImpl(_tag); +} + +template +inline T const & +maxValue(T /*tag*/) +{ + T * _tag = 0; + return supremumValueImpl(_tag); +} + +// ---------------------------------------------------------------------------- +// Function infimumValueImpl +// ---------------------------------------------------------------------------- + +template inline T const & infimumValueImpl(T *); + +// ---------------------------------------------------------------------------- +// Function minValue +// ---------------------------------------------------------------------------- + +// Forward to infimumValueImpl() only. + +template +inline T const & +minValue() +{ + T * _tag = 0; + return infimumValueImpl(_tag); +} + +template +inline T const & +minValue(T /*tag*/) +{ + T * _tag = 0; + return infimumValueImpl(_tag); +} + +// ---------------------------------------------------------------------------- +// Function isNegative() +// ---------------------------------------------------------------------------- + +// to remove '... < 0 is always false' warning +template +inline bool +isNegative(T, False) +{ + return false; +} + +template +inline bool +isNegative(T t, True) +{ + return t < 0; +} + +template +inline bool +isNegative(T t) +{ + return isNegative(t, typename IsSameType::Type>::Type()); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_BASIC_ALPHABET_MATH_H_ diff --git a/seqan/basic/alphabet_profile.h b/seqan/basic/alphabet_profile.h new file mode 100644 index 0000000..ac81662 --- /dev/null +++ b/seqan/basic/alphabet_profile.h @@ -0,0 +1,382 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Tobias Rausch +// ========================================================================== +// Profile alphabet character code. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_PROFILE_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_PROFILE_H_ + +#include + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +template +class Proxy; + +template +struct IteratorProxy; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +/*! + * @class ProfileChar + * + * @headerfile + * + * @brief Alphabet type for profiles over another alphabet. + * + * @signature template + * class ProfileChar; + * + * @tparam TValue The underlying alphabet type. + * @tparam TCount The type to use for counting, default: unsigned int. + * @tparam TSpec Specialization tag, default: void + */ + +/*! + * @var VariableType ProfileChar::count[] + * + * @brief Array of ValueSize elements, giving counts in profile. + */ + +template +class ProfileChar; + +template +class ProfileChar +{ +public: + typedef typename ValueSize::Type TSize; + + TCount count[ValueSize::VALUE]; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + + ProfileChar() + { + memset::VALUE * sizeof(TCount), (unsigned char) 0>(count); + } + + ProfileChar(ProfileChar const & other_data) + { + for (TSize i = 0; i < ValueSize::VALUE; ++i) + count[i] = other_data.count[i]; + } + + // TODO(holtgrew): Limit TOther to SourceValue? + template + ProfileChar(TOther const & other_data) + { + memset::VALUE * sizeof(TCount), (unsigned char) 0>(count); + count[ordValue(TValue(other_data))] = 1; + } + + template + ProfileChar(Proxy const & proxy) + { + memset::VALUE * sizeof(TCount), (unsigned char) 0>(count); + assign(*this, getValue(proxy)); + } + + // ------------------------------------------------------------------------ + // Assignment operators; Have to be defined in class. + // ------------------------------------------------------------------------ + + ProfileChar & + operator=(ProfileChar const & other_data) + { + if (this == &other_data) return *this; + + for (TSize i = 0; i < ValueSize::VALUE; ++i) + count[i] = other_data.count[i]; + return *this; + } + + template + ProfileChar & + operator=(TOther const & other_data) + { + memset::VALUE * sizeof(TCount), 0u>(count); + count[ordValue(TValue(other_data))] = 1; + return *this; + } + + // ------------------------------------------------------------------------ + // Type conversion operators; Have to be defined in class. + // ------------------------------------------------------------------------ + + operator char() + { + typename Size::Type maxIndex = getMaxIndex(*this); + return (maxIndex == ValueSize::VALUE - 1) ? gapValue() : (char) TValue(maxIndex); + } +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction ValueSize +// ---------------------------------------------------------------------------- + +/*! + * @mfn ProfileChar#ValueSize + * @brief Number of different values a value type object can have. + * + * @signature ValueSize::VALUE; + * + * @tparam T The type to query. + * + * @return VALUE Number of different values T can have. + */ + +template +struct ValueSize > +{ + enum { VALUE = ValueSize::VALUE + 1 }; + typedef unsigned Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction SourceValue +// ---------------------------------------------------------------------------- + +/*! + * @mfn ProfileChar#SourceValue + * @brief Returns underlying value for ProfileChar. + * + * @signature SourceValue::Type + * + * @tparam T Type to query. + * + * @return Type The type of the underlying character. + * + * @section Examples + * + * @code{.cpp} + * typedef ProfileChar TProfileChar; + * typedef SourceValue::Type TType; // Is Dna. + * @endcode + */ + +template +struct SourceValue; + +template +struct SourceValue > +{ + typedef TValue Type; +}; + +template +struct SourceValue const> : + SourceValue > +{}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function operator==() +// ---------------------------------------------------------------------------- + +template +inline bool +operator==(ProfileChar const & lhs, + ProfileChar const & rhs) +{ + typedef ProfileChar TProfileChar; + typedef typename ValueSize::Type TValueSize; + + for (TValueSize i = 0; i < ValueSize::VALUE; ++i) + if (lhs.count[i] != rhs.count[i]) + return false; + return true; +} + +// ---------------------------------------------------------------------------- +// Function operator!=() +// ---------------------------------------------------------------------------- + +template +inline +bool +operator!=(ProfileChar const & lhs, + ProfileChar const & rhs) +{ + typedef ProfileChar TProfileChar; + typedef typename ValueSize::Type TSize; + + for (TSize i = 0; i < ValueSize::VALUE; ++i) + if (lhs.count[i] != rhs.count[i]) + return true; + return false; +} + +// ---------------------------------------------------------------------------- +// Function empty() +// ---------------------------------------------------------------------------- + +/*! + * @fn ProfileChar#empty + * @brief Check whether there are only gaps in the representation of the ProfileChar. + * + * @signature bool empty(c); + * + * @param c ProfileChar to query. + * @return bool Whether or not the ProfileChar only contains gaps. + */ +template +bool empty(ProfileChar const & source) +{ + typedef typename ValueSize const>::Type TSize; + + for (TSize i = 0; i < ValueSize::VALUE; ++i) + if (source.count[i]) + return false; + return true; +} + +// ---------------------------------------------------------------------------- +// Helper Function getMaxIndex() +// ---------------------------------------------------------------------------- + +/*! + * @fn ProfileChar#getMaxIndex + * @brief Return number of dominating entry in ProfileChar. + * + * @signature TSize getMaxIndex(c); + * + * @param[in] c ProfileChar to query for its dominating entry. + * @return TSize index (with the @link FiniteOrderedAlphabetConcept#ordValue @endlink) of the dominating character + * in c + */ +template +typename Size const>::Type +getMaxIndex(ProfileChar const & source) +{ + typedef ProfileChar TProfileChar; + typedef typename Size::Type TSize; + TSize maxIndex = 0; + TSourceCount maxCount = source.count[0]; + for (TSize i = 1; i < ValueSize::VALUE; ++i) + { + if (source.count[i] > maxCount) + { + maxIndex = i; + maxCount = source.count[i]; + } + } + return maxIndex; +} + +// ---------------------------------------------------------------------------- +// Helper Function totalCount() +// ---------------------------------------------------------------------------- + +/*! + * @fn ProfileChar#totalCount + * @brief Return sum of counts in ProfileChar. + * + * @signature TCount totalCount(c); + * + * @param[in] c ProfileChar to query. + * @return TCount Total number of characters represented by c. + */ +template +TSourceCount totalCount(ProfileChar const & source) +{ + typedef ProfileChar TProfileChar; + typedef typename Size::Type TSize; + TSourceCount totalCount = source.count[0]; + for (TSize i = 1; i < ValueSize::VALUE; ++i) + totalCount += source.count[i]; + return totalCount; +} + + +// ---------------------------------------------------------------------------- +// Function assign() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): What if there only are gaps? + +template +inline void +assign(SimpleType & target, + ProfileChar const & source) +{ + target.value = getMaxIndex(source); +} + +// ---------------------------------------------------------------------------- +// Function convertImpl() +// ---------------------------------------------------------------------------- + +template +inline typename Convert >::Type +convertImpl(Convert const &, + ProfileChar const & source) +{ + return (getMaxIndex(source) == ValueSize::VALUE) ? convertImpl(Convert(), '-') : convertImpl(Convert(), TSourceValue(getMaxIndex(source))); +} + +// ---------------------------------------------------------------------------- +// Function operator<<(); Stream output. +// ---------------------------------------------------------------------------- + +template +inline TStream & +operator<<(TStream & os, ProfileChar const & rhs) +{ + typedef ProfileChar TProfileChar; + typedef typename Size::Type TSize; + for (TSize i = 0; i < ValueSize::VALUE; ++i) + os << i << ':' << rhs.count[i] << ' ' << ';'; + return os; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_PROFILE_H_ diff --git a/seqan/basic/alphabet_qualities.h b/seqan/basic/alphabet_qualities.h new file mode 100644 index 0000000..b3b79de --- /dev/null +++ b/seqan/basic/alphabet_qualities.h @@ -0,0 +1,129 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// Author: Manuel Holtgrewe +// ========================================================================== +// Definitions for piggybacking qualities in free bits of bytes. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_QUALITIES_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_QUALITIES_H_ + +// TODO(holtgrew): Should the documentation be here? + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction QualityValueSize +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Do we want a default specialization? Should it return 0? +template +struct QualityValueSize +{ + enum { VALUE = ValueSize::VALUE }; +}; + +template +struct QualityValueSize : QualityValueSize +{}; + +// ---------------------------------------------------------------------------- +// Metafunction HasQualities +// ---------------------------------------------------------------------------- + +template +struct HasQualities +{ + typedef False Type; + static const bool VALUE = false; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function assignQualityValue() +// ---------------------------------------------------------------------------- + +// Documentation is in alphabet_concept.h. + +// ---------------------------------------------------------------------------- +// Function getQualityValue() +// ---------------------------------------------------------------------------- + +// Documentation is in alphabet_concept.h. + +// ---------------------------------------------------------------------------- +// Function convertQuality() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): This could use some thought, what about other scales? + +/*! + * @fn convertQuality + * @headerfile + * + * @brief Convert an integer quality value into its ASCII representation for FASTQ (Phred scale). + * + * @signature void convertQuality(c, q); + * + * @param[in] q Value of the quality to convert. The quality value is an integral value between 0 and 62 + * (inclusive), int. + * @param[out] c Character to store the quality in, char. + * + * @see AlphabetWithQualitiesConcept#getQualityValue + * @see AlphabetWithQualitiesConcept#assignQualityValue + */ + +inline +void convertQuality(char & c, int q) +{ + c = '!' + char(q); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_QUALITIES_H_ diff --git a/seqan/basic/alphabet_residue.h b/seqan/basic/alphabet_residue.h new file mode 100644 index 0000000..fae9710 --- /dev/null +++ b/seqan/basic/alphabet_residue.h @@ -0,0 +1,1493 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// Implementation of the biological SimpleType specializations Dna, Dna5, +// DnaQ, Dna5Q, Rna, Rna5, Iupac, and AminoAcid. The conversion tables are +// in alphabet_residue_tabs.h. +// +// This header's structure is an exception to the standard. Because +// splitting into one header for each specialization is a bit too much, we +// define all types in one header. We define the classes, metafunctions and +// functions in one section, one subsection for reach type to make the whole +// thing more readable. Conversion through assignment is defined in the +// Function section. +// ========================================================================== + +// TODO(holtgrew): Add RnaQ and Rna5Q? Can we create a tag/type for Dna and Rna that is then differentiated with one additional tag? + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_RESIDUE_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_RESIDUE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +template struct BaseAlphabet; + +// ============================================================================ +// Classes, Metafunctions, Functions +// ============================================================================ + +// Also see comment at the top for more information on this exceptional +// structure. +// +// We define the SimpleType specializations, the metafunctions ValueSize and +// BitsPerValue and the functions unknownValueImpl() for each specialization in +// this section. + +// ---------------------------------------------------------------------------- +// Specialization Dna +// ---------------------------------------------------------------------------- + +/*! + * @class Dna + * @extends SimpleType + * @headerfile + * @brief Alphabet for DNA. + * + * @signature typedef SimpleType Dna; + * + * The ValueSize of Dna is 4. The nucleotides are enumerated this way: 'A' = 0, 'C' = 1, 'G' = 2, 'T' = + * 3. + * + * Objects of type Dna can be converted to various other types and vice versa. An object that has a value not + * in {'A', 'C', 'G', 'T'} is converted to 'A'. + * + * @see Dna5 + * @see DnaString + * @see DnaIterator + */ + +struct Dna_ {}; +typedef SimpleType Dna; + +template <> +struct ValueSize +{ + typedef uint8_t Type; + static const Type VALUE = 4; +}; + +template <> +struct BitsPerValue< Dna > +{ + typedef uint8_t Type; + static const Type VALUE = 2; +}; + +// ---------------------------------------------------------------------------- +// Specialization Dna5 +// ---------------------------------------------------------------------------- + +/*! + * @class Dna5 + * @extends SimpleType + * @headerfile + * @brief Alphabet for DNA including 'N' character. + * + * @signature typedef SimpleType Dna5; + * + * The @link FiniteOrderedAlphabetConcept#ValueSize @endlink of Dna5 is 5. The nucleotides are enumerated this + * way: 'A' = 0, 'C' = 1, 'G' = 2, 'T' = 3. The 'N' character ("unkown nucleotide") is encoded by 4. + * + * Objects of type Dna5 can be converted to various other types and vice versa. An object that has a value not + * in {'A', 'C', 'G', 'T'} is converted to 'N'. + * + * @see Dna5Iterator + * @see Dna5String + * @see Dna + */ + +struct Dna5_ {}; +typedef SimpleType Dna5; + +template <> +struct ValueSize +{ + typedef uint8_t Type; + static const Type VALUE = 5; +}; + +template <> +struct BitsPerValue +{ + typedef uint8_t Type; + static const Type VALUE = 3; +}; + +inline Dna5 +unknownValueImpl(Dna5 *) +{ + static const Dna5 _result = Dna5('N'); + return _result; +} + +// ---------------------------------------------------------------------------- +// Specialization DnaQ +// ---------------------------------------------------------------------------- + +/*! + * @class DnaQ + * @extends SimpleType + * @headerfile + * @implements AlphabetWithQualitiesConcept + * @brief Alphabet for DNA plus PHRED quality. + * + * @signature typedef SimpleType DnaQ; + * + * The ValueSize of DnaQ is 4. The nucleotides are enumerated this way: 'A' = 0, 'C' = 1, 'G' = 2, 'T' = + * 3. + * + * Objects of type DnaQ can be converted to various other types and vice versa. + * + * Note that the default quality value is set to 60. + * + * @see Dna5Q + * @see Dna + */ + +#ifndef SEQAN_DEFAULT_QUALITY +#define SEQAN_DEFAULT_QUALITY 40 +#endif + +struct DnaQ_ {}; +typedef SimpleType DnaQ; + +template <> struct ValueSize +{ + typedef uint8_t Type; + static const ValueSize::Type VALUE = 4; // Considering nucleotides. +}; + +template <> struct InternalValueSize_ +{ + enum { VALUE = 252 }; // Considering nucleotides x Quality 0..62. +}; + +template <> struct BitsPerValue +{ + enum { VALUE = 8 }; + typedef uint8_t Type; +}; + +template <> struct HasQualities +{ + typedef True Type; + static const bool VALUE = true; +}; + +template <> +struct BaseAlphabet +{ + typedef Dna Type; +}; + +template <> +struct QualityValueSize +{ + enum { VALUE = 63 }; // 64 - 1 (N) +}; + +template +inline int getQualityValue(TValue const &) +{ + return 0; +} + +inline int getQualityValue(DnaQ const & c) +{ + return c.value >> 2; +} + +inline +void assignQualityValue(DnaQ & c, int q) +{ + if (q < 0) q = 0; + if (q >= QualityValueSize::VALUE) + q = QualityValueSize::VALUE - 1; + c.value = (c.value & 3) | (q << 2); +} + +inline +void assignQualityValue(DnaQ & c, char q) +{ + int q1 = static_cast(q - '!'); + if (q1 < 0) q1 = 0; + if (q1 >= QualityValueSize::VALUE) + q1 = QualityValueSize::VALUE - 1; + assignQualityValue(c, q1); +} + +inline +void assignQualityValue(char & q, DnaQ c) +{ + q = '!' + getQualityValue(c); +} + + +// ---------------------------------------------------------------------------- +// Specialization Dna5Q +// ---------------------------------------------------------------------------- + +/*! + * @class Dna5Q + * @extends SimpleType + * @headerfile + * @implements AlphabetWithQualitiesConcept + * @brief Alphabet for DNA plus PHRED quality including 'N' character. + * + * @signature typedef SimpleType Dna5Q; + * + * The ValueSize of Dna5Q is 5. The nucleotides are enumerated this way: 'A' = 0, 'C' = 1, 'G' = 2, 'T' = + * 3. The 'N' character ("unknown nucleotide") is encoded by 4. + * + * Objects of type Dna5 can be converted to various other types and vice versa. + * + * Note that the default quality value is set to 40. + * + * @see Dna5 + * @see DnaQ + */ + +struct Dna5Q_ {}; +typedef SimpleType Dna5Q; + +static const unsigned char Dna5QValueN_ = 252; // value representing N + +template <> struct ValueSize +{ + typedef uint8_t Type; + static const Type VALUE = 5; // Considering nucleotides + N. +}; + +template <> struct InternalValueSize_ +{ + enum { VALUE = 253 }; // Considering (nucleotides x Quality 0..62) + N. +}; + +template <> struct BitsPerValue +{ + enum { VALUE = 8 }; + typedef uint8_t Type; +}; + +template <> struct HasQualities +{ + typedef True Type; + static const bool VALUE = true; +}; + +template <> +struct BaseAlphabet +{ + typedef Dna5 Type; +}; + +template <> struct +QualityValueSize +{ + enum { VALUE = 63 }; +}; + +inline Dna5Q +unknownValueImpl(Dna5Q *) +{ + static const Dna5Q _result = Dna5Q('N'); + return _result; +} + +inline int getQualityValue(Dna5Q const &c) +{ + // We use a lookup table to extract the qualities from DNA5Q. The lookup + // table based code is equivalent to the following line: + // return (c.value == Dna5QValueN_)? 0: c.value >> 2; + + static const unsigned table[] = { + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, + 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, + 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, + 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, + 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, + 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, + 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, + 34, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, 38, + 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, + 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, + 46, 47, 47, 47, 47, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, + 51, 51, 51, 51, 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, + 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, + 59, 59, 60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, + 0, 0, 0, 0}; + return table[c.value]; +} + +inline +void assignQualityValue(Dna5Q &c, int q) +{ + if (q < 0) q = 0; + if (q >= QualityValueSize::VALUE) + q = QualityValueSize::VALUE - 1; + if (c.value != Dna5QValueN_) + c.value = (c.value & 3) | (q << 2); +} + +inline +void assignQualityValue(Dna5Q &c, char q) +{ + int q1 = static_cast(q - '!'); + if (q1 < 0) q1 = 0; + if (q1 >= QualityValueSize::VALUE) + q1 = QualityValueSize::VALUE - 1; + assignQualityValue(c, q1); +} + +inline +void assignQualityValue(char & q, Dna5Q c) +{ + q = '!' + getQualityValue(c); +} + +// ---------------------------------------------------------------------------- +// Specialization Rna +// ---------------------------------------------------------------------------- + +/*! + * @class Rna + * @extends SimpleType + * @headerfile + * @brief Alphabet for RNA. + * + * @signature typedef SimpleType Rna; + * + * The ValueSize of Rna is 4. The nucleotides are enumerated this way: 'A' = 0, 'C' = 1, 'G' = 2, 'U' = + * 3. + * + * Objects of type Rna can be converted to various other types and vice versa. An object that has a value not + * in {'A', 'C', 'G', 'U'} is converted to 'A'. + * + * Rna is typedef for SimpleType, while Rna_ is a helper specialization tag class. + * + * @see Rna5 + * @see RnaString + * @see RnaIterator + */ + +struct Rna_ {}; +typedef SimpleType Rna; + +template <> +struct ValueSize +{ + typedef uint8_t Type; + static const Type VALUE = 4; +}; + +template <> +struct BitsPerValue +{ + typedef uint8_t Type; + static const Type VALUE = 2; +}; + +// ---------------------------------------------------------------------------- +// Specialization Rna5 +// ---------------------------------------------------------------------------- + +/*! + * @class Rna5 + * @extends SimpleType + * @headerfile + * @brief Alphabet for RNA including 'N' character. + * + * @signature typedef SimpleType Rna5; + * + * The ValueSize of Rna5 is 5. The nucleotides are enumerated this way: 'A' = 0, 'C' = 1, 'G' = 2, 'U' = + * 3. The 'N' character ("unkown nucleotide") is encoded by 4. + * + * Objects of type Rna5 can be converted to various other types and vice versa. An object that has a value not + * in {'A', 'C', 'G', 'U'} is converted to 'N'. + * + * @see Rna5Iterator + * @see Rna5String + * @see Rna + */ + +struct Rna5_ {}; +typedef SimpleType Rna5; + +template <> +struct ValueSize +{ + typedef uint8_t Type; + static const Type VALUE = 5; +}; + +template <> struct BitsPerValue +{ + typedef uint8_t Type; + static const Type VALUE = 3; +}; + +inline Rna5 +unknownValueImpl(Rna5 *) +{ + static const Rna5 _result = Rna5('N'); + return _result; +} + +// ---------------------------------------------------------------------------- +// Specialization Iupac +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): We should support retrieval of nucleotides represented by a IUPAC char. + +/*! + * @class Iupac + * @extends SimpleType + * @headerfile + * @brief Iupac code for DNA. + * + * @signature typedef SimpleType Iupac; + * + * The ValueSize of Iupac is 16. The nucleotides are enumerated from 0 to 19 in this order: 'U'=0, 'T', 'A', + * 'W', 'C', 'Y', 'M', 'H', 'G', 'K', 'R', 'D', 'S', 'B', 'V', 'N'=15. + * + * Objects of type Iupac can be converted to various other types and vice versa. Unknown values are converted + * to 'N'. + * + * @see IupacString + * @see IupacIterator + */ + +struct Iupac_ {}; +typedef SimpleType Iupac; + +template <> struct ValueSize +{ + typedef uint8_t Type; + static const Type VALUE = 16; +}; + +template <> struct BitsPerValue +{ + typedef uint8_t Type; + static const Type VALUE = 4; +}; + +inline Iupac +unknownValueImpl(Iupac *) +{ + static const Iupac _result = Iupac('N'); + return _result; +} + +// ---------------------------------------------------------------------------- +// Specialization AminoAcid +// ---------------------------------------------------------------------------- + +/*! + * @class AminoAcid + * @extends SimpleType + * @headerfile + * @brief IUPAC code for amino acids. + * @signature typedef SingleType AminoAcid; + * + * The ValueSize of AminoAcid is 27. + * + * The amino acid symbols are as follows, i.e. they are sorted alphabetically + * up until the last two symbols: + * + * 'A' = 0, 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'Y', 'Z', 'X'. '*' + * + * Of these 'B' is a wildcard for (Aspartic Acid, Asparagine), + * 'J' for (Leucine, Isoleucine), 'Z' for (Glutamic Acid, Glutamine) and + * 'X' for "any amino acid". + * + * 'O' refers to the rare Pyrrolysine, 'U' refers to the rare Selenocysteine and '*' to the terminator tRNA. + * + * Objects of type AminoAcid can be converted to char and vice versa. Unknown values are converted to + * 'X'. + * + * @see FiniteOrderedAlphabetConcept#ValueSize + * @see PeptideIterator + * @see Peptide + */ + +struct AminoAcid_ {}; +typedef SimpleType AminoAcid; + +template <> struct ValueSize +{ + typedef uint8_t Type; + static const Type VALUE = 27; +}; + +template <> struct BitsPerValue +{ + typedef uint8_t Type; + static const Type VALUE = 5; +}; + +inline AminoAcid +unknownValueImpl(AminoAcid *) +{ + static const AminoAcid _result = AminoAcid('X'); + return _result; +} + +// ---------------------------------------------------------------------------- +// Specialization Finite +// ---------------------------------------------------------------------------- + +/*! + * @class Finite + * @extends SimpleType + * @headerfile + * + * @brief A finite alphabet of a fixed size. + * + * @signature template + * class SimpleType >; + * + * @tparam TValue The type that is use to store the values. + * @tparam SIZE The ValueSize of the alphabet. + */ + +template +struct Finite; + +template +struct ValueSize > > +{ + typedef unsigned Type; + static const Type VALUE = SIZE; +}; + +template +struct BitsPerValue > > +{ + typedef uint8_t Type; + static const Type VALUE = Log2::VALUE; +}; + +// ============================================================================ +// Assignment / Conversion Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// char +// ---------------------------------------------------------------------------- + +inline void assign(char & c_target, + Dna const & source) +{ + c_target = TranslateTableDna5ToChar_<>::VALUE[source.value]; +} + +inline void assign(char & c_target, + Dna5 const & source) +{ + c_target = TranslateTableDna5ToChar_<>::VALUE[source.value]; +} + +inline void assign(char & c_target, + Rna const & source) +{ + c_target = TranslateTableRna5ToChar_<>::VALUE[source.value]; +} + +inline void assign(char & c_target, + Rna5 const & source) +{ + c_target = TranslateTableRna5ToChar_<>::VALUE[source.value]; +} + +inline void assign(char & c_target, Iupac const & source) +{ + c_target = TranslateTableIupacToChar_<>::VALUE[source.value]; +} + +inline void assign(char & c_target, AminoAcid const & source) +{ + c_target = TranslateTableAAToChar_<>::VALUE[source.value]; +} + +// ---------------------------------------------------------------------------- +// Dna +// ---------------------------------------------------------------------------- + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(Dna & target, uint8_t c_source) +{ + target.value = TranslateTableByteToDna_<>::VALUE[c_source]; +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(Dna & target, char c_source) +{ + target.value = TranslateTableCharToDna_<>::VALUE[(unsigned char) c_source]; +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(Dna & target, Dna5 const & c_source) +{ + target.value = c_source.value & 0x03; +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(Dna & target, Iupac const & source) +{ + target.value = TranslateTableIupacToDna_<>::VALUE[source.value]; +} + +// ---------------------------------------------------------------------------- +// Dna5 +// ---------------------------------------------------------------------------- + +template <> +struct CompareTypeImpl +{ + typedef Dna5 Type; +}; + +inline void assign(Dna5 & target, uint8_t c_source) +{ + target.value = TranslateTableByteToDna5_<>::VALUE[c_source]; +} + +template <> +struct CompareTypeImpl +{ + typedef Dna5 Type; +}; + +inline void assign(Dna5 & target, char c_source) +{ + target.value = TranslateTableCharToDna5_<>::VALUE[(unsigned char) c_source]; +} + +template <> +struct CompareTypeImpl +{ + typedef Dna5 Type; +}; + +inline void assign(Dna5 & target, Iupac const & source) +{ + target.value = TranslateTableIupacToDna5_<>::VALUE[source.value]; +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(Dna5 & target, Dna const & c_source) +{ + target.value = c_source.value; +} + +// ---------------------------------------------------------------------------- +// Rna +// ---------------------------------------------------------------------------- + +template <> +struct CompareTypeImpl +{ + typedef Rna Type; +}; + +inline void assign(Rna & target, uint8_t c_source) +{ + target.value = TranslateTableByteToDna_<>::VALUE[c_source]; +} + +template <> +struct CompareTypeImpl +{ + typedef Rna Type; +}; + +inline void assign(Rna & target, char c_source) +{ + target.value = TranslateTableCharToDna_<>::VALUE[(unsigned char)c_source]; +} + +template <> +struct CompareTypeImpl +{ + typedef Rna Type; +}; + +inline void assign(Rna & target, Rna5 const & c_source) +{ + target.value = c_source.value & 0x03; +} + +// --------------------------------------------------------------------------- +// Rna5 +// --------------------------------------------------------------------------- + +template <> +struct CompareTypeImpl +{ + typedef Rna5 Type; +}; + +inline void assign(Rna5 & target, uint8_t c_source) +{ + target.value = TranslateTableByteToDna5_<>::VALUE[c_source]; +} + +template <> +struct CompareTypeImpl +{ + typedef Rna5 Type; +}; + +inline void assign(Rna5 & target, char c_source) +{ + target.value = TranslateTableCharToDna5_<>::VALUE[(unsigned char)c_source]; +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(Rna5 & target, Rna const & c_source) +{ + target.value = c_source.value; +} + +// --------------------------------------------------------------------------- +// Iupac +// --------------------------------------------------------------------------- + +template <> +struct CompareTypeImpl +{ + typedef Iupac Type; +}; + +inline void assign(Iupac & target, uint8_t c_source) +{ + target.value = TranslateTableByteToIupac_<>::VALUE[c_source]; +} + +template <> +struct CompareTypeImpl +{ + typedef Iupac Type; +}; + +inline void assign(Iupac & target, char c_source) +{ + target.value = TranslateTableCharToIupac_<>::VALUE[(unsigned char) c_source]; +} + +inline void assign(Iupac & target, Dna const & source) +{ + target.value = TranslateTableDna5ToIupac_<>::VALUE[source.value]; +} + +inline void assign(Iupac & target, Dna5 const & source) +{ + target.value = TranslateTableDna5ToIupac_<>::VALUE[source.value]; +} + +// --------------------------------------------------------------------------- +// Amino Acid +// --------------------------------------------------------------------------- + +template <> +struct CompareTypeImpl +{ + typedef AminoAcid Type; +}; + +inline void assign(AminoAcid & target, uint8_t c_source) +{ + target.value = TranslateTableByteToAA_<>::VALUE[c_source]; +} + +template <> +struct CompareTypeImpl +{ + typedef AminoAcid Type; +}; + +inline void assign(AminoAcid & target, char c_source) +{ + target.value = TranslateTableCharToAA_<>::VALUE[(unsigned char) c_source]; +} + +// --------------------------------------------------------------------------- +// DnaQ +// --------------------------------------------------------------------------- + +// template +// struct CompareTypeImpl, SimpleType > +// { +// typedef SimpleType Type; +// }; +// +// template +// struct CompareTypeImpl, SimpleType > +// { +// typedef SimpleType Type; +// }; + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(DnaQ & target, Dna const & source) +{ + target.value = source.value | (SEQAN_DEFAULT_QUALITY << 2); +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(Dna & target, DnaQ const & source) +{ + target.value = source.value & 3; +} + +template <> +struct CompareTypeImpl +{ + typedef Iupac Type; +}; + +inline void assign(DnaQ & target, Iupac const & source) +{ + assign(target, (Dna) source); +} + +template <> +struct CompareTypeImpl +{ + typedef Iupac Type; +}; + +inline void assign(Iupac & target, DnaQ const & source) +{ + assign(target, (Dna) source); +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(DnaQ & target, Dna5 const & source) +{ + assign(target, (Dna) source); +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(DnaQ & target, uint8_t c_source) +{ + assign(target, (Dna) c_source); +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(DnaQ & target, char c_source) +{ + assign(target, (Dna) c_source); +} + +inline void +assign(DnaQ & target, DnaQ const & source) +{ + target.value = source.value; +} + +template +inline void +assign(DnaQ & target, TSource const & source) +{ + target.value = (Dna)source; +} + +inline void +assign(int64_t & c_target, + DnaQ & source) +{ + c_target = Dna(source); +} + +inline void +assign(int64_t & c_target, + DnaQ const & source) +{ + c_target = Dna(source); +} + +// uint64_t + +inline void +assign(uint64_t & c_target, + DnaQ & source) +{ + c_target = Dna(source); +} + +inline void +assign(uint64_t & c_target, + DnaQ const & source) +{ + c_target = Dna(source); +} + +// int + +inline void +assign(int & c_target, + DnaQ & source) +{ + c_target = Dna(source); +} + +inline void +assign(int & c_target, + DnaQ const & source) +{ + c_target = Dna(source); +} + +// unsigned int + +inline void +assign(unsigned int & c_target, + DnaQ & source) +{ + c_target = Dna(source); +} + +inline void +assign(unsigned int & c_target, + DnaQ const & source) +{ + c_target = Dna(source); +} + +// short + +inline void +assign(short & c_target, + DnaQ & source) +{ + c_target = Dna(source); +} + +inline void +assign(short & c_target, + DnaQ const & source) +{ + c_target = Dna(source); +} + +// unsigned short + +inline void +assign(unsigned short & c_target, + DnaQ & source) +{ + c_target = Dna(source); +} + +inline void +assign(unsigned short & c_target, + DnaQ const & source) +{ + c_target = Dna(source); +} + +// char + +inline void +assign(char & c_target, + DnaQ & source) +{ + c_target = Dna(source); +} + +inline void +assign(char & c_target, + DnaQ const & source) +{ + c_target = Dna(source); +} + +// signed char + +inline void +assign(signed char & c_target, + DnaQ & source) +{ + c_target = Dna(source); +} + +inline void +assign(signed char & c_target, + DnaQ const & source) +{ + c_target = Dna(source); +} + +// unsigned char + +inline void +assign(unsigned char & c_target, + DnaQ & source) +{ + c_target = Dna(source); +} + +inline void +assign(unsigned char & c_target, + DnaQ const & source) +{ + c_target = Dna(source); +} + +// --------------------------------------------------------------------------- +// Dna5Q +// --------------------------------------------------------------------------- + +// template +// struct CompareTypeImpl, SimpleType > +// { +// typedef SimpleType Type; +// }; +// +// template +// struct CompareTypeImpl, SimpleType > +// { +// typedef SimpleType Type; +// }; + + +template <> +struct CompareTypeImpl +{ + typedef Dna5 Type; +}; + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(DnaQ & target, Dna5Q const & source) +{ + // We perform the converstion from DNA5 to DNA5 with qualities by a simple + // table lookup. The lookup below is equivalent to the following line: + // + // target.value = (source.value == Dna5QValueN_)? 0: source.value; + + static const unsigned table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 0, 0, 0, 0 + }; + target.value = table[source.value]; +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(Dna5Q & target, DnaQ const & source) +{ + target.value = source.value; +} + + +template <> +struct CompareTypeImpl +{ + typedef Dna5 Type; +}; + +inline void assign(Dna5 & target, Dna5Q const & source) +{ + + // We perform the conversion from DNA5 to DNA5 with qualities by a simple + // table lookup. The lookup below is equivalent to the following line: + // + // target.value = (source.value == Dna5QValueN_)? 4: source.value & 3; + + static const unsigned table[] = { + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, + 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 4, 4, 4, 4 // <-- note the 4 + }; + target.value = table[source.value]; +} + +template <> +struct CompareTypeImpl +{ + typedef Dna5 Type; +}; + +inline void assign(Dna5Q & target, Dna5 const & source) +{ + + // We perform the conversion from DNA5 with qualities to DNA5 by a simple + // table lookup. The lookup below is equivalent to the following line: + // + // target.value = (source.value == 4)? Dna5QValueN_ : source.value | (40 << 2); + + static const unsigned table[] = { + (SEQAN_DEFAULT_QUALITY << 2) + 0, (SEQAN_DEFAULT_QUALITY << 2) + 1, + (SEQAN_DEFAULT_QUALITY << 2) + 2, (SEQAN_DEFAULT_QUALITY << 2) + 3, Dna5QValueN_ + }; + target.value = table[source.value]; +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(Dna5Q & target, Dna const & source) +{ + assign(target, (DnaQ) source); +} + +template <> +struct CompareTypeImpl +{ + typedef Dna Type; +}; + +inline void assign(Dna & target, Dna5Q const & source) +{ + assign(target, (Dna5)source); +} + +template <> +struct CompareTypeImpl +{ + typedef Dna5 Type; +}; + +inline void assign(Dna5 & target, DnaQ const & source) +{ + assign(target, (Dna5Q)source); +} + +template <> +struct CompareTypeImpl +{ + typedef Dna5 Type; +}; + +inline void assign(Dna5Q & target, uint8_t c_source) +{ + assign(target, (Dna5)c_source); +} + +template <> +struct CompareTypeImpl +{ + typedef Dna5 Type; +}; + +inline void assign(Dna5Q & target, char c_source) +{ + assign(target, (Dna5)c_source); +} + +template <> +struct CompareTypeImpl +{ + typedef Iupac Type; +}; + +inline void assign(Dna5Q & target, Iupac const & source) +{ + assign(target, (Dna5)source); +} + +template <> +struct CompareTypeImpl +{ + typedef Iupac Type; +}; + +inline void assign(Iupac & target, Dna5Q const & source) +{ + assign(target, (Dna5)source); +} + +inline void +assign(Dna5Q & target, Dna5Q const & source) +{ + target.value = source.value; +} + +template +inline void +assign(Dna5Q & target, TSource const & source) +{ + assign(target, (Dna5)source); +} + +// int64_t + +inline void +assign(int64_t & c_target, + Dna5Q & source) +{ + c_target = Dna5(source); +} + +inline void +assign(int64_t & c_target, + Dna5Q const & source) +{ + c_target = Dna5(source); +} + +// uint64_t + +inline void +assign(uint64_t & c_target, + Dna5Q & source) +{ + c_target = Dna5(source); +} + +inline void +assign(uint64_t & c_target, + Dna5Q const & source) +{ + c_target = Dna5(source); +} + +// int + +inline void +assign(int & c_target, + Dna5Q & source) +{ + c_target = Dna5(source); +} + +inline void +assign(int & c_target, + Dna5Q const & source) +{ + c_target = Dna5(source); +} + +// unsigned int + +inline void +assign(unsigned int & c_target, + Dna5Q & source) +{ + c_target = Dna5(source); +} + +inline void +assign(unsigned int & c_target, + Dna5Q const & source) +{ + c_target = Dna5(source); +} + + +//short + +inline void +assign(short & c_target, + Dna5Q & source) +{ + c_target = Dna5(source); +} + +inline void +assign(short & c_target, + Dna5Q const & source) +{ + c_target = Dna5(source); +} + +//unsigned short + +inline void +assign(unsigned short & c_target, + Dna5Q & source) +{ + c_target = Dna5(source); +} + +inline void +assign(unsigned short & c_target, + Dna5Q const & source) +{ + c_target = Dna5(source); +} + +// char + +inline void +assign(char & c_target, + Dna5Q & source) +{ + c_target = Dna5(source); +} + +inline void +assign(char & c_target, + Dna5Q const & source) +{ + c_target = Dna5(source); +} + +// signed char + +inline void +assign(signed char & c_target, + Dna5Q & source) +{ + c_target = Dna5(source); +} + +inline void +assign(signed char & c_target, + Dna5Q const & source) +{ + c_target = Dna5(source); +} + +// unsigned char + +inline void +assign(unsigned char & c_target, + Dna5Q & source) +{ + c_target = Dna5(source); +} + +inline void +assign(unsigned char & c_target, + Dna5Q const & source) +{ + c_target = Dna5(source); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_RESIDUE_H_ diff --git a/seqan/basic/alphabet_residue_funcs.h b/seqan/basic/alphabet_residue_funcs.h new file mode 100644 index 0000000..7c11c1d --- /dev/null +++ b/seqan/basic/alphabet_residue_funcs.h @@ -0,0 +1,87 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2013 NVIDIA Corporation +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Enrico Siragusa +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_RESIDUE_FUNCS_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_RESIDUE_FUNCS_H_ + + +namespace seqan { + +// -------------------------------------------------------------------------- +// Dna +// -------------------------------------------------------------------------- + +template +inline unsigned char +_translateCharToDna(unsigned char c) +{ + switch (toUpperValue(c)) + { + case 'C': + return 1; + case 'G': + return 2; + case 'T': + return 3; + default: + return 0; + }; +} + +// -------------------------------------------------------------------------- +// Dna5 +// -------------------------------------------------------------------------- + +template +inline unsigned char +_translateCharToDna5(unsigned char c) +{ + switch (toUpperValue(c)) + { + case 'A': + return 0; + case 'C': + return 1; + case 'G': + return 2; + case 'T': + return 3; + default: + return 4; + }; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_RESIDUE_FUNCS_H_ diff --git a/seqan/basic/alphabet_residue_tabs.h b/seqan/basic/alphabet_residue_tabs.h new file mode 100644 index 0000000..ca2f439 --- /dev/null +++ b/seqan/basic/alphabet_residue_tabs.h @@ -0,0 +1,461 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// ========================================================================== +// Conversion tables for residue SimpleType specializations. +// +// Dna and Dna5 share their tables for conversion to char. So do Rna and +// Rna5. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_RESIDUE_TABS_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_RESIDUE_TABS_H_ + + +namespace seqan { + +// -------------------------------------------------------------------------- +// Dna and Dna5 +// -------------------------------------------------------------------------- + +template +struct TranslateTableDna5ToChar_ +{ + static char const VALUE[5]; +}; + +template +char const TranslateTableDna5ToChar_::VALUE[5] = {'A', 'C', 'G', 'T', 'N'}; + + +template +struct TranslateTableDna5ToIupac_ +{ + static char const VALUE[5]; +}; + +template +char const TranslateTableDna5ToIupac_::VALUE[5] = {0x01, 0x02, 0x04, 0x08, 0x0f}; + +template +struct TranslateTableCharToDna_ +{ + static char const VALUE[256]; +}; + +template +char const TranslateTableCharToDna_::VALUE[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //3 + + 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, //4 +// , A, B, C, D, E, D, G, H, I, J, K, L, M, N, O, + + 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //5 +// P, Q, R, S, T, U, V, W, X, Y, Z, , , , , + + 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, //6 +// , a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, + + 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //7 +// p, q, r, s, t, u, v, w, x, y, z, , , , , + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //11 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //12 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //13 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //14 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //15 +}; + + +template +struct TranslateTableCharToDna5_ +{ + static char const VALUE[256]; +}; + +template +char const TranslateTableCharToDna5_::VALUE[256] = +{ + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //0 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //1 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //2 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //3 + + 4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, //4 +// , A, B, C, D, E, D, G, H, I, J, K, L, M, N, O, + + 4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //5 +// P, Q, R, S, T, U, V, W, X, Y, Z, , , , , + + 4, 0, 4, 1, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, //6 +// , a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, + + 4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //7 +// p, q, r, s, t, u, v, w, x, y, z, , , , , + + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //8 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //9 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //10 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //11 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //12 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //13 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //14 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 //15 +}; + +template +struct TranslateTableByteToDna_ +{ + static char const VALUE[256]; +}; + +template +char const TranslateTableByteToDna_::VALUE[256] = +{ + 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //7 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //11 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //12 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //13 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //14 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //15 +}; + +template +struct TranslateTableByteToDna5_ +{ + static char const VALUE[256]; +}; + +template +char const TranslateTableByteToDna5_::VALUE[256] = +{ + 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //0 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //1 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //2 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //3 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //4 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //5 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //6 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //7 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //8 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //9 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //10 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //11 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //12 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //13 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, //14 + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 //15 +}; + +// -------------------------------------------------------------------------- +// Rna and Rna5 +// -------------------------------------------------------------------------- + +template +struct TranslateTableRna5ToChar_ +{ + static char const VALUE[5]; +}; + +template +char const TranslateTableRna5ToChar_::VALUE[5] = {'A', 'C', 'G', 'U', 'N'}; + +// other tables identical to Dna(5) + +// -------------------------------------------------------------------------- +// Iupac +// -------------------------------------------------------------------------- + +template +struct TranslateTableIupacToChar_ +{ + static char const VALUE[16]; +}; + +template +char const TranslateTableIupacToChar_::VALUE[16] = +{ //TGCA + 'U', //0000=0 = or U + 'A', //0001=1 + 'C', //0010=2 + 'M', //0011=3 AC + 'G', //0100=4 + 'R', //0101=5 AG (purine) + 'S', //0110=6 CG + 'V', //0111=7 non-T + 'T', //1000=8 + 'W', //1001=9 TA + 'Y', //1010=A TC (pyrimidine) + 'H', //1011=B not-G + 'K', //1100=C TG + 'D', //1101=D not-C + 'B', //1110=E non-A + 'N' //1111=F any +}; + +template +struct TranslateTableIupacToDna_ +{ + static char const VALUE[16]; +}; + +template +char const TranslateTableIupacToDna_::VALUE[16] = +{ //TGCA + 3, //0000=0 = or U + 0, //0001=1 + 1, //0010=2 + 0, //0011=3 AC + 2, //0100=4 + 0, //0101=5 AG (purine) + 1, //0110=6 CG + 0, //0111=7 non-T + 3, //1000=8 + 0, //1001=9 TA + 1, //1010=A TC (pyrimidine) + 0, //1011=B not-G + 2, //1100=C TG + 0, //1101=D not-C + 1, //1110=E non-A + 0 //1111=F any +}; + +template +struct TranslateTableIupacToDna5_ +{ + static char const VALUE[16]; +}; + +template +char const TranslateTableIupacToDna5_::VALUE[16] = +{ //TGCA + 3, //0000=0 = or U + 0, //0001=1 + 1, //0010=2 + 4, //0011=3 AC + 2, //0100=4 + 4, //0101=5 AG (purine) + 4, //0110=6 CG + 4, //0111=7 non-T + 3, //1000=8 + 4, //1001=9 TA + 4, //1010=A TC (pyrimidine) + 4, //1011=B not-G + 4, //1100=C TG + 4, //1101=D not-C + 4, //1110=E non-A + 4 //1111=F any +}; + +template +struct TranslateTableCharToIupac_ +{ + static char const VALUE[256]; +}; + +template +char const TranslateTableCharToIupac_::VALUE[256] = +{ + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + // = + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, + // A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, + 15, 1, 14, 2, 13, 15, 15, 4, 11, 15, 15, 12, 15, 3, 15, 15, + // Q, R, S, T, U, V, W, X, Y, Z + 15, 15, 5, 6, 8, 0, 7, 9, 15, 10, 15, 15, 15, 15, 15, 15, + // a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, + 15, 1, 14, 2, 13, 15, 15, 4, 11, 15, 15, 12, 15, 3, 15, 15, + // q, r, s, t, u, v, w, x, y, z + 15, 15, 5, 6, 8, 0, 7, 9, 15, 10, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 +}; + +template +struct TranslateTableByteToIupac_ +{ + static char const VALUE[256]; +}; + +template +char const TranslateTableByteToIupac_::VALUE[256] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, //0 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //1 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //2 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //3 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //4 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //5 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //6 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //7 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //8 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //9 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //10 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //11 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //12 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //13 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, //14 + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 //15 +}; + +// -------------------------------------------------------------------------- +// Amino Acid +// -------------------------------------------------------------------------- + +template +struct TranslateTableAAToChar_ +{ + static char const VALUE[27]; +}; +template +char const TranslateTableAAToChar_::VALUE[27] = +{ + 'A', // Ala Alanine + 'B', // Aspartic Acid, Asparagine + 'C', // Cys Cystine + 'D', // Asp Aspartic Acid + 'E', // Glu Glutamic Acid + 'F', // Phe Phenylalanine + 'G', // Gly Glycine + 'H', // His Histidine + 'I', // Ile Isoleucine + 'J', // Leucine, Isoleucine + 'K', // Lys Lysine + 'L', // Leu Leucine + 'M', // Met Methionine + 'N', // Asn Asparagine + 'O', // Pyl Pyrrolysine + 'P', // Pro Proline + 'Q', // Gln Glutamine + 'R', // Arg Arginine + 'S', // Ser Serine + 'T', // Thr Threonine + 'U', // Selenocystein + 'V', // Val Valine + 'W', // Trp Tryptophan + 'Y', // Tyr Tyrosine + 'Z', // Glutamic Acid, Glutamine + 'X', // Unknown + '*' // Terminator +}; + +template +struct TranslateTableCharToAA_ +{ + static char const VALUE[256]; +}; + +template +char const TranslateTableCharToAA_::VALUE[256] = +{ + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //0 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //1 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 25, 25, //2 +// * + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //3 + 25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //4 +// , A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, + + 15, 16, 17, 18, 19, 20, 21, 22, 25, 23, 24, 25, 25, 25, 25, 25, //5 +// P, Q, R, S, T, U, V, W, X, Y, Z, , , , , , + + 25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //6 +// , a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, + + 15, 16, 17, 18, 19, 20, 21, 22, 25, 23, 24, 25, 25, 25, 25, //7 +// p, q, r, s, t, u, v, w, x, y, z, , , , , , + + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //8 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //9 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //10 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //11 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //12 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //13 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //14 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 //15 +}; + +template +struct TranslateTableByteToAA_ +{ + static char const VALUE[256]; +}; + +template +char const TranslateTableByteToAA_::VALUE[256] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, //0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 25, 25, 25, 25, 25, //1 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //2 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //3 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //4 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //5 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //6 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //7 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //8 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //9 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //10 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //11 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //12 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //13 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, //14 + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 //15 +}; + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_RESIDUE_TABS_H_ diff --git a/seqan/basic/alphabet_simple_type.h b/seqan/basic/alphabet_simple_type.h new file mode 100644 index 0000000..f4955fc --- /dev/null +++ b/seqan/basic/alphabet_simple_type.h @@ -0,0 +1,1092 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// Author: Manuel Holtgrewe +// ========================================================================== +// The SimpleType alphabet type is the base class for all residue types. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_SIMPLE_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_SIMPLE_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Class SimpleType +// ---------------------------------------------------------------------------- + +/*! + * @class SimpleType + * @implements FiniteOrderedAlphabetConcept + * @headerfile + * + * @brief Implementation for "simple" types. + * + * @signature template + * class SimpleType; + * + * @tparam TSpec Specialization tag. + * @tparam TValue Type that stores the values of an instance. TValue must be a simple type. + * + * A "simple type" is a C++ type that can be constructed without constructor, destructed without destructor and copied + * without copy constructor or assignment operator. All basic types (like char, int or + * float) are simple. Pointers, references and arrays of simple types are simple. POD types ("plain old data + * types"), that are - simplified spoken - C++-types that already existed in C, are simple too. + * + * Arrays of simple types can be copied very fast by memory manipulation routines, but the default implementation of + * functions like arrayCopyForward and arrayCopy are not optimized for simple types this way. But for classes derived + * from SimpleType, optimized variants of array manipulation functions are applied. + * + * Note that simple types need not to be derived or specialized from SimpleType, but it could be convenient to + * do so. + * + * @see IsSimple + */ + +/*! + * @var TValue SimpleType::value + * @brief The internal value storage of the SimpleType object. + * + * @important Do not modify this value directly. SimpleType implements conversion operators for all numeric types, so + * you can simply assign and cast the SimpleType to all built-in numeric types. + * + * Stores the value of the SimpleType, is of type TValue. Valid values are from 0 to @link + * FiniteOrderedAlphabetConcept#ValueSize @endlink minus one. + */ + +/*! + * @fn SimpleType::SimpleType + * @brief Constructor of SimpleType type. + * + * @signature SimpleType::SimpleType(); + * @signature SimpleType::SimpleType(other); + * @signature template SimpleType::SimpleType(param); + * + * @param[in] other Other SimpleType to copy construct with. + * @param[in] param Any value of type TParam that can be assigned to the SimpleType object. + * + * The default constructor initializes the SimpleType object with the value 0 and the copy constructor copies + * over the value of the SimpleType. + * + * When constructing with a param that is not a SimpleType then param is assigned to the SimpleType + * object, using @link AssignableConcept#assign assign @endlink. This function can be overloaded differently for each + * type. You can expect the following behaviour for all SimpleType objects, however: + * + *
    + *
  • If param is a builtin integer then this value is directly assigned to the @link SimpleType::value value + * @endlink member of the SimpleType object. Note that this can allow an invalid assignment, e.g., when assigning + * 42 to a @link Dna @endlink object.
  • + *
  • If param is a char then this character value is converted to the appropriate value and written + * to the @link SimpleType::value value @endlink member. For example, assigning 'A' or 'a' to + * a SimpleType object assigns 0 to the @link SimpleType::value value @endlink member.
  • + *
+ * + * @section Example + * + * The following example shows construction of a @link Dna @endlink (specialization of SimpleType) object with from + * char and integer values. + * + * @snippet demos/dox/basic/simple_type_construction.cpp simple type construction and assignment + */ + +#pragma pack(push,1) +template +class SimpleType +{ +public: + // ------------------------------------------------------------------------ + // Members; Have to be defined in class. + // ------------------------------------------------------------------------ + + TValue value; + + // ------------------------------------------------------------------------ + // Constructors; Have to be defined in class. + // ------------------------------------------------------------------------ + + // TODO(holtgrew): Do we want default initialization? + + SimpleType() : value(0) + {} + + + SimpleType(SimpleType const & other) + { + assign(*this, other); + } + + // TODO(holtgrew): Do we want an explicit here? + template + + SimpleType(T const & other) + { + assign(*this, other); + } + + // ------------------------------------------------------------------------ + // Assignment Operator; Have to be defined in class. + // ------------------------------------------------------------------------ + + + SimpleType & operator=(SimpleType const & other) + { + assign(*this, other); + return *this; + } + + template + inline SimpleType & + operator=(T const & other) + { + assign(*this, other); + return *this; + } + + // ------------------------------------------------------------------------ + // Conversion Operators; Have to be defined in class. + // ------------------------------------------------------------------------ + + // Class.SimpleType specifies type conversion operators for all built-in + // integer types since there is no way to extend the build-in types with + // copy and assignment constructors in C++. + // + // This cannot be a template since it would conflict to the template + // constructor. + + + operator int64_t() const + { + int64_t c; + assign(c, *this); + return c; + } + + + operator uint64_t() const + { + uint64_t c; + assign(c, *this); + return c; + } + + + operator int() const + { + int c; + assign(c, *this); + return c; + } + + + operator unsigned int() const + { + unsigned int c; + assign(c, *this); + return c; + } + + + operator short() const + { + short c; + assign(c, *this); + return c; + } + + + operator unsigned short() const + { + unsigned short c; + assign(c, *this); + return c; + } + + + operator char() const + { + char c; + assign(c, *this); + return c; + } + + + operator signed char() const + { + signed char c; + assign(c, *this); + return c; + } + + + operator unsigned char() const + { + unsigned char c; + assign(c, *this); + return c; + } +}; +#pragma pack(pop) + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction IsSimple +// ---------------------------------------------------------------------------- + +template +struct IsSimple > +{ + typedef True Type; +}; + +// ---------------------------------------------------------------------------- +// Concept Convertible +// ---------------------------------------------------------------------------- + +template +struct Is< Convertible, TSource> > : + Is< FundamentalConcept > {}; + +template +struct Is< Convertible > > : + Is< FundamentalConcept > {}; + +// ---------------------------------------------------------------------------- +// Metafunction Value +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Rename? SimpleType is no container! + +template +struct Value > +{ + typedef TValue Type; +}; + +template +struct Value const> +{ + typedef TValue const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction MinValue +// ---------------------------------------------------------------------------- + +template +struct MinValue > +{ + static const SimpleType VALUE; +}; + +template +const SimpleType MinValue >::VALUE = SimpleType(0); + +template +inline SimpleType const & +infimumValueImpl(SimpleType *) +{ + return MinValue >::VALUE; +} + +// ---------------------------------------------------------------------------- +// Metafunction MaxValue +// ---------------------------------------------------------------------------- + +template +struct MaxValue > +{ + static const SimpleType VALUE; +}; + +template +const SimpleType MaxValue >::VALUE = SimpleType(((TValue)ValueSize >::VALUE - 1)); + +template +inline SimpleType const & +supremumValueImpl(SimpleType *) +{ + return MaxValue >::VALUE; +} + +// ---------------------------------------------------------------------------- +// Metafunction Spec +// ---------------------------------------------------------------------------- + +template +struct Spec > +{ + typedef TSpec Type; +}; + +template +struct Spec const> +{ + typedef TSpec Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction CompareType +// ---------------------------------------------------------------------------- + +// TODO(doering): muss geprueft werden, ob diese Metafunktion noch ausgeweitet oder aber versteckt wird. +// TODO(holtgrew): Is this at the right place here? Do we need it for all types? +// TODO(holtgrew): CompareType is not symmetric because of class instantiation conflicts. Evaluate these problems and possibly fix them. +// TODO(holtgrew): Is some of the code below redundant, can we lose some copy and paste here? + +template +struct CompareTypeImpl, TRight> +{ + typedef TRight Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// TODO(holtgrew): Why are functions with Proxies defined here? Better in Proxy header? Or externalize? + +// ---------------------------------------------------------------------------- +// Function convertImpl() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Document + +template +inline typename RemoveConst_::Type +convertImpl(Convert const, + SimpleType const & source_) +{ + typename RemoveConst_::Type target_; + assign(target_, source_); + return target_; +} + +// ---------------------------------------------------------------------------- +// Function operator<<() +// ---------------------------------------------------------------------------- + +template +inline TStream & +operator<<(TStream & stream, + SimpleType const & data) +{ + stream << convert(data); + return stream; +} + +// ---------------------------------------------------------------------------- +// Function operator>>() +// ---------------------------------------------------------------------------- + +template +inline TStream & +operator>>(TStream & stream, + SimpleType & data) +{ + char c; + stream >> c; + assign(data, c); + return stream; +} + +// ---------------------------------------------------------------------------- +// Function assign() +// ---------------------------------------------------------------------------- + +template +inline void +assign(SimpleType & target, + SimpleType & source) +{ + target.value = source.value; +} + +template +inline void +assign(SimpleType & target, + SimpleType const & source) +{ + target.value = source.value; +} + +template +inline void +assign(SimpleType & target, + TSource & source) +{ + target.value = source; +} + +template +inline void +assign(SimpleType & target, + TSource const & source) +{ + target.value = source; +} + +// Assign Proxy to SimpleType +// NOTE(doering): Diese Funktionen wurden noetig wegen eines seltsamen VC++-Verhaltens +// TODO(holtgrew): Still necessary with dropped 2003 support? + +template +inline void +assign(SimpleType & target, + Proxy & source) +{ + target.value = getValue(source); +} + +template +inline void +assign(SimpleType & target, + Proxy const & source) +{ + target.value = getValue(source); +} + +//INTEGRAL TYPES +// NOTE(doering): It is not possible to write a single function here since "assign" must be specialized for the first argument at the first place + +template +inline void +assign(int64_t & c_target, + SimpleType & source) +{ + c_target = source.value; +} + +template +inline void +assign(int64_t & c_target, + SimpleType const & source) +{ + c_target = source.value; +} + +template +inline void +assign(uint64_t & c_target, + SimpleType & source) +{ + c_target = source.value; +} + +template +inline void +assign(uint64_t & c_target, + SimpleType const & source) +{ + c_target = source.value; +} + +template +inline void +assign(int & c_target, + SimpleType & source) +{ + c_target = source.value; +} + +template +inline void +assign(int & c_target, + SimpleType const & source) +{ + c_target = source.value; +} + +template +inline void +assign(unsigned int & c_target, + SimpleType & source) +{ + c_target = source.value; +} + +template +inline void +assign(unsigned int & c_target, + SimpleType const & source) +{ + c_target = source.value; +} + +template +inline void +assign(short & c_target, + SimpleType & source) +{ + c_target = source.value; +} + +template +inline void +assign(short & c_target, + SimpleType const & source) +{ + c_target = source.value; +} + +template +inline void +assign(unsigned short & c_target, + SimpleType & source) +{ + c_target = source.value; +} + +template +inline void +assign(unsigned short & c_target, + SimpleType const & source) +{ + c_target = source.value; +} + +template +inline void +assign(char & c_target, + SimpleType & source) +{ + c_target = source.value; +} + +template +inline void +assign(char & c_target, + SimpleType const & source) +{ + c_target = source.value; +} + +template +inline void +assign(signed char & c_target, + SimpleType & source) +{ + c_target = source.value; +} + +template +inline void +assign(signed char & c_target, + SimpleType const & source) +{ + c_target = source.value; +} + +template +inline void +assign(unsigned char & c_target, + SimpleType & source) +{ + c_target = source.value; +} + +template +inline void +assign(unsigned char & c_target, + SimpleType const & source) +{ + c_target = source.value; +} + +// ---------------------------------------------------------------------------- +// Function operator==() +// ---------------------------------------------------------------------------- + +template +inline bool +operator==(SimpleType const & left_, + TRight const & right_) +{ + typedef SimpleType TLeft; + typedef typename CompareType::Type TCompareType; + return convert(left_) == convert(right_); +} + +template +inline bool +operator==(TLeft const & left_, + SimpleType const & right_) +{ + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) == convert(right_); +} + +template +inline bool +operator==(SimpleType const & left_, + SimpleType const & right_) +{ + typedef SimpleType TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) == convert(right_); +} + +template +inline bool +operator==(SimpleType const & left_, + SimpleType const & right_) +{ + return convert(left_) == convert(right_); +} + +template +inline bool +operator==(Proxy const & left_, + SimpleType const & right_) +{ + typedef Proxy TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) == convert(right_); +} + +template +inline bool +operator==(SimpleType const & left_, + Proxy const & right_) +{ + typedef SimpleType TLeft; + typedef Proxy TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) == convert(right_); +} + +// ---------------------------------------------------------------------------- +// Function operator!=() +// ---------------------------------------------------------------------------- + +template +inline bool +operator!=(SimpleType const & left_, + TRight const & right_) +{ + typedef SimpleType TLeft; + typedef typename CompareType::Type TCompareType; + return convert(left_) != convert(right_); +} + +template +inline bool +operator!=(TLeft const & left_, + SimpleType const & right_) +{ + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) != convert(right_); +} + +template +inline bool +operator!=(SimpleType const & left_, + SimpleType const & right_) +{ + typedef SimpleType TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) != convert(right_); +} + +template +inline bool +operator!=(SimpleType const & left_, + SimpleType const & right_) +{ + return convert(left_) != convert(right_); +} + +template +inline bool +operator!=(Proxy const & left_, + SimpleType const & right_) +{ + typedef Proxy TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) != convert(right_); +} + +template +inline bool +operator!=(SimpleType const & left_, + Proxy const & right_) +{ + typedef SimpleType TLeft; + typedef Proxy TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) != convert(right_); +} + +// ---------------------------------------------------------------------------- +// Function operator<() +// ---------------------------------------------------------------------------- + +template +inline bool +operator<(SimpleType const & left_, + TRight const & right_) +{ + typedef SimpleType TLeft; + typedef typename CompareType::Type TCompareType; + return convert(left_) < convert(right_); +} + +template +inline bool +operator<(TLeft const & left_, + SimpleType const & right_) +{ + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) < convert(right_); +} + +template +inline bool +operator<(SimpleType const & left_, + SimpleType const & right_) +{ + typedef SimpleType TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) < convert(right_); +} + +template +inline bool +operator<(SimpleType const & left_, + SimpleType const & right_) +{ + return convert(left_) < convert(right_); +} + +template +inline bool +operator<(Proxy const & left_, + SimpleType const & right_) +{ + typedef Proxy TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) < convert(right_); +} + +template +inline bool +operator<(SimpleType const & left_, + Proxy const & right_) +{ + typedef SimpleType TLeft; + typedef Proxy TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) < convert(right_); +} + +// ---------------------------------------------------------------------------- +// Function operator<=() +// ---------------------------------------------------------------------------- + +template +inline bool +operator<=(SimpleType const & left_, + TRight const & right_) +{ + typedef SimpleType TLeft; + typedef typename CompareType::Type TCompareType; + return convert(left_) <= convert(right_); +} + +template +inline bool +operator<=(TLeft const & left_, + SimpleType const & right_) +{ + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) <= convert(right_); +} + +template +inline bool +operator<=(SimpleType const & left_, + SimpleType const & right_) +{ + typedef SimpleType TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) <= convert(right_); +} + +template +inline bool +operator<=(SimpleType const & left_, + SimpleType const & right_) +{ + return convert(left_) <= convert(right_); +} + +template +inline bool +operator<=(Proxy const & left_, + SimpleType const & right_) +{ + typedef Proxy TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) <= convert(right_); +} +template +inline bool +operator<=(SimpleType const & left_, + Proxy const & right_) +{ + typedef SimpleType TLeft; + typedef Proxy TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) <= convert(right_); +} + +// ---------------------------------------------------------------------------- +// Function operator>() +// ---------------------------------------------------------------------------- + +template +inline bool +operator>(SimpleType const & left_, + TRight const & right_) +{ + typedef SimpleType TLeft; + typedef typename CompareType::Type TCompareType; + return convert(left_) > convert(right_); +} + +template +inline bool +operator>(TLeft const & left_, + SimpleType const & right_) +{ + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) > convert(right_); +} + +template +inline bool +operator>(SimpleType const & left_, + SimpleType const & right_) +{ + typedef SimpleType TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) > convert(right_); +} + +template +inline bool +operator>(SimpleType const & left_, + SimpleType const & right_) +{ + return convert(left_) > convert(right_); +} + +template +inline bool +operator>(Proxy const & left_, + SimpleType const & right_) +{ + typedef Proxy TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) > convert(right_); +} + +template +inline bool +operator>(SimpleType const & left_, + Proxy const & right_) +{ + typedef SimpleType TLeft; + typedef Proxy TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) > convert(right_); +} + +// ---------------------------------------------------------------------------- +// Function operator>=() +// ---------------------------------------------------------------------------- + +template +inline bool +operator>=(SimpleType const & left_, + TRight const & right_) +{ + typedef SimpleType TLeft; + typedef typename CompareType::Type TCompareType; + return convert(left_) >= convert(right_); +} + +template +inline bool +operator>=(TLeft const & left_, + SimpleType const & right_) +{ + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) >= convert(right_); +} + +template +inline bool +operator>=(SimpleType const & left_, + SimpleType const & right_) +{ + typedef SimpleType TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) >= convert(right_); +} + +template +inline bool +operator>=(SimpleType const & left_, + SimpleType const & right_) +{ + return convert(left_) >= convert(right_); +} + +template +inline bool +operator>=(Proxy const & left_, + SimpleType const & right_) +{ + typedef Proxy TLeft; + typedef SimpleType TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) >= convert(right_); +} +template +inline bool +operator>=(SimpleType const & left_, + Proxy const & right_) +{ + typedef SimpleType TLeft; + typedef Proxy TRight; + typedef typename CompareType::Type TCompareType; + return convert(left_) >= convert(right_); +} + +// ---------------------------------------------------------------------------- +// Function operator++() +// ---------------------------------------------------------------------------- + +template +inline SimpleType & +operator++(SimpleType & me) +{ + ++me.value; + return me; +} + +template +inline SimpleType +operator++(SimpleType & me, int) +{ + SimpleType dummy = me; + ++me.value; + return dummy; +} + +// ---------------------------------------------------------------------------- +// Function operator--() +// ---------------------------------------------------------------------------- + +template +inline SimpleType & +operator--(SimpleType & me) +{ + --me.value; + return me; +} + +template +inline SimpleType +operator--(SimpleType & me, int) +{ + SimpleType dummy = me; + --me.value; + return dummy; +} + +// ---------------------------------------------------------------------------- +// Function operator+() [unary] +// ---------------------------------------------------------------------------- + +template +inline SimpleType +operator+(SimpleType const & v) +{ + return v; +} + +template +inline typename ValueSize >::Type +_internalOrdValue(SimpleType const & c) +{ + return c.value; +} + +template +inline typename ValueSize >::Type +ordValue(SimpleType const & c) +{ + return convert(c); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_SIMPLE_H_ diff --git a/seqan/basic/alphabet_storage.h b/seqan/basic/alphabet_storage.h new file mode 100644 index 0000000..53a5df3 --- /dev/null +++ b/seqan/basic/alphabet_storage.h @@ -0,0 +1,291 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Doering +// Author: Manuel Holtgrewe +// ========================================================================== +// Storage-related alphabet interface part. This means both +// construction type (simple, non-simple) and storage size. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_STORAGE_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_STORAGE_H_ + +#include + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +template +class SimpleType; + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction BitsPerValue +// ---------------------------------------------------------------------------- + +template +struct BitsPerValue +{ + static const unsigned VALUE = sizeof(TValue) * 8; + typedef unsigned Type; +}; + +template +struct BitsPerValue : public BitsPerValue +{}; + +// template +// const unsigned BitsPerValue::VALUE = ; + +// ---------------------------------------------------------------------------- +// Metafunction ValueSize +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Enable default implementation only for integers? Move to adapt builtins? + +template +struct ValueSize +{ + typedef uint64_t Type; + static const Type VALUE = (BitsPerValue::VALUE < 64)? 1ull << (BitsPerValue::VALUE & 63) : 0ull; +}; + +template +struct ValueSize : ValueSize +{}; + +// TODO(holtgrew): Use static assertion to make sure that ValueSize is never called on floating point numbers? Include assertion for int64_t and uint64_t? + +template <> +struct ValueSize +{ + typedef uint64_t Type; + static const Type VALUE = 0; +}; + +template <> +struct ValueSize +{ + typedef uint64_t Type; + static const Type VALUE = 0; +}; + +template <> +struct ValueSize +{ + typedef uint64_t Type; + static const Type VALUE = 0; +}; + +template <> +struct ValueSize +{ + typedef uint64_t Type; + static const Type VALUE = 0; +}; + + +// The internal value size is used for alphabets with piggyback qualities, +// for example Dna5Q. Here, the public value size is 5 but the internal +// value size is 256. + +template +struct InternalValueSize_ + : public ValueSize +{}; + +// ---------------------------------------------------------------------------- +// Metafunction BytesPerValue +// ---------------------------------------------------------------------------- + +/*! + * @mfn BytesPerValue + * @headerfile + * @brief Number of bytes needed to store a value. + * + * @signature BytesPerValue::VALUE + * + * @tparam T The type to query. + * + * @return VALUE The number of bytes to store on T object. + * + * By default, this function returns ceil(BitsPerValue<T>::VALUE). For built-in types, this is the same + * as sizeof(T). + * + * @see FiniteOrderedAlphabetConcept#ValueSize + * @see AlphabetConcept#BitsPerValue + * @see IntegralForValue + */ + +template +struct BytesPerValue +{ + enum { VALUE = (BitsPerValue::VALUE + 7) / 8 }; +}; + +// ---------------------------------------------------------------------------- +// Metafunction IntegralForValue +// ---------------------------------------------------------------------------- + +/*! + * @mfn IntegralForValue + * @headerfile + * @brief Returns an itegral type that provides sufficient space to store a value. + * + * @signature IntegralForValue::Type; + * + * @tparam T The type to query. + * + * @return Type An integral type. + * + * The type is the smallest unsigned integral type that has a size of at least BytesPerValue bytes. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
sizeof(T) in bytesintegral types
1unsigned char
2unsigned short
3unsigned int
4unsigned int
> 4int64_t
+ * + * Note that the returned integral type cannot store T values, if T takes more than 8 bytes, since + * there exists no integral type that provides sufficient space to store types of this size. + * + * @see FiniteOrderedAlphabetConcept#ValueSize + * @see AlphabetConcept#BitsPerValue + * @see BytesPerValue + */ + +template +struct IntegralForValueImpl_ +{ + typedef int64_t Type; +}; + +// TODO(holtgrew): Switch to uint8_t, uint16_t, uint32_t? +template <> +struct IntegralForValueImpl_<1> +{ + typedef unsigned char Type; +}; + +template <> +struct IntegralForValueImpl_<2> +{ + typedef unsigned short Type; +}; + +template <> +struct IntegralForValueImpl_<3> +{ + typedef unsigned int Type; +}; + +template <> +struct IntegralForValueImpl_<4> +{ + typedef unsigned int Type; +}; + +template +struct IntegralForValue : IntegralForValueImpl_::VALUE> +{}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function ordValue() +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Enable only for integers, move to adapt builtins? + +template +inline typename ValueSize::Type +ordValue(TValue const & c) +{ + return convert(static_cast::Type const &>(c)); +} + +// The internal ord value is used for alphabets with piggyback qualities. + +template +inline typename ValueSize::Type +_internalOrdValue(TValue const & c) +{ + return ordValue(c); +} + +// ---------------------------------------------------------------------------- +// Function valueSize() +// ---------------------------------------------------------------------------- + +template +inline typename ValueSize::Type +valueSize() +{ + return +ValueSize::VALUE; +} + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ALPHABET_STORAGE_H_ diff --git a/seqan/basic/array_construct_destruct.h b/seqan/basic/array_construct_destruct.h new file mode 100644 index 0000000..cb83d7a --- /dev/null +++ b/seqan/basic/array_construct_destruct.h @@ -0,0 +1,1272 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Döring +// ========================================================================== +// Functions for destructing and several ways of constructing (e.g. copy, +// move) values or arrays of values. +// ========================================================================== + +// TODO(holtgrew): Order of parameters should be (target1, target2, ..., source1, source2, ...). +// TODO(holtgrew): Can we maybe replace at least part with http://www.cplusplus.com/reference/std/memory/? +// TODO(holtgrew): The metafunction should go into the alphabet submodule, the functions into the sequence/string module. + +#include + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_ARRAY_CONSTRUCT_DESTRUCT_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_ARRAY_CONSTRUCT_DESTRUCT_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction IsSimple +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): This has to go to alphabet sub module, storage section, adaption. + +/*! + * @mfn IsSimple + * @headerfile + * @brief Tests type to be simple. + * + * @signature IsSimple::Type; + * + * @tparam T Type that is tested. + * + * @return Type Either True or False, depending on T being a "POD" type. + * + * A simple type is a type that does not need constructors to be created, a destructor to be destroyed, and copy + * assignment operators or copy constructors to be copied. All POD ("plain old data") types are simple, but some + * non-POD types could be simple too, e.g. some specializations of SimpleType. + * + * @see SimpleType + */ + +template +struct IsSimple_ +{ + typedef False Type; + enum { VALUE = 0 }; +}; + +// ---------------------------------------------------------------------------- +// Metafunction IsSimple +// ---------------------------------------------------------------------------- + +template <> struct IsSimple_ { typedef True Type; }; +template <> struct IsSimple_ { typedef True Type; }; + +template <> struct IsSimple_ { typedef True Type; }; +template <> struct IsSimple_ { typedef True Type; }; +template <> struct IsSimple_ { typedef True Type; }; +template <> struct IsSimple_ { typedef True Type; }; + +template <> struct IsSimple_ { typedef True Type; }; +template <> struct IsSimple_ { typedef True Type; }; +template <> struct IsSimple_ { typedef True Type; }; +template <> struct IsSimple_ { typedef True Type; }; + +template <> struct IsSimple_ { typedef True Type; }; +template <> struct IsSimple_ { typedef True Type; }; +template <> struct IsSimple_ { typedef True Type; }; + +template +struct IsSimple +{ + typedef typename IsSimple_::Type Type; + enum { VALUE = Type::VALUE }; +}; + +// user defined types (re-specializations are allowed here) +template <> struct IsSimple { typedef True Type; }; +template <> struct IsSimple { typedef True Type; }; +template <> struct IsSimple { typedef True Type; }; + +template +struct IsSimple : public IsSimple {}; + +// ---------------------------------------------------------------------------- +// Metafunction Value +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): This should probably to into sequence module along with this header. + +template +struct Value +{ + typedef TValue Type; +}; + +template +struct Value +{ + typedef TValue Type; +}; + +// TODO(holtgrew): Is this still a problem with dropped 2003 support of VC++? + +//The next two metafunctions dont work in VC++ due to a compiler bug. +//(the default implementation in common_type.h is called instead) +//work-around: convert arrays to pointers. +template +struct Value +{ + typedef TValue Type; +}; + +template +struct Value +{ + typedef TValue Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Reference +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): This should probably to into sequence module along with this header. + +template +struct Reference +{ + typedef TValue & Type; +}; + +template +struct Reference +{ + typedef TValue const & Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function value() for pointers. +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): This has to go to iterator module, adaption of pointers to iterators. + +template +inline T & +value(T * me) +{ + return *me; +} + +// ---------------------------------------------------------------------------- +// Function getValue() for pointers. +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): This has to go to iterator module, adaption of pointers to iterators. + +template +inline T & +getValue(T * me) +{ + return value(me); +} + +// TODO(holtgrew): All of the helper structs could be replaced by global functions. + +// TODO(holtgrew): First, the generic versions for iterators are defined. Below are the versions for pointers. + +// ---------------------------------------------------------------------------- +// Function valueConstruct() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn valueConstruct + * @headerfile + * @brief Constructs an object at specified position. + * + * @signature void valueConstruct(iterator [, param [, move_tag]]); + * + * @param[in,out] iterator Pointer or iterator to position where the object should be constructed. + * @param[in] param Parameter that is forwarded to constructor. + * @param[in] moveTag Instance of the move tag. If the tag is specified, it is forwarded to the constructor, + * so the constructed object must support move construction. + * + * The type of the destructed object is the value type of iterator. + */ + +// Helper code for constructing values behind iterators that do not return +// proxies from their value() functions but references. +struct ValueConstructor_ +{ + template + static inline void + construct(TIterator it) + { + typedef typename Value::Type TValue; + typedef typename RemoveConst::Type TNonConstValue; + new( (void*) & value(it) ) TNonConstValue; + } + + template + static inline void + construct(TIterator it, + TParam && param_) + { + typedef typename Value::Type TValue; + typedef typename RemoveConst::Type TNonConstValue; + new( (void*) & value(it) ) TNonConstValue(std::forward(param_)); + } +}; + +// Helper code for constructing values behind iterators that return proxies +// from their value() function. +// +// TODO(holtgrew): These implementations are empty and to be overwritten. Should we have dynamic/static asserstions here? +struct ValueConstructorProxy_ +{ + template + static inline void construct(TIterator) {} + + template + static inline void construct(TIterator, TParam &&) {} +}; + +template +inline void +valueConstruct(TIterator it) +{ + typedef typename IfC< + IsSameType< + typename Value::Type &, + typename Reference::Type + >::VALUE, + // THEN + ValueConstructor_, // true, types are equal + // ELSE + ValueConstructorProxy_ // false, types differ -> value() returns a proxy + >::Type TConstructor; + + TConstructor::construct(it); +} + +template +inline void +valueConstruct(TIterator it, + TParam && param_) +{ + typedef typename IfC< + IsSameType< + typename Value::Type &, + typename Reference::Type + >::VALUE, + // THEN + ValueConstructor_, // true, types are equal + // ELSE + ValueConstructorProxy_ // false, types differ -> value() returns a proxy + >::Type TConstructor; + + TConstructor::construct(it, std::forward(param_)); +} + +// ---------------------------------------------------------------------------- +// Function valueDestruct() using iterators +// ---------------------------------------------------------------------------- + +// Helper code for destructing values behind iterators that do not return +// proxies from their value() function but references. +struct ValueDestructor_ +{ + template + static inline void + _destruct(TValue * p) + { + p->~TValue(); + } + + template + static inline void + destruct(TIterator it) + { + _destruct(&value(it)); + } +}; + +// Helper code for destructing values behind iterators that return proxies +// from their value() function. +// +// TODO(holtgrew): These implementations are empty and to be overwritten. Should we have dynamic/static asserstions here? +struct ValueDestructorProxy_ +{ + template + static inline void destruct(TIterator) {} +}; + +/*! + * @fn valueDestruct + * @headerfile + * @brief Destroys an object at specified position. + * + * @signature void valueDestruct(iterator); + * + * @param[in,out] iterator Pointer or iterator to position where the object should be destructed. + * + * The type of the constructed object is the value type of iterator. + */ + +template +inline void +valueDestruct(TIterator it) +{ + typedef typename IfC< + IsSameType< + typename Value::Type &, + typename Reference::Type + >::VALUE, + // THEN + ValueDestructor_, // true, types are equal + // ELSE + ValueDestructorProxy_ // false, types differ -> value() returns a proxy + >::Type TDestructor; + + TDestructor::destruct(it); +} + +// ---------------------------------------------------------------------------- +// Function arrayConstruct() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayConstruct + * @headerfile + * @brief Construct objects in a given memory buffer. + * + * @signature void arrayConstruct(begin, end[, value]); + * + * @param[in] begin Iterator to the begin of the range that is to be constructed. + * @param[in] end Iterator behind the end of the range. + * @param[in] value Argument that is forwarded to the constructor. An appropriate constructor is required. If + * value is not specified, the default constructor is used. + * + * The type of the constructed Objects is the value type of begin and end. + */ + +// NOTE(holtgrew): Of course, it does not make sense to declare this in a move version! + +template +inline void +_arrayConstructDefault(TIterator1 begin_, + TIterator2 end_) +{ + while (begin_ != end_) + { + valueConstruct(begin_); + ++begin_; + } +} + +template +inline void +arrayConstruct(TIterator1 begin_, + TIterator2 end_) +{ + _arrayConstructDefault(begin_, end_); +} + +template +inline void +_arrayConstructDefault(TIterator1 begin_, + TIterator2 end_, + TParam const & param_) +{ + while (begin_ != end_) + { + valueConstruct(begin_, param_); + ++begin_; + } +} + +template +inline void +arrayConstruct(TIterator1 begin_, + TIterator2 end_, + TParam const & param_) +{ + _arrayConstructDefault(begin_, end_, param_); +} + +// ---------------------------------------------------------------------------- +// Function arrayConstructCopy() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayConstructCopy + * @headerfile + * @brief Copy constructs an array of objects into in a given memory buffer. + * + * @signature void arrayConstructCopy(sourceBegin, sourceEnd, target); + * + * @param[in] sourceBegin Iterator to the first element of the source range. + * @param[in] sourceEnd Iterator behind the last element of the source range. sourceEnd should have the same + * type as sourceBegin. + * @param[in] target Pointer to the memory block the new objects will be constructed in. The type of target + * specifies the type of the constructed objects: If T* is the type of target, then + * the function constructs objects of type T. The memory buffer should be large enough to + * store sourceEnd - sourceBegin objects. An appropriate (copy-) constructor that + * constructs an target objects given a source object is required. + */ + +template +inline void +_arrayConstructCopyDefault(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + while (source_begin != source_end) + { + // NOTE(holtgrew): getValue() is used here since value() could return + // a proxy! + valueConstruct(target_begin, getValue(source_begin)); + ++source_begin; + ++target_begin; + } +} + +template +inline void +arrayConstructCopy(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + _arrayConstructCopyDefault(source_begin, source_end, target_begin); +} + +// ---------------------------------------------------------------------------- +// Function arrayConstructMove() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayConstructMove + * @headerfile + * @brief Move constructs an array of objects into in a given memory buffer. + * + * @signature void arrayConstructMove(sourceBegin, sourceEnd, target); + * + * @param[in] sourceEnd Iterator behind the last element of the source range. sourceEnd should have the same + * type as sourceBegin. + * @param[in] sourceBegin Iterator to the first element of the source range. + * @param[in] target Pointer to the memory block the new objects will be constructed in. The type of target + * specifies the type of the constructed objects: If T* is the type of target, then + * the function constructs objects of type T. The memory buffer should be large enough to + * store sourceEnd - sourceBegin objects. An appropriate move constructor that + * constructs an target objects given a source object is required. + */ + +template +inline void +_arrayConstructMoveDefault(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + while (source_begin < source_end) + { + // NOTE(holtgrew): Using value() here, used to be getValue() but + // cannot move from const reference or proxy. + // valueConstruct(target_begin, value(source_begin), Move()); + // TODO(holtgrew): We need a "has move constructor" metafunction to switch between move/copy constructing before we can use the line here. + valueConstruct(target_begin, std::move(*source_begin)); + ++source_begin; + ++target_begin; + } +} + +template +inline void +arrayConstructMove(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + _arrayConstructMoveDefault(source_begin, source_end, target_begin); +} + +// ---------------------------------------------------------------------------- +// Function arrayDestruct() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayDestruct + * @headerfile + * @brief Destroys an array of objects. + * + * @signature void arrayDestruct(begin, end); + * + * @param[in] begin Iterator to the begin of the range that is to be destructed. + * @param[in] end Iterator behind the end of the range. + * + * This function does not deallocates the memory. + */ + +template +inline void +_arrayDestructDefault(TIterator1 begin_, + TIterator2 end_) +{ + while (begin_ != end_) + { + valueDestruct(begin_); + ++begin_; + } +} + +template +inline void +arrayDestruct(TIterator1 begin_, + TIterator2 end_) +{ + _arrayDestructDefault(begin_, end_); +} + +// ---------------------------------------------------------------------------- +// Function arrayFill() using iterators +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): What is the advantage over arrayConstruct() with prototype? + +/*! + * @fn arrayFill + * @headerfile + * @brief Assigns one object to each element of a range. + * + * @signature void arrayFill(begin, end, value[, parallelTag]); + * + * @param[in] begin Iterator to the begin of the range that is to be filled. + * @param[in] end Iterator behind the end of the range. + * @param[in] value Argument that is assigned to all count objects in array. + * @param[in] parallelTag Tag to enable/disable parallelism. Types: Serial, Parallel + * + * All objects target_begin[0] to target_begin[count-1] are set to value. + */ + +// TODO(holtgrew): Redirects to fill_n. What are the exact semantics here? Do the array elements have to be initialized already? fill_n uses assignment, not copy construction! + +template +inline void +arrayFill(TIterator begin_, + TIterator end_, + TValue const & value) +{ + std::fill_n(begin_, end_ - begin_, value); +} + +template +inline void +arrayFill(TIterator begin_, + TIterator end_, + TValue const & value, + Serial) +{ + arrayFill(begin_, end_, value); +} + +// ---------------------------------------------------------------------------- +// Function arrayCopyForward() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayCopyForward + * @headerfile + * @brief Copies a range of objects into another range of objects starting from the first element. + * + * @signature void arrayCopyForward(sourceBegin, sourceEnd, target); + * + * @param[in] sourceEnd Iterator behind the last element of the source array. sourceEnd must have the same type + * as sourceBegin. + * @param[in] sourceBegin Iterator to the first element of the source array. + * @param[in] target Iterator to the first element of the target array. The target capacity should be at least as + * long as the source range. + * + * Be careful if source and target range overlap, because in this case some source elements could be accidently + * overwritten before they are copied. + * + * If there is no need for the source elements to persist, consider to use arrayMoveForward instead to improve + * performance. + */ + +template +inline void +_arrayCopyForwardDefault(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + std::copy(source_begin, source_end, target_begin); +} + +template +inline void +arrayCopyForward(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + _arrayCopyForwardDefault(source_begin, source_end, target_begin); +} + +// ---------------------------------------------------------------------------- +// Function arrayCopyBackward() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayCopyBackward + * @headerfile + * @brief Copies a range of objects into another range of objects starting from the last element. + * + * @signature void arrayCopyBackward(source_begin, source_end, target); + * + * @param[in] sourceBegin Iterator to the first element of the source array. + * @param[in] sourceEnd Iterator behind the last element of the source array. sourceEnd must have the same type + * as source_begin. + * @param[in] target Iterator to the first element of the target array. The target capacity should be at least as + * long as the source range. + * + * Be careful if source and target range overlap, because in this case some source elements could be accidently + * overwritten before they are moved. + * + * If source and target do not overlap, consider to use the function arrayCopyForward instead that is faster in some + * cases. + * + * If there is no need for the source elements to persist, consider to use arrayMoveBackward instead to improve + * performance. + * + * The semantic of this function's argument target differ from the arguments of std::copy_backward. + */ + +template +inline void +_arrayCopyBackwardDefault(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + std::copy_backward(source_begin, source_end, target_begin + (source_end - source_begin)); +} + +template +inline void +arrayCopyBackward(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + _arrayCopyBackwardDefault(source_begin, source_end, target_begin); +} + +// ---------------------------------------------------------------------------- +// Function arrayCopy() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayCopy + * + * @headerfile + * + * @brief Copies a range of objects into another range of objects. + * + * @signature void arrayCopy(sourceBegin, sourceEnd, target); + * + * @param[in] sourceEnd Iterator behind the last element of the source range. sourceEnd must have the same type + * as sourceBegin. + * @param[in] sourceBegin Iterator to the first element of the source range. + * @param[in] target Iterator to the first element of the target range.The target capacity should be at least as long + * as the source range. + * + * If source and target range do not overlap, consider to use arrayCopyForward instead to improve performance. + * + * If there is no need for the source elements to persist, consider to use arrayMoveForward instead to improve + * performance. + */ + +template +inline void arrayCopy(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + if (target_begin <= source_begin) + arrayCopyForward(source_begin, source_end, target_begin); + else + arrayCopyBackward(source_begin, source_end, target_begin); +} + +// ---------------------------------------------------------------------------- +// Function arrayMoveForward() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayMoveForward + * @headerfile + * @brief Moves a range of objects into another range of objects starting from the first element. + * + * @signature void arrayMoveForward(sourceBegin, sourceEnd, target); + * + * @param[in] sourceEnd Iterator behind the last element of the source array. sourceEnd must have the same type + * as sourceBegin. + * @param[in] sourceBegin Iterator to the first element of the source array. + * @param[in] target Iterator to the first element of the target array. The target capacity should be at least as + * long as the source range. + * + * The function possibly clears (but does not destroy) the source elements. If source elements must persist, consider + * to use arrayCopyForward instead. + * + * Be careful if source and target range overlap, because in this case some source elements could be accidently + * overwritten before they are moved. + */ + +template +inline void +_arrayMoveForwardDefault(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + std::move(source_begin, source_end, target_begin); +} + +template +inline void +arrayMoveForward(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + _arrayMoveForwardDefault(source_begin, source_end, target_begin); +} + +// ---------------------------------------------------------------------------- +// Function arrayMoveBackward() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayMoveBackward + * @headerfile + * @brief Moves a range of objects into another range of objects starting from the last element. + * + * @signature void arrayMoveBackward(sourceBegin, sourceEnd, target); + * + * @param[in] sourceEnd Iterator behind the last element of the source array. sourceEnd must have the same type + * as sourceBegin. + * @param[in] sourceBegin Iterator to the first element of the source array. + * @param[in] target Iterator to the first element of the target array.The target capacity should be at least as long + * as the source range. + * + * The function possibly clears (but does not destroy) the source elements. If source elements must persist, consider + * to use arrayCopyBackward instead. + * + * Be careful if source and target range overlap, because in this case some source elements could be accidently + * overwritten before they are moved. + * + * If source and target do not overlap, consider to use the function arrayMoveForward instead that is faster in some + * cases. + * + * The semantic of this function's argument target differ from the arguments of std::copy_backward. + */ + +template +inline void +_arrayMoveBackwardDefault(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + std::move_backward(source_begin, source_end, target_begin + (source_end - source_begin)); +} + +template +inline void +arrayMoveBackward(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + _arrayMoveBackwardDefault(source_begin, source_end, target_begin); +} + +// ---------------------------------------------------------------------------- +// Function arrayMove using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayMove + * @headerfile + * @brief Moves a range of objects into another range of objects. + * + * @signature void arrayMove(sourceBegin, sourceEnd, target); + * + * @param[in] sourceBegin Iterator to the first element of the source range. + * @param[in] sourceEnd Iterator behind the last element of the source range. sourceEnd must have the same type + * as sourceBegin. + * @param[in] target Iterator to the first element of the target range. The target capacity should be at least as + * long as the source range. + * + * The function possibly clears (but does not destroy) the source elements. If source elements must persist, consider + * to use arrayCopy instead. + * + * If source and target range do not overlap, consider to use arrayMoveForward instead to improve performance. + * + * Don't confuse this function with the standard move function that resembles arrayCopy. + */ + +template +inline void +arrayMove(TSource1 source_begin, + TSource2 source_end, + TTarget target_begin) +{ + if (target_begin <= source_begin) + arrayMoveForward(source_begin, source_end, target_begin); + else + arrayMoveBackward(source_begin, source_end, target_begin); +} + +// ---------------------------------------------------------------------------- +// Function arrayClearSpace() using iterators +// ---------------------------------------------------------------------------- + +/*! + * @fn arrayClearSpace + * @headerfile + * @brief Destroys the begin of an array and keeps the rest. + * + * @signature void arrayClearSpace(arrBegin, arrLength, keepFrom, moveTo); + * + * @param[in] arrBegin Pointer to the first element of the array. + * @param[in] keepFrom Offset of the first object that will be kept. + * @param[in] arrLength Length of the array. + * @param[in] moveTo Offset the first kept object will get at the end of the function. + * + * The objects arr[keep_from] to arr[arr_length-1] are moved to the area beginning at positions + * move_to. All objects in arr[0] to arr[keep_from-1] are destroyed. After this function, the + * first move_to positions of the array are free and dont contain objects. + * + * The array must have at least enough space to store arr_length + move_to - keep_from objects. + * + * The objects from arr[0] to arr[array_length-1] have to be initialized/constructed, arrays beyond + * arr[array_length-1] are assumed not to be constructed. If this assumption is violated, memory might leak. + */ + +// TODO(holtgrew): The feature that the range [0, array_begin) is deleted is used nowhere. Can this be removed to simplify behaviour? + +template +void _arrayClearSpaceDefault(TIterator array_begin, + size_t array_length, + size_t keep_from, + size_t move_to) +{ + if (keep_from == array_length) { + // In the simplest case, we only destruct elements. + arrayDestruct(array_begin, array_begin + array_length); + return; + } + + // Otherwise, we will perform the destruction & movement. + SEQAN_ASSERT_LT(keep_from, array_length); + if (keep_from == move_to) { + // Case 1: No movement, just destroy elements. + arrayDestruct(array_begin, array_begin + move_to); + return; + } else if (keep_from < move_to) { + // Case 2: Move to the right. + if (array_length > move_to) { + // Case 2a: Moving right of array_length, i.e. we can move a part + // of the objects and have to move-construct the rest. + size_t middle = array_length - (move_to - keep_from); + arrayConstructMove(array_begin + middle, array_begin + array_length, array_begin + array_length); + arrayMove(array_begin + keep_from, array_begin + middle, array_begin + move_to); + arrayDestruct(array_begin, array_begin + move_to); + } else { + // Case 2b: We have to move-construct all target objects. + arrayConstructMove(array_begin + keep_from, array_begin + array_length, array_begin + move_to); + arrayDestruct(array_begin, array_begin + array_length); + } + } else { + // Case 3: Move to the left. + arrayMove(array_begin + keep_from, array_begin + array_length, array_begin + move_to); + arrayDestruct(array_begin, array_begin + move_to); + arrayDestruct(array_begin + array_length - (keep_from - move_to), array_begin + array_length); + } +} + +template +void arrayClearSpace(TIterator array_begin, + size_t array_length, + size_t keep_from, + size_t move_to) +{ + _arrayClearSpaceDefault(array_begin, array_length, keep_from, move_to); +} + +// ---------------------------------------------------------------------------- +// Function arrayConstruct() using pointers +// ---------------------------------------------------------------------------- + +template +inline void +_arrayConstructPointer(TIterator, + TIterator, + True) +{ + //nothing to do +} + +template +inline void +_arrayConstructPointer(TIterator begin_, + TIterator end_, + False) +{ + _arrayConstructDefault(begin_, end_); +} + +template +inline void +arrayConstruct(TValue * begin_, + TValue * end_) +{ + _arrayConstructPointer(begin_, end_, typename IsSimple::Type() ); +} + +template +inline void +_arrayConstructPointer(TValue * begin_, + TValue * end_, + TParam const & param_, + True) +{ + arrayFill(begin_, end_, static_cast(param_)); +} + +template +inline void +_arrayConstructPointer(TValue * begin_, + TValue * end_, + TParam const & param_, + False) +{ + _arrayConstructDefault(begin_, end_, param_); +} + +template +inline void +arrayConstruct(TValue * begin_, + TValue * end_, + TParam const & param_) +{ + _arrayConstructPointer(begin_, end_, param_, typename IsSimple::Type()); +} + +// ---------------------------------------------------------------------------- +// Function arrayConstructCopy() using pointers +// ---------------------------------------------------------------------------- + +template +inline void +_arrayConstructCopyPointer(TValueSource * source_begin, + TValueSource * source_end, + TValueTarget * target_begin, + True) +{ + arrayCopyForward(source_begin, source_end, target_begin); +} + +template +inline void +_arrayConstructCopyPointer(TValueSource * source_begin, + TValueSource * source_end, + TValueTarget const* target_begin, + True) +{ + arrayCopyForward(source_begin, source_end, const_cast(target_begin)); +} + +template +inline void +_arrayConstructCopyPointer(TValueSource * source_begin, + TValueSource * source_end, + TValueTarget * target_begin, + False) +{ + _arrayConstructCopyDefault(source_begin, source_end, target_begin); +} +template +inline void +arrayConstructCopy(TValueSource * source_begin, + TValueSource * source_end, + TValueTarget * target_begin) +{ + _arrayConstructCopyPointer(source_begin, source_end, target_begin, typename IsSimple::Type() ); +} + +// ---------------------------------------------------------------------------- +// Function arrayConstructMove() using pointers +// ---------------------------------------------------------------------------- + +template +inline void +_arrayConstructMovePointer(TValue * source_begin, + TValue * source_end, + TValue * target_begin, + True) +{ + arrayMoveForward(source_begin, source_end, target_begin); +} + +template +inline void +_arrayConstructMovePointer(TValue * source_begin, + TValue * source_end, + TValue * target_begin, + False) +{ + _arrayConstructMoveDefault(source_begin, source_end, target_begin); +} + +template +inline void +arrayConstructMove(TValue * source_begin, + TValue * source_end, + TValue * target_begin) +{ + _arrayConstructMovePointer(source_begin, source_end, target_begin, typename IsSimple::Type() ); +} + +// ---------------------------------------------------------------------------- +// Function arrayDestruct() using pointers +// ---------------------------------------------------------------------------- + +template +inline void +_arrayDestructPointer(TValue * /*begin_*/, + TValue * /*end_*/, + True) +{ + //do nothing +} + +template +inline void +_arrayDestructPointer(TValue * begin_, + TValue * end_, + False) +{ + _arrayDestructDefault(begin_, end_); +} + +template +inline void +arrayDestruct(TValue * begin_, + TValue * end_) +{ + _arrayDestructPointer(begin_, end_, typename IsSimple::Type() ); +} + +// ---------------------------------------------------------------------------- +// Function arrayFill() using pointers +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Missing? + +//no specializiation for pointer to simple + +// ---------------------------------------------------------------------------- +// Function arrayCopyBackward() using pointers +// ---------------------------------------------------------------------------- + +template +inline void +_arrayCopyForwardPointer(TValue * source_begin, + TValue * source_end, + TValue * target_begin, + True) +{ + std::memmove(target_begin, source_begin, (source_end - source_begin) * sizeof(TValue)); +} + +template +inline void +_arrayCopyForwardPointer(TValue * source_begin, + TValue * source_end, + TValue * target_begin, + False) +{ + _arrayCopyForwardDefault(source_begin, source_end, target_begin); +} + +template +inline void +arrayCopyForward(TValue * source_begin, + TValue * source_end, + TValue * target_begin) +{ + _arrayCopyForwardPointer(source_begin, source_end, target_begin, typename IsSimple::Type() ); +} + +template +inline void +_arrayCopyBackwardPointer(TValue * source_begin, + TValue * source_end, + TValue * target_begin, + True) +{ + std::memmove(target_begin, source_begin, (source_end - source_begin) * sizeof(TValue)); +} + +template +inline void +_arrayCopyBackwardPointer(TValue * source_begin, + TValue * source_end, + TValue * target_begin, + False) +{ + _arrayCopyBackwardDefault(source_begin, source_end, target_begin); +} + +template +inline void +arrayCopyBackward(TValue * source_begin, + TValue * source_end, + TValue * target_begin) +{ + _arrayCopyBackwardPointer(source_begin, source_end, target_begin, typename IsSimple::Type() ); +} + +// ---------------------------------------------------------------------------- +// Function arrayMoveBackward() using pointers +// ---------------------------------------------------------------------------- + +template +inline void +_arrayMoveForwardPointer(TValue * source_begin, + TValue * source_end, + TValue * target_begin, + True) +{ + std::memmove(target_begin, source_begin, (source_end - source_begin) * sizeof(TValue)); +} + +template +inline void +_arrayMoveForwardPointer(TValue * source_begin, + TValue * source_end, + TValue * target_begin, + False) +{ + _arrayMoveForwardDefault(source_begin, source_end, target_begin); +} + +template +inline void +arrayMoveForward(TValue * source_begin, + TValue * source_end, + TValue * target_begin) +{ + _arrayMoveForwardPointer(source_begin, source_end, target_begin, typename IsSimple::Type() ); +} + +template +inline void +_arrayMoveBackwardPointer(TValue * source_begin, + TValue * source_end, + TValue * target_begin, + True) +{ + std::memmove(target_begin, source_begin, (source_end - source_begin) * sizeof(TValue)); +} +template +inline void +_arrayMoveBackwardPointer(TValue * source_begin, + TValue * source_end, + TValue * target_begin, + False) +{ + _arrayMoveBackwardDefault(source_begin, source_end, target_begin); +} + +template +inline void +arrayMoveBackward(TValue * source_begin, + TValue * source_end, + TValue * target_begin) +{ + _arrayMoveBackwardPointer(source_begin, source_end, target_begin, typename IsSimple::Type() ); +} + +// ---------------------------------------------------------------------------- +// Function arrayClearSpace() using pointers +// ---------------------------------------------------------------------------- + +// clearSpace() on simple type using pointers. +template +inline void +_arrayClearSpacePointer(TValue * array_begin, + size_t array_length, + size_t keep_from, + size_t move_to, + True const & /*isSimple*/) +{ + if (keep_from == move_to) return; + // TODO(holtgrew): arrayCopy is more appropriate here since we are dealing with the IsSimple case. + arrayMove(array_begin + keep_from, array_begin + array_length, array_begin + move_to); +} + +// clearSpace() on non-simple type using pointers. +template +inline void +_arrayClearSpacePointer(TValue * array_begin, + size_t array_length, + size_t keep_from, + size_t move_to, + False const & /*isSimple*/) +{ + _arrayClearSpaceDefault(array_begin, array_length, keep_from, move_to); +} + +template +void arrayClearSpace(TValue * array_begin, + size_t array_length, + size_t keep_from, + size_t move_to) +{ + _arrayClearSpacePointer(array_begin, array_length, keep_from, move_to, typename IsSimple::Type()); +} + + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_ARRAY_CONSTRUCT_DESTRUCT_H_ diff --git a/seqan/basic/basic_aggregate.h b/seqan/basic/basic_aggregate.h new file mode 100644 index 0000000..e0998f7 --- /dev/null +++ b/seqan/basic/basic_aggregate.h @@ -0,0 +1,62 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for basic/aggregate submodule. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_AGGREGATE_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_AGGREGATE_H_ + +// -------------------------------------------------------------------------- +// Prerequisites +// -------------------------------------------------------------------------- + +#include +#include +#include +#include + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_AGGREGATE_H_ diff --git a/seqan/basic/basic_allocator.h b/seqan/basic/basic_allocator.h new file mode 100644 index 0000000..1a3f609 --- /dev/null +++ b/seqan/basic/basic_allocator.h @@ -0,0 +1,64 @@ +// ========================================================================== +// basic_allocator.h +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for basic/allocator submodule. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALLOCATOR_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALLOCATOR_H_ + +// -------------------------------------------------------------------------- +// Dependencies +// -------------------------------------------------------------------------- + +#include +#include +#include + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +// The allocator interface definitions. +#include + +// The allocator specializations. +#include +#include +#include +#include + +// Adaption from SeqAn allocator to STL allocator. +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALLOCATOR_H_ diff --git a/seqan/basic/basic_alphabet.h b/seqan/basic/basic_alphabet.h new file mode 100644 index 0000000..91da52a --- /dev/null +++ b/seqan/basic/basic_alphabet.h @@ -0,0 +1,98 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for the basic/alphabet sub module. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_H_ + +// -------------------------------------------------------------------------- +// Dependencies +// -------------------------------------------------------------------------- + +#include +#include +#include +#include + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +// The first, more generic part of this sub module contains concepts, and the +// necessary metafunction and function prototypes as well as some forward and +// default implementations. + +// The alphabet concepts. +#include + +// Alphabet math functions / metafunctions forwards and default +// implementations. +#include + +// Adaptions for builtin C++ types to the alphabet concepts. +// TODO(holtgrew): Move into second part? +#include + +// Alphabets from Bioinformatics application - gapped unknown values. +#include + +// Alphabet with qualities metafunction and function forwards and default +// implementations +#include + +// Forward declarations and default implementations for storage related +// aspects of alphabets. +#include + +// The second part contains basic alphabets, namely the SimpleType class with +// the specialization for the biological data types, such as Dna, Rna, and +// Amino Acid. Furthermore, it contains a character storing profile entries. + +// The SimpleType class. +#include + +// Conversion tables for the biological SimpleType specializations. +#include + +// Conversion functions for the biological SimpleType specializations. +#include + +// The actual biological SimpleType specializations. +#include + +// The profile character implementation. +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ALPHABET_H_ diff --git a/seqan/basic/basic_concept.h b/seqan/basic/basic_concept.h new file mode 100644 index 0000000..5fb0376 --- /dev/null +++ b/seqan/basic/basic_concept.h @@ -0,0 +1,67 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for sub module basic_concept. +// +// This sub module contains the SeqAn Concept Checking library (ported from +// Boost Concept Checking Library) and fundamental concepts (based both on +// Boost concepts and ConceptC++ concepts). +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_CONCEPT_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_CONCEPT_H_ + +// -------------------------------------------------------------------------- +// Prerequisites +// -------------------------------------------------------------------------- + +#include +#include +#include + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +// Minimal subset of the boost preprocessor library, required for concept +// checknig library port. +#include + +// SeqAn Concept Checking Library (ported from Boost). +#include + +// Fundamental concepts such as Assignable. +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_CONCEPT_H_ diff --git a/seqan/basic/basic_container.h b/seqan/basic/basic_container.h new file mode 100644 index 0000000..d8f8bf0 --- /dev/null +++ b/seqan/basic/basic_container.h @@ -0,0 +1,59 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for the basic_container submodule. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_CONTAINER_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_CONTAINER_H_ + +// -------------------------------------------------------------------------- +// Dependencies +// -------------------------------------------------------------------------- + +#include +#include +#include +#include + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +// PropertyMap concept. +#include + +// Container concept. +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_CONTAINER_H_ diff --git a/seqan/basic/basic_debug.h b/seqan/basic/basic_debug.h new file mode 100644 index 0000000..3b0aefe --- /dev/null +++ b/seqan/basic/basic_debug.h @@ -0,0 +1,60 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// The submodule basic/debug contains supporting codes for debugging, the +// assert macros double for test checks. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_DEBUG_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_DEBUG_H_ + +// -------------------------------------------------------------------------- +// Prerequisites +// -------------------------------------------------------------------------- + +#include + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +// The debug system with assertions. +#include + +// Test and debug helpers. +#include + +// Code for profiling. +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_DEBUG_H_ diff --git a/seqan/basic/basic_device.h b/seqan/basic/basic_device.h new file mode 100644 index 0000000..c20f412 --- /dev/null +++ b/seqan/basic/basic_device.h @@ -0,0 +1,152 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2013 NVIDIA Corporation +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA Corporation nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Enrico Siragusa +// ========================================================================== + +#ifndef SEQAN_BASIC_DEVICE_H +#define SEQAN_BASIC_DEVICE_H + +namespace seqan { + +// ============================================================================ +// Tags +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Execution space tags +// ---------------------------------------------------------------------------- + +struct ExecHost_; +struct ExecDevice_; + +typedef Tag ExecHost; +typedef Tag ExecDevice; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Device +// ---------------------------------------------------------------------------- + +/*! + * @mfn Device + * @headerfile + * @brief Converts a given type into one that lives on a device. + * + * @signature Device::Type; + * @tparam TObject The type to be converted into a device type. + * @return Type The resulting device type. + * + * This metafunction is used to convert host containers into device containers. + * + * @see View + */ + +template +struct Device +{ + typedef TObject Type; +}; + +template +struct Device +{ + typedef typename Device::Type const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction IsDevice +// ---------------------------------------------------------------------------- + +/*! + * @mfn IsDevice + * @headerfile + * @brief Tests if a given type is a device type. + * + * @signature IsDevice::Type; + * @tparam TObject The type to be tested for being a device type. + * @return Type @link LogicalValuesTags#True @endlink or @link LogicalValuesTags#False @endlink. + * + * @see Device + */ + +template +struct IsDevice : public False {}; + +template +struct IsDevice : public IsDevice {}; + +// ---------------------------------------------------------------------------- +// Metafunction IfDevice +// ---------------------------------------------------------------------------- + +template +struct IfDevice +{ + typedef typename If, T1, T2>::Type Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction ExecSpace +// ---------------------------------------------------------------------------- + +template +struct ExecSpace +{ + typedef typename If, ExecDevice, ExecHost>::Type Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction ExecSpec +// ---------------------------------------------------------------------------- + +template +struct ExecSpec +{ + typedef typename IfDevice, TSpec>::Type Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction CtaSize +// ---------------------------------------------------------------------------- + +template +struct CtaSize +{ + static const unsigned VALUE = 256; +}; + +} // namespace seqan + +#endif // #ifndef SEQAN_BASIC_DEVICE_H diff --git a/seqan/basic/basic_exception.h b/seqan/basic/basic_exception.h new file mode 100644 index 0000000..8a5a95a --- /dev/null +++ b/seqan/basic/basic_exception.h @@ -0,0 +1,378 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Enrico Siragusa +// ========================================================================== +// Definition of basic exceptions. +// ========================================================================== + +#ifndef SEQAN_BASIC_BASIC_EXCEPTION_H_ +#define SEQAN_BASIC_BASIC_EXCEPTION_H_ + +// ============================================================================ +// Prerequisites +// ============================================================================ + +#include +#include +#include + +#if !defined(STDLIB_VS) +#include +#endif + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +template +struct Tag; + +//struct Nothing_; +//typedef Tag Nothing; + +// ============================================================================ +// Macros +// ============================================================================ + +/*! + * @defgroup ExceptionHandling SeqAn Exception Handling + * @brief Macros supporting exception handling on various platforms. + */ + +/*! + * @macro ExceptionHandling#SEQAN_EXCEPTIONS + * @headerfile + * @brief Determines whether exceptions are enabled or not. + * + * @signature #define SEQAN_EXCEPTIONS + * + * @see ExceptionHandling#SEQAN_TRY + * @see ExceptionHandling#SEQAN_CATCH + * @see ExceptionHandling#SEQAN_THROW + * @see Exception + */ + +#define SEQAN_EXCEPTIONS __EXCEPTIONS + +/*! + * @macro ExceptionHandling#SEQAN_TRY + * @headerfile + * @brief Replaces the C++ try keyword. + * + * @signature SEQAN_TRY {} SEQAN_CATCH() {} + * + * When exceptions are disabled, i.e. SEQAN_EXCEPTIONS is set to false, the code inside the try block is always executed. + * + * @see ExceptionHandling#SEQAN_CATCH + * @see ExceptionHandling#SEQAN_THROW + * @see Exception + * + * @section Examples + * + * @code{.cpp} + * + * SEQAN_TRY + * { + * SEQAN_THROW(Exception) + * } + * SEQAN_CATCH(Exception const & e) + * { + * std::cerr << e.what() << std::endl; + * } + * + * @endcode + */ + +/*! + * @macro ExceptionHandling#SEQAN_CATCH + * @headerfile + * @brief Replaces the C++ catch keyword. + * + * @signature SEQAN_TRY {} SEQAN_CATCH() {} + * + * When exceptions are disabled, i.e. SEQAN_EXCEPTIONS is set to false, the code inside the catch block is never executed. + * + * @see ExceptionHandling#SEQAN_TRY + * @see ExceptionHandling#SEQAN_THROW + * @see Exception + * + * @section Examples + * + * See @link ExceptionHandling#SEQAN_TRY @endlink for a full example. + */ + +/*! + * @macro ExceptionHandling#SEQAN_THROW + * @headerfile + * @brief Replaces the C++ throw keyword. + * + * @signature SEQAN_THROW(Exception); + * + * When exceptions are disabled, i.e. AssertMacros#SEQAN_EXCEPTIONS is set to false, the macro turns into SEQAN_FAIL. + * + * @see ExceptionHandling#SEQAN_TRY + * @see ExceptionHandling#SEQAN_CATCH + * @see AssertMacros#SEQAN_FAIL + * @see Exception + * + * @section Examples + * + * See @link ExceptionHandling#SEQAN_TRY @endlink for a full example. + */ + +#ifdef SEQAN_EXCEPTIONS + +#define SEQAN_TRY try +#define SEQAN_CATCH(E) catch(E) +#define SEQAN_THROW(E) throw E +#define SEQAN_RETHROW throw + +#else + +#define SEQAN_TRY if (true) +#define SEQAN_CATCH(E) if (false) +//#define SEQAN_CATCH(E) for (E ; false; ) +#define SEQAN_THROW(E) SEQAN_FAIL(#E) +#define SEQAN_RETHROW + +#endif // #ifdef SEQAN_EXCEPTIONS + +// ============================================================================ +// Exceptions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Basic Exception +// ---------------------------------------------------------------------------- + +/*! + * @class Exception + * @headerfile + * @brief Generic SeqAn exception. + * @signature typedef std::exception Exception; + * + * @fn Exception::Exception + * @brief Constructor. + * + * @signature Exception::Exception(msg); + * @param[in] msg The message as a std::string. + */ + +typedef std::exception Exception; + +// ---------------------------------------------------------------------------- +// Exception BadAlloc +// ---------------------------------------------------------------------------- + +/*! + * @class BadAlloc + * @headerfile + * @brief Generic SeqAn exception. + * @signature typedef std::bad_alloc BadAlloc; + * + * @fn BadAlloc::BadAlloc + * @brief Constructor. + * + * @signature BadAlloc::BadAlloc(msg); + * @param[in] msg The message as a std::string. + */ + +typedef std::bad_alloc BadAlloc; + +// ---------------------------------------------------------------------------- +// Exception BadCast +// ---------------------------------------------------------------------------- + +/*! + * @class BadCast + * @headerfile + * @brief Generic SeqAn exception. + * @signature typedef std::bad_cast BadCast; + * + * @fn BadCast::BadCast + * @brief Constructor. + * + * @signature BadCast::BadCast(msg); + * @param[in] msg The message as a std::string. + */ + +typedef std::bad_cast BadCast; + +// ---------------------------------------------------------------------------- +// Exceptions Bad* +// ---------------------------------------------------------------------------- +// NOTE(esiragusa): These exceptions can be introduced as long as we need them. + +//typedef std::bad_exception BadException; +//typedef std::bad_typeid BadTypeId; +//typedef std::bad_function_call BadFunctionCall; +//typedef std::bad_weak_ptr BadWeakPtr; + +// ---------------------------------------------------------------------------- +// Exception RuntimeError +// ---------------------------------------------------------------------------- + +/*! + * @class RuntimeError + * @headerfile + * @brief Runtime error exception. + * @signature typedef std::runtime_error RuntimeError; + * + * + * @fn RuntimeError::RuntimeError + * @brief Constructor. + * + * @signature RuntimeError::RuntimeError(msg); + * @param[in] msg The message as a std::string. + */ + +typedef std::runtime_error RuntimeError; + +// ---------------------------------------------------------------------------- +// Exception LogicError +// ---------------------------------------------------------------------------- +// NOTE(esiragusa): Always prefer SEQAN_ASSERT to logic error exceptions. + +//typedef std::logic_error LogicError; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction ExceptionMessage +// ---------------------------------------------------------------------------- + +template +struct ExceptionMessage +{ + static const std::string VALUE; +}; + +template +const std::string ExceptionMessage::VALUE; + +// ---------------------------------------------------------------------------- +// Function getExceptionMessage() +// ---------------------------------------------------------------------------- + +template +inline std::string const & +getExceptionMessage(TFunctor const &, TContext const &) +{ + return ExceptionMessage::VALUE; +} + +// ============================================================================ +// Functors +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Functor AssertFunctor +// ---------------------------------------------------------------------------- + +template +struct AssertFunctor +{ + TFunctor func; + + AssertFunctor() {} + + AssertFunctor(TFunctor & func) : + func(func) + {} + + std::string escapeChar(unsigned char val) + { + if (val <= '\r') + { + static const char * const escapeCodes[14] = { + "\\0", "\\1", "\\2", "\\3", "\\4", "\\5", "\\6", "\\a", + "\\b", "\\t", "\\n", "\\v", "\\f", "\\r" }; + return std::string(escapeCodes[val]); + } + else if (' ' <= val && val < 128u) + return std::string() + (char)val; + else + { + char buffer[6]; // 5 + 1, e.g. "\0xff" + trailing zero + snprintf(buffer, 6, "\\%#2x", (unsigned)val); + return std::string(buffer); + } + } + + template + bool operator() (TValue const & val) + { + if (SEQAN_UNLIKELY(!func(val))) + throw TException(std::string("Unexpected character '") + escapeChar(val) + "' found. " + + getExceptionMessage(func, TContext())); + return RETURN_VALUE; + } +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function globalExceptionHandler() +// ---------------------------------------------------------------------------- + +#if defined(SEQAN_EXCEPTIONS) && defined(SEQAN_GLOBAL_EXCEPTION_HANDLER) +// Declare global exception handler. +inline static void globalExceptionHandler() +{ + SEQAN_TRY + { + SEQAN_RETHROW; + } + SEQAN_CATCH(Exception & e) + { + SEQAN_FAIL("Uncaught exception of type %s: %s", toCString(Demangler(e)), e.what()); + } + SEQAN_CATCH(...) + { + SEQAN_FAIL("Uncaught exception of unknown type.\n"); + } +} + +// Install global exception handler. +static const std::terminate_handler SEQAN_UNUSED _globalExceptionHandler = std::set_terminate(globalExceptionHandler); + +#endif // #if defined(SEQAN_EXCEPTIONS) && defined(SEQAN_GLOBAL_EXCEPTION_HANDLER) + +} // namespace seqan + +#endif // #ifndef SEQAN_BASIC_BASIC_EXCEPTION_H_ diff --git a/seqan/basic/basic_functors.h b/seqan/basic/basic_functors.h new file mode 100644 index 0000000..6633709 --- /dev/null +++ b/seqan/basic/basic_functors.h @@ -0,0 +1,214 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// Author: Enrico Siragusa +// ========================================================================== + +#ifndef SEQAN_BASIC_FUNCTORS_H_ +#define SEQAN_BASIC_FUNCTORS_H_ + +namespace seqan { + +// ============================================================================ +// Functors +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Functor OrFunctor +// ---------------------------------------------------------------------------- + +template +struct OrFunctor +{ + TFunctor1 func1; + TFunctor2 func2; + + OrFunctor() + {} + + OrFunctor(TFunctor1 const &func1, TFunctor2 const &func2): + func1(func1), func2(func2) + {} + + template + bool operator() (TValue const & val) + { + return func1(val) || func2(val); + } + + template + bool operator() (TValue const & val) const + { + return func1(val) || func2(val); + } +}; + +// ---------------------------------------------------------------------------- +// Functor AndFunctor +// ---------------------------------------------------------------------------- + +template +struct AndFunctor +{ + TFunctor1 func1; + TFunctor2 func2; + + AndFunctor() + {} + + AndFunctor(TFunctor1 const &func1, TFunctor2 const &func2): + func1(func1), func2(func2) + {} + + template + bool operator() (TValue const & val) + { + return func1(val) && func2(val); + } + + template + bool operator() (TValue const & val) const + { + return func1(val) && func2(val); + } +}; + +// ---------------------------------------------------------------------------- +// Functor NotFunctor +// ---------------------------------------------------------------------------- + +template +struct NotFunctor +{ + TFunctor func; + + NotFunctor() + {} + + NotFunctor(TFunctor const &func): + func(func) + {} + + template + bool operator() (TValue const & val) + { + return !func(val); + } + + + template + bool operator() (TValue const & val) const + { + return !func(val); + } +}; + +// ---------------------------------------------------------------------------- +// Functor CountDownFunctor +// ---------------------------------------------------------------------------- + +template +struct CountDownFunctor +{ + uint64_t remaining; + TFunctor func; + + CountDownFunctor(uint64_t remaining = REMAINING): + remaining(remaining) + {} + + CountDownFunctor(uint64_t remaining, TFunctor const &func): + remaining(remaining), + func(func) + {} + + template + bool operator() (TValue const & val) + { + if (remaining == 0) + return true; + if (func(val)) + --remaining; + return false; + } + + operator bool() + { + return remaining == 0; + } +}; + +// ---------------------------------------------------------------------------- +// Functor CountFunctor +// ---------------------------------------------------------------------------- + +template +struct CountFunctor +{ + uint64_t count; + TFunctor func; + + CountFunctor() : count(0) + {} + + CountFunctor(TFunctor const & func) : count(0), func(func) + {} + + template + bool operator() (TValue const & val) + { + if (func(val)) + ++count; + return false; + } + + operator uint64_t() const + { + return count; + } +}; + +template +inline void clear(CountFunctor &func) +{ + func.count = 0; +} + +template +inline uint64_t & value(CountFunctor &func) +{ + return func.count; +} + +} // namespace seqan + +#endif // SEQAN_BASIC_FUNCTORS_H_ diff --git a/seqan/basic/basic_fundamental.h b/seqan/basic/basic_fundamental.h new file mode 100644 index 0000000..b60abdc --- /dev/null +++ b/seqan/basic/basic_fundamental.h @@ -0,0 +1,88 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade hader for the submodule basic_fundamental. +// +// This module contains fundamental code such as forward declarations and +// prototypes for common metafunctions like Value<>, functions assign() etc. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_FUNDAMENTAL_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_FUNDAMENTAL_H_ + +// -------------------------------------------------------------------------- +// Prerequisites +// -------------------------------------------------------------------------- + +#include + +#include +#include + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +// Macros for deprecating code. +#include + +// Pseudo header with documentation for builtin functions. +#include + +// Common metafunctions such as Value<>. +#include + +// Basic tag-related code. +#include + +// Functions and metafunctions to use contiguous chunks of memory +#include + +// Definition of assign(), set(), move(). +#include + +// Code supporting comparison. +#include + +// Conversion support. +#include + +// TODO(holtgrew): This is not fundamental. Should go into sequence module. +// Construct/destruct functions for arrays. +#include + +// TODO(holtgrew): This is not really fundamental, either. Should go into its own sub module. +// Hosted type. +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_HOSTED_TYPE_INTERFACE_H_ diff --git a/seqan/basic/basic_iterator.h b/seqan/basic/basic_iterator.h new file mode 100644 index 0000000..82a1ecc --- /dev/null +++ b/seqan/basic/basic_iterator.h @@ -0,0 +1,92 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for basic_iterator submodule. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ITERATOR_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ITERATOR_H_ + +// -------------------------------------------------------------------------- +// Dependencies +// -------------------------------------------------------------------------- + +#include +#include +#include +#include + +#include // TODO(holtgrew): Temporary dependency + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +// Iterator interface definition. +#include + +// Iter base class. +#include + +// Iterator concept. +#include + +// PropertyMap concept. +#include + +// Container concept. +#include + +// Counting iterator. +#include + +// Positional iterator. +#include + +// Makes a container out of begin/end iterators +#include + +// Iterator for adapting iterators to Rooted Iterators. +#include + +// Adaption between STL iterators and SeqAn iterators. +#include + +// TODO(holtgrew): Does proxy really belong here? +#include +#include + +// Zip iterator. Requires C++11 +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_ITERATOR_H_ diff --git a/seqan/basic/basic_math.h b/seqan/basic/basic_math.h new file mode 100644 index 0000000..a9473b6 --- /dev/null +++ b/seqan/basic/basic_math.h @@ -0,0 +1,58 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for the basic/math sub module. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_MATH_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_MATH_H_ + +// -------------------------------------------------------------------------- +// Dependencies +// -------------------------------------------------------------------------- + +#include +#include + +#include +#include + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +#include +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_MATH_H_ + diff --git a/seqan/basic/basic_metaprogramming.h b/seqan/basic/basic_metaprogramming.h new file mode 100644 index 0000000..d620dcf --- /dev/null +++ b/seqan/basic/basic_metaprogramming.h @@ -0,0 +1,64 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for the basic/metaprogramming submodule. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_METAPROGRAMMING_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_METAPROGRAMMING_H_ + +#include + +#include + +#include + +// Metaprogramming logical operations. +#include + +// Metaprogramming control structures. +#include + +// Metaprogramming mathematics. +#include + +// Metaprogramming for querying and modifying types. +#include + +// Metaprogramming for type algebra. +#include + +// Metaprogramming for conditional enabling/disabling of code. +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_METAPROGRAMMING_H_ diff --git a/seqan/basic/basic_parallelism.h b/seqan/basic/basic_parallelism.h new file mode 100644 index 0000000..b96c43a --- /dev/null +++ b/seqan/basic/basic_parallelism.h @@ -0,0 +1,76 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// This sub module contains simple, generic support code for parallelism in +// SeqAn. +// +// It mainly defines the macro SEQAN_ENABLE_PARALLELISM. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_PARALLELISM_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_PARALLELISM_H_ + +/*! + * @macro SEQAN_ENABLE_PARALLELISM + * @headerfile + * @brief Indicates whether parallelism is enabled with value 0/1. + * + * @signature SEQAN_ENABLE_PARALLELISM + * + * By default, set to 1 if _OPENMP is defined and set to 0 otherwise. + * + * @section Examples + * + * If you want to change tihs value then you have to define this value before include any SeqAn header. + * + * @code{.cpp} + * #define SEQAN_ENABLE_PARALLELISM 0 // ALWAYS switch off parallelism! + * + * #include + * + * int main(int argc, char ** argv) + * { + * return 0; + * } + * @endcode + */ + +#if !defined(SEQAN_ENABLE_PARALLELISM) +#if defined(_OPENMP) +#define SEQAN_ENABLE_PARALLELISM 1 +#else // defined(_OPENMP) +#define SEQAN_ENABLE_PARALLELISM 0 +#endif // defined(_OPENMP) +#endif // !defined(SEQAN_ENABLE_PARALLELISM) + +#endif // SEQAN_INCLUDE_SEQAN_BASIC_BASIC_PARALLELISM_H_ diff --git a/seqan/basic/basic_proxy.h b/seqan/basic/basic_proxy.h new file mode 100644 index 0000000..fe6b711 --- /dev/null +++ b/seqan/basic/basic_proxy.h @@ -0,0 +1,59 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Proxy definition. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_PROXY_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_PROXY_H_ + +// -------------------------------------------------------------------------- +// Dependencies +// -------------------------------------------------------------------------- + +#include +#include +#include + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +// Proxy base class. +#include + +// Implementation of a proxy through an iterator (the latter only needs +// assignValue() and setValue()). +#include + +#endif // SEQAN_INCLUDE_SEQAN_BASIC_BASIC_PROXY_H_ diff --git a/seqan/basic/basic_simd_vector.h b/seqan/basic/basic_simd_vector.h new file mode 100644 index 0000000..40f6e56 --- /dev/null +++ b/seqan/basic/basic_simd_vector.h @@ -0,0 +1,1671 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// René Rahn +// Stefan Budach +// ========================================================================== +// generic SIMD interface for SSE3 / AVX2 +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_SIMD_VECTOR_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_SIMD_VECTOR_H_ + +#include +#include + +// Currently only support the following compilers +#if defined(COMPILER_GCC) || defined(COMPILER_CLANG) || defined(COMPILER_LINTEL) + // Define global macro to check if simd instructions are enabled. + #define SEQAN_SIMD_ENABLED + + // Define maximal size of vector in byte. + #if defined(__AVX2__) + #define SEQAN_SIZEOF_MAX_VECTOR 32 + #elif defined(__SSE4_1__) && defined(__SSE4_2__) + #define SEQAN_SSE4 + #define SEQAN_SIZEOF_MAX_VECTOR 16 + #else // defined(__AVX2__) + #undef SEQAN_SIMD_ENABLED // Disable simd if instruction set is not supported. + #endif // defined(__AVX2__) +#endif // defined(COMPILER_GCC) || defined(COMPILER_CLANG) || defined(COMPILER_LINTEL) + +#ifdef SEQAN_SIMD_ENABLED // Include header with intrinsics. + #include +#endif // SEQAN_SIMD_ENABLED + +namespace seqan { + +#ifdef COMPILER_LINTEL +#include +#define SEQAN_VECTOR_CAST_(T, v) static_cast::type>(v) +#define SEQAN_VECTOR_CAST_LVALUE_(T, v) static_cast(v) +#else +#define SEQAN_VECTOR_CAST_(T, v) reinterpret_cast(v) +#define SEQAN_VECTOR_CAST_LVALUE_(T, v) reinterpret_cast(v) +#endif + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Useful Macros +// ============================================================================ + +#define SEQAN_DEFINE_SIMD_VECTOR_GETVALUE_(TSimdVector) \ +template \ +inline typename Value::Type \ +getValue(TSimdVector &vector, TPosition pos) \ +{ \ +/* \ + typedef typename Value::Type TValue; \ + TValue val = (SEQAN_VECTOR_CAST_(TValue*, &vector))[pos]; \ + return val; \ +*/ \ + return vector[pos]; \ +} + +#define SEQAN_DEFINE_SIMD_VECTOR_VALUE_(TSimdVector) \ +template \ +inline typename Value::Type \ +value(TSimdVector &vector, TPosition pos) \ +{ \ + return getValue(vector, pos); \ +} + +#define SEQAN_DEFINE_SIMD_VECTOR_ASSIGNVALUE_(TSimdVector) \ +template \ +inline void \ +assignValue(TSimdVector &vector, TPosition pos, TValue2 value) \ +{ \ +/* \ + typedef typename Value::Type TValue; \ + (SEQAN_VECTOR_CAST_(TValue*, &vector))[pos] = value; \ +*/ \ + vector[pos] = value; \ +} + +// define a concept and its models +// they allow us to define generic vector functions +SEQAN_CONCEPT(SimdVectorConcept, (T)) {}; + +// Only include following code if simd instructions are enabled. +#ifdef SEQAN_SIMD_ENABLED + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// a metafunction returning the biggest supported SIMD vector +template +struct SimdVector; + +// internal struct to specialize for vector parameters +// VEC_SIZE = Vector size := sizeof(vec) +// LENGTH = number of elements := VEC_SIZE / sizeof(InnerValue::Type) +template +struct SimdParams_ {}; + +template +struct ScaleParam_ +{}; + +// internal struct to specialize for matrix parameters +template +struct SimdMatrixParams_ {}; + +#define SEQAN_DEFINE_SIMD_VECTOR_(TSimdVector, TValue, SIZEOF_VECTOR) \ + typedef TValue TSimdVector __attribute__ ((__vector_size__(SIZEOF_VECTOR))); \ + template <> struct SimdVector { typedef TSimdVector Type; }; \ + template <> struct Value { typedef TValue Type; }; \ + template <> struct Value: public Value {}; \ + template <> struct LENGTH { enum { VALUE = SIZEOF_VECTOR / sizeof(TValue) }; }; \ + template <> struct LENGTH: public LENGTH {}; \ + SEQAN_DEFINE_SIMD_VECTOR_GETVALUE_(TSimdVector) \ + SEQAN_DEFINE_SIMD_VECTOR_GETVALUE_(TSimdVector const) \ + SEQAN_DEFINE_SIMD_VECTOR_VALUE_(TSimdVector) \ + SEQAN_DEFINE_SIMD_VECTOR_VALUE_(TSimdVector const) \ + SEQAN_DEFINE_SIMD_VECTOR_ASSIGNVALUE_(TSimdVector) \ + template <> \ + SEQAN_CONCEPT_IMPL((TSimdVector), (SimdVectorConcept)); \ + template <> \ + SEQAN_CONCEPT_IMPL((TSimdVector const), (SimdVectorConcept)); + +#ifdef __AVX2__ +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector32Char, char, 32) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector32SChar, signed char, 32) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector32UChar, unsigned char, 32) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector16Short, short, 32) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector16UShort, unsigned short, 32) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector8Int, int, 32) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector8UInt, unsigned int, 32) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector4Int64, int64_t, 32) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector4UInt64, uint64_t, 32) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector8Float, float, 32) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector4Double, double, 32) +#endif // __AVX2__ + +#ifdef SEQAN_SSE4 +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector8Char, char, 8) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector8SChar, signed char, 8) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector8UChar, unsigned char, 8) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector4Short, short, 8) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector4UShort, unsigned short, 8) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector2Int, int, 8) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector2UInt, unsigned int, 8) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector2Float, float, 8) + +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector16Char, char, 16) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector16SChar, signed char, 16) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector16UChar, unsigned char, 16) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector8Short, short, 16) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector8UShort, unsigned short, 16) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector4Int, int, 16) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector4UInt, unsigned int, 16) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector2Int64, int64_t, 16) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector2UInt64, uint64_t, 16) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector4Float, float, 16) +SEQAN_DEFINE_SIMD_VECTOR_(SimdVector2Double, double, 16) +#endif // SEQAN_SSE4 + +// ============================================================================ +// Functions +// ============================================================================ + +// ============================================================================ +// AVX/AVX2 wrappers (256bit vectors) +// ============================================================================ + +#ifdef __AVX2__ + +// -------------------------------------------------------------------------- +// _fillVector (256bit) +// -------------------------------------------------------------------------- + +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<32, 32>) { SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_set1_epi8(std::get<0>(x)); } +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<32, 16>) { SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_set1_epi16(std::get<0>(x)); } +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<32, 8>) { SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_set1_epi32(std::get<0>(x)); } +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<32, 4>) { SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_set1_epi64x(std::get<0>(x)); } +template + inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<32, 8>) { SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_set1_ps(std::get<0>(x)); } +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<32, 4>) { SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_set1_pd(std::get<0>(x)); } + +template +inline void _fillVector(TSimdVector &vector, std::tuple const & values, std::index_sequence const &, SimdParams_<32, 32>) +{ + SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_set_epi8(std::get(values)...); +} + +template +inline void _fillVector(TSimdVector &vector, std::tuple const & values, std::index_sequence const &, SimdParams_<32, 16>) +{ + SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_set_epi16(std::get(values)...); +} +template +inline void _fillVector(TSimdVector &vector, std::tuple const & values, std::index_sequence const &, SimdParams_<32, 8>) +{ + SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_set_epi32(std::get(values)...); +} + +template +inline void _fillVector(TSimdVector &vector, std::tuple const & values, std::index_sequence const &, SimdParams_<32, 4>) +{ + SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_set_epi64x(std::get(values)...); +} + +// -------------------------------------------------------------------------- +// _clearVector (256bit) +// -------------------------------------------------------------------------- + +template +inline void _clearVector(TSimdVector &vector, SimdParams_<32, L>) { SEQAN_VECTOR_CAST_LVALUE_(__m256i&, vector) = _mm256_setzero_si256(); } +template +inline void _clearVector(TSimdVector &vector, SimdParams_<32, 8>) { SEQAN_VECTOR_CAST_LVALUE_(__m256&, vector) = _mm256_setzero_ps(); } +template +inline void _clearVector(TSimdVector &vector, SimdParams_<32, 4>) { SEQAN_VECTOR_CAST_LVALUE_(__m256d&, vector) = _mm256_setzero_pd(); } + +// -------------------------------------------------------------------------- +// _createVector (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _createVector(TValue x, SimdParams_<32, 32>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_set1_epi8(x)); } +template +inline TSimdVector _createVector(TValue x, SimdParams_<32, 16>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_set1_epi16(x)); } +template +inline TSimdVector _createVector(TValue x, SimdParams_<32, 8>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_set1_epi32(x)); } +template +inline TSimdVector _createVector(TValue x, SimdParams_< 32, 4>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_set1_epi64x(x)); } +template +inline TSimdVector _createVector(float x, SimdParams_<32, 8>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_set1_ps(x)); } +template +inline TSimdVector _createVector(double x, SimdParams_<32, 4>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_set1_pd(x)); } + +// -------------------------------------------------------------------------- +// _cmpEq (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _cmpEq(TSimdVector &a, TSimdVector &b, SimdParams_<32, 32>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_cmpeq_epi8(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _cmpEq(TSimdVector &a, TSimdVector &b, SimdParams_<32, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_cmpeq_epi16(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _cmpEq(TSimdVector &a, TSimdVector &b, SimdParams_<32, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_cmpeq_epi32(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _cmpEq(TSimdVector &a, TSimdVector &b, SimdParams_<32, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_cmpeq_epi64(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +// -------------------------------------------------------------------------- +// _cmpGt (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _cmpGt(TSimdVector &a, TSimdVector &b, SimdParams_<32, 32>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_cmpgt_epi8(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _cmpGt(TSimdVector &a, TSimdVector &b, SimdParams_<32, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_cmpgt_epi16(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _cmpGt(TSimdVector &a, TSimdVector &b, SimdParams_<32, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_cmpgt_epi32(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _cmpGt(TSimdVector &a, TSimdVector &b, SimdParams_<32, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_cmpgt_epi64(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +// -------------------------------------------------------------------------- +// _bitwiseOr (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _bitwiseOr(TSimdVector &a, TSimdVector &b, SimdParams_<32, L>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_or_si256(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +// -------------------------------------------------------------------------- +// _bitwiseAnd (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _bitwiseAnd(TSimdVector &a, TSimdVector &b, SimdParams_<32, L>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_and_si256(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _bitwiseAnd(TSimdVector &a, TSimdVector &b, SimdParams_<32, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_and_ps(SEQAN_VECTOR_CAST_(const __m256&, a), + SEQAN_VECTOR_CAST_(const __m256&, b))); +} + +template +inline TSimdVector _bitwiseAnd(TSimdVector &a, TSimdVector &b, SimdParams_<32, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_and_pd(SEQAN_VECTOR_CAST_(const __m256d&, a), + SEQAN_VECTOR_CAST_(const __m256d&, b))); +} + +// -------------------------------------------------------------------------- +// _bitwiseAndNot (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _bitwiseAndNot(TSimdVector &a, TSimdVector &b, SimdParams_<32, L>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_andnot_si256(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +// -------------------------------------------------------------------------- +// _bitwiseNot (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _bitwiseNot(TSimdVector &a, SimdParams_<32, 32>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_cmpeq_epi8(SEQAN_VECTOR_CAST_(const __m256i&, a), _mm256_setzero_si256())); +} + +template +inline TSimdVector _bitwiseNot(TSimdVector &a, SimdParams_<32, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_cmpeq_epi16(SEQAN_VECTOR_CAST_(const __m256i&, a), _mm256_setzero_si256())); +} + +template +inline TSimdVector _bitwiseNot(TSimdVector &a, SimdParams_<32, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_cmpeq_epi32(SEQAN_VECTOR_CAST_(const __m256i&, a), _mm256_setzero_si256())); + +} +template +inline TSimdVector _bitwiseNot(TSimdVector &a, SimdParams_<32, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_cmpeq_epi64(SEQAN_VECTOR_CAST_(const __m256i&, a), _mm256_setzero_si256())); +} + +// -------------------------------------------------------------------------- +// _divide (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _divide(TSimdVector &a, int b, SimdParams_<32, 32>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_div_epi8(a, _mm256_set1_epi8(b))); } + +template +inline TSimdVector _divide(TSimdVector &a, int b, SimdParams_<32, 16>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_div_epi16(a, _mm256_set1_epi16(b))); } + +template +inline TSimdVector _divide(TSimdVector &a, int b, SimdParams_<32, 8>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_div_epi32(a, _mm256_set1_epi32(b))); } + +template +inline TSimdVector _divide(TSimdVector &a, int b, SimdParams_<32, 4>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_div_epi64(a, _mm256_set1_epi64x(b))); } + +// -------------------------------------------------------------------------- +// _add (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _add(TSimdVector &a, TSimdVector &b, SimdParams_<32, 32>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_add_epi8(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _add(TSimdVector &a, TSimdVector &b, SimdParams_<32, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_add_epi16(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _add(TSimdVector &a, TSimdVector &b, SimdParams_<32, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_add_epi32(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _add(TSimdVector &a, TSimdVector &b, SimdParams_<32, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_add_epi64(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +// -------------------------------------------------------------------------- +// _sub (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _sub(TSimdVector &a, TSimdVector &b, SimdParams_<32, 32>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_sub_epi8(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _sub(TSimdVector &a, TSimdVector &b, SimdParams_<32, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_sub_epi16(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _sub(TSimdVector &a, TSimdVector &b, SimdParams_<32, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_sub_epi32(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _sub(TSimdVector &a, TSimdVector &b, SimdParams_<32, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_sub_epi64(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +// -------------------------------------------------------------------------- +// _mult (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _mult(TSimdVector &a, TSimdVector &b, SimdParams_<32, 32>) +{ + SEQAN_ASSERT_FAIL("AVX2 intrinsics for multiplying 8 bit values not implemented!"); + return a; +} + +template +inline TSimdVector _mult(TSimdVector &a, TSimdVector &b, SimdParams_<32, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_mullo_epi16(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _mult(TSimdVector &a, TSimdVector &b, SimdParams_<32, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_mullo_epi32(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _mult(TSimdVector &a, TSimdVector &b, SimdParams_<32, 4>) +{ + SEQAN_ASSERT_FAIL("AVX2 intrinsics for multiplying 64 bit values not implemented!"); + return a; +} + +// -------------------------------------------------------------------------- +// _max (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _max(TSimdVector &a, TSimdVector &b, SimdParams_<32, 32>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_max_epi8(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _max(TSimdVector &a, TSimdVector &b, SimdParams_<32, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_max_epi16(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _max(TSimdVector &a, TSimdVector &b, SimdParams_<32, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_max_epi32(SEQAN_VECTOR_CAST_(const __m256i&, a), + SEQAN_VECTOR_CAST_(const __m256i&, b))); +} + +template +inline TSimdVector _max(TSimdVector &a, TSimdVector &b, SimdParams_<32, 4>) +{ + SEQAN_ASSERT_FAIL("AVX2 intrinsics for max on 64 bit values not implemented!"); + return a; +} + +// -------------------------------------------------------------------------- +// _blend (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _blend(TSimdVector const &a, TSimdVector const &b, TSimdVectorMask const &mask, SimdParams_<32, L>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm256_blendv_epi8(SEQAN_VECTOR_CAST_(const __m256i &, a), + SEQAN_VECTOR_CAST_(const __m256i &, b), + SEQAN_VECTOR_CAST_(const __m256i &, mask))); +} + +// -------------------------------------------------------------------------- +// _storeu (256bit) +// -------------------------------------------------------------------------- + +template +inline void _storeu(T * memAddr, TSimdVector &vec, SimdParams_<32, L>) +{ + _mm256_storeu_si256((__m256i*)memAddr, SEQAN_VECTOR_CAST_(const __m256i&, vec)); +} + +// ---------------------------------------------------------------------------- +// Function _load() 256bit +// ---------------------------------------------------------------------------- + +template +inline TSimdVector _load(T const * memAddr, SimdParams_<32, L>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_load_si256((__m256i const *) memAddr)); +} + +// -------------------------------------------------------------------------- +// _shuffleVector (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector1 +_shuffleVector(TSimdVector1 const &vector, TSimdVector2 const &indices, SimdParams_<32, 32>, SimdParams_<32, 32>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector1, _mm256_shuffle_epi8(SEQAN_VECTOR_CAST_(const __m256i &, vector), + SEQAN_VECTOR_CAST_(const __m256i &, indices))); +} +template +inline TSimdVector1 +_shuffleVector(TSimdVector1 const &vector, TSimdVector2 const &indices, SimdParams_<32, 16>, SimdParams_<16, 16>) +{ + // copy 2nd 64bit word to 3rd, compute 2*idx + __m256i idx = _mm256_slli_epi16(_mm256_permute4x64_epi64(_mm256_castsi128_si256(SEQAN_VECTOR_CAST_(const __m128i &, indices)), 0x50), 1); + + // interleave with 2*idx+1 and call shuffle + return SEQAN_VECTOR_CAST_(TSimdVector1, _mm256_shuffle_epi8(SEQAN_VECTOR_CAST_(const __m256i &, vector), + _mm256_unpacklo_epi8(idx, _mm256_add_epi8(idx, _mm256_set1_epi8(1))))); +} + +// -------------------------------------------------------------------------- +// _shiftRightLogical (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _shiftRightLogical(TSimdVector const &vector, const int imm, SimdParams_<32, 32>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_srli_epi16(SEQAN_VECTOR_CAST_(const __m256i &, vector), imm) & _mm256_set1_epi8(0xff >> imm)); +} +template +inline TSimdVector _shiftRightLogical(TSimdVector const &vector, const int imm, SimdParams_<32, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_srli_epi16(SEQAN_VECTOR_CAST_(const __m256i &, vector), imm)); +} +template +inline TSimdVector _shiftRightLogical(TSimdVector const &vector, const int imm, SimdParams_<32, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_srli_epi32(SEQAN_VECTOR_CAST_(const __m256i &, vector), imm)); +} +template +inline TSimdVector _shiftRightLogical(TSimdVector const &vector, const int imm, SimdParams_<32, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_srli_epi64(SEQAN_VECTOR_CAST_(const __m256i &, vector), imm)); +} + +// -------------------------------------------------------------------------- +// _gather (256bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _gather(TValue const * memAddr, + TSimdVector const & idx, + std::integral_constant const & /*scale*/, + SimdParams_<32, 16>) +{ + // 1. Unpack low idx values and interleave with 0 and gather from memAddr. + // 2. Unpack high idx values and interleave with 0, than gather from memAddr. + // 3. Merge 2 8x32 vectors into 1x16 vector by signed saturation. This operation reverts the interleave by the unpack operations above. + return SEQAN_VECTOR_CAST_(TSimdVector, _mm256_packs_epi32(_mm256_i32gather_epi32(static_cast(memAddr), _mm256_unpacklo_epi16(SEQAN_VECTOR_CAST_(__m256i const &, idx), _mm256_set1_epi16(0)), SCALE), + _mm256_i32gather_epi32(static_cast(memAddr), _mm256_unpackhi_epi16(SEQAN_VECTOR_CAST_(__m256i const &, idx), _mm256_set1_epi16(0)), SCALE))); +} + +// -------------------------------------------------------------------------- +// _transposeMatrix (256bit) +// -------------------------------------------------------------------------- + +// emulate missing _mm256_unpacklo_epi128/_mm256_unpackhi_epi128 instructions +inline __m256i _mm256_unpacklo_epi128(__m256i const &a, __m256i const &b) +{ + return _mm256_permute2x128_si256(a, b, 0x20); +// return _mm256_inserti128_si256(a, _mm256_extracti128_si256(b, 0), 1); +} + +inline __m256i _mm256_unpackhi_epi128(__m256i const &a, __m256i const &b) +{ + return _mm256_permute2x128_si256(a, b, 0x31); +// return _mm256_inserti128_si256(b, _mm256_extracti128_si256(a, 1), 0); +} + +template +inline void +_transposeMatrix(TSimdVector matrix[], SimdMatrixParams_<32, 32, 8>) +{ + // we need a look-up table to reverse the lowest 4 bits + // in order to place the permute the transposed rows + static const unsigned char bitRev[] = { 0, 8, 4,12, 2,10, 6,14, 1, 9, 5,13, 3,11, 7,15, + 16,24,20,28,18,26,22,30,17,25,21,29,19,27,23,31}; + + // transpose a 32x32 byte matrix + __m256i tmp1[32]; + for (int i = 0; i < 16; ++i) + { + tmp1[i] = _mm256_unpacklo_epi8(SEQAN_VECTOR_CAST_(const __m256i &, matrix[2*i]), SEQAN_VECTOR_CAST_(const __m256i &, matrix[2*i+1])); + tmp1[i+16] = _mm256_unpackhi_epi8(SEQAN_VECTOR_CAST_(const __m256i &, matrix[2*i]), SEQAN_VECTOR_CAST_(const __m256i &, matrix[2*i+1])); + } + __m256i tmp2[32]; + for (int i = 0; i < 16; ++i) + { + tmp2[i] = _mm256_unpacklo_epi16(tmp1[2*i], tmp1[2*i+1]); + tmp2[i+16] = _mm256_unpackhi_epi16(tmp1[2*i], tmp1[2*i+1]); + } + for (int i = 0; i < 16; ++i) + { + tmp1[i] = _mm256_unpacklo_epi32(tmp2[2*i], tmp2[2*i+1]); + tmp1[i+16] = _mm256_unpackhi_epi32(tmp2[2*i], tmp2[2*i+1]); + } + for (int i = 0; i < 16; ++i) + { + tmp2[i] = _mm256_unpacklo_epi64(tmp1[2*i], tmp1[2*i+1]); + tmp2[i+16] = _mm256_unpackhi_epi64(tmp1[2*i], tmp1[2*i+1]); + } + for (int i = 0; i < 16; ++i) + { + matrix[bitRev[i]] = SEQAN_VECTOR_CAST_(TSimdVector, _mm256_unpacklo_epi128(tmp2[2*i],tmp2[2*i+1])); + matrix[bitRev[i+16]] = SEQAN_VECTOR_CAST_(TSimdVector, _mm256_unpackhi_epi128(tmp2[2*i],tmp2[2*i+1])); + } +} + +// -------------------------------------------------------------------------- +// Function _testAllZeros (256bit) +// -------------------------------------------------------------------------- + +template +SEQAN_FUNC_ENABLE_IF(Is >, int) +inline _testAllZeros(TSimdVector const &vector, TSimdVector const &mask, SimdParams_<32>) +{ + return _mm256_testz_si256(SEQAN_VECTOR_CAST_(const __m256i &, vector), + SEQAN_VECTOR_CAST_(const __m256i &, mask)); +} + +// -------------------------------------------------------------------------- +// Function _testAllOnes (256bit) +// -------------------------------------------------------------------------- + +template +inline int _testAllOnes(TSimdVector const &vector, SimdParams_<32>) +{ + __m256i vec = SEQAN_VECTOR_CAST_(const __m256i &, vector); + return _mm256_testc_si256(vec, _mm256_cmpeq_epi32(vec, vec)); +} + +#endif // #ifdef __AVX2__ + +// ============================================================================ +// SSE3 wrappers (128bit vectors) +// ============================================================================ + +#ifdef SEQAN_SSE4 + +// -------------------------------------------------------------------------- +// _fillVector (128bit) +// -------------------------------------------------------------------------- + +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<16, 16>) { SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_set1_epi8(std::get<0>(x)); } +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<16, 8>) { SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_set1_epi16(std::get<0>(x)); } +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<16, 4>) { SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_set1_epi32(std::get<0>(x)); } +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<16, 2>) { SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_set1_epi64x(std::get<0>(x)); } +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<16, 4>) { SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_set1_ps(std::get<0>(x)); } +template +inline void _fillVector(TSimdVector &vector, std::tuple const & x, std::index_sequence<0> const &, SimdParams_<16, 2>) { SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_set1_pd(std::get<0>(x)); } + +template +inline void _fillVector(TSimdVector &vector, std::tuple const & args, std::index_sequence const &, SimdParams_<16, 16>) +{ + SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_set_epi8(std::get(args)...); +} + +template +inline void _fillVector(TSimdVector &vector, std::tuple const & args, std::index_sequence const &, SimdParams_<16, 8>) +{ + SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_set_epi16(std::get(args)...); +} + +template +inline void _fillVector(TSimdVector &vector, std::tuple const & args, std::index_sequence const &, SimdParams_<16, 4>) +{ + SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_set_epi32(std::get(args)...); +} + +template +inline void _fillVector(TSimdVector &vector, std::tuple const & args, std::index_sequence const &, SimdParams_<16, 2>) +{ + SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_set_epi64x(std::get(args)...); +} + +// -------------------------------------------------------------------------- +// _clearVector (128bit) +// -------------------------------------------------------------------------- + +template +inline void _clearVector(TSimdVector &vector, SimdParams_<16, L>) { SEQAN_VECTOR_CAST_LVALUE_(__m128i&, vector) = _mm_setzero_si128(); } +template +inline void _clearVector(TSimdVector &vector, SimdParams_<16, 4>) { SEQAN_VECTOR_CAST_LVALUE_(__m128&, vector) = _mm_setzero_ps(); } +template +inline void _clearVector(TSimdVector &vector, SimdParams_<16, 2>) { SEQAN_VECTOR_CAST_LVALUE_(__m128d&, vector) = _mm_setzero_pd(); } + +// -------------------------------------------------------------------------- +// _createVector (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _createVector(TValue x, SimdParams_<16, 16>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm_set1_epi8(x)); } +template +inline TSimdVector _createVector(TValue x, SimdParams_<16, 8>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm_set1_epi16(x)); } +template +inline TSimdVector _createVector(TValue x, SimdParams_<16, 4>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm_set1_epi32(x)); } +template +inline TSimdVector _createVector(TValue x, SimdParams_<16, 2>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm_set1_epi64x(x)); } +template +inline TSimdVector _createVector(float x, SimdParams_<16, 4>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm_set1_ps(x)); } +template +inline TSimdVector _createVector(double x, SimdParams_<16, 2>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm_set1_pd(x)); } + +// -------------------------------------------------------------------------- +// cmpEq (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _cmpEq(TSimdVector &a, TSimdVector &b, SimdParams_<16, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpeq_epi8(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _cmpEq(TSimdVector &a, TSimdVector &b, SimdParams_<16, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpeq_epi16(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _cmpEq(TSimdVector &a, TSimdVector &b, SimdParams_<16, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpeq_epi32(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _cmpEq(TSimdVector &a, TSimdVector &b, SimdParams_<16, 2>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpeq_epi64(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +// -------------------------------------------------------------------------- +// _cmpGt (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _cmpGt(TSimdVector &a, TSimdVector &b, SimdParams_<16, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpgt_epi8(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _cmpGt(TSimdVector &a, TSimdVector &b, SimdParams_<16, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpgt_epi16(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _cmpGt(TSimdVector &a, TSimdVector &b, SimdParams_<16, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpgt_epi32(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _cmpGt(TSimdVector &a, TSimdVector &b, SimdParams_<16, 2>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpgt_epi64(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +// -------------------------------------------------------------------------- +// _bitwiseOr (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _bitwiseOr(TSimdVector &a, TSimdVector &b, SimdParams_<16, L>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_or_si128(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +// -------------------------------------------------------------------------- +// _bitwiseAnd (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _bitwiseAnd(TSimdVector &a, TSimdVector &b, SimdParams_<16, L>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_and_si128(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +// -------------------------------------------------------------------------- +// _bitwiseAndNot (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _bitwiseAndNot(TSimdVector &a, TSimdVector &b, SimdParams_<16, L>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_andnot_si128(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +// -------------------------------------------------------------------------- +// _bitwiseNot (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _bitwiseNot(TSimdVector &a, SimdParams_<16, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpeq_epi8(SEQAN_VECTOR_CAST_(const __m128i&, a), + _mm_setzero_si128())); +} + +template +inline TSimdVector _bitwiseNot(TSimdVector &a, SimdParams_<16, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpeq_epi16(SEQAN_VECTOR_CAST_(const __m128i&, a), + _mm_setzero_si128())); +} + +template +inline TSimdVector _bitwiseNot(TSimdVector &a, SimdParams_<16, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpeq_epi32(SEQAN_VECTOR_CAST_(const __m128i&, a), + _mm_setzero_si128())); +} + +template +inline TSimdVector _bitwiseNot(TSimdVector &a, SimdParams_<16, 2>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_cmpeq_epi64(SEQAN_VECTOR_CAST_(const __m128i&, a), + _mm_setzero_si128())); +} + +// -------------------------------------------------------------------------- +// _divide (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _divide(TSimdVector &a, int b, SimdParams_<16, 16>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm_div_epi8(a, _mm_set1_epi8(b))); } + +template +inline TSimdVector _divide(TSimdVector &a, int b, SimdParams_<16, 8>){ return SEQAN_VECTOR_CAST_(TSimdVector, _mm_div_epi16(a, _mm_set1_epi16(b))); } + +template +inline TSimdVector _divide(TSimdVector &a, int b, SimdParams_<16, 4>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm_div_epi32(a, _mm_set1_epi32(b))); } + +template +inline TSimdVector _divide(TSimdVector &a, int b, SimdParams_<16, 2>) { return SEQAN_VECTOR_CAST_(TSimdVector, _mm_div_epi64(a, _mm_set1_epi64x(b))); } + +// -------------------------------------------------------------------------- +// _add (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _add(TSimdVector &a, TSimdVector &b, SimdParams_<16, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_add_epi8(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _add(TSimdVector &a, TSimdVector &b, SimdParams_<16, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_add_epi16(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _add(TSimdVector &a, TSimdVector &b, SimdParams_<16, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_add_epi32(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _add(TSimdVector &a, TSimdVector &b, SimdParams_<16, 2>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_add_epi64(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +// -------------------------------------------------------------------------- +// _sub (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _sub(TSimdVector &a, TSimdVector &b, SimdParams_<16, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_sub_epi8(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _sub(TSimdVector &a, TSimdVector &b, SimdParams_<16, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_sub_epi16(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _sub(TSimdVector &a, TSimdVector &b, SimdParams_<16, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_sub_epi32(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _sub(TSimdVector &a, TSimdVector &b, SimdParams_<16, 2>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_sub_epi64(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +// -------------------------------------------------------------------------- +// _mult (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _mult(TSimdVector &a, TSimdVector &/*b*/, SimdParams_<16, 16>) +{ + SEQAN_ASSERT_FAIL("SSE intrinsics for multiplying 8 bit values not implemented!"); + return a; +} + +template +inline TSimdVector _mult(TSimdVector &a, TSimdVector &b, SimdParams_<16, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_mullo_epi16(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _mult(TSimdVector &a, TSimdVector &b, SimdParams_<16, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_mullo_epi32(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _mult(TSimdVector &a, TSimdVector &/*b*/, SimdParams_<16, 2>) +{ + SEQAN_ASSERT_FAIL("SSE intrinsics for multiplying 64 bit values not implemented!"); + return a; +} + +// -------------------------------------------------------------------------- +// _max (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _max(TSimdVector &a, TSimdVector &b, SimdParams_<16, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_max_epi16(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _max(TSimdVector &a, TSimdVector &b, SimdParams_<16, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_max_epi8(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +template +inline TSimdVector _max(TSimdVector &a, TSimdVector &b, SimdParams_<16, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_max_epi32(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b))); +} + +// -------------------------------------------------------------------------- +// _blend (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _blend(TSimdVector const &a, TSimdVector const &b, TSimdVectorMask const &mask, SimdParams_<16, L>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, + _mm_blendv_epi8(SEQAN_VECTOR_CAST_(const __m128i&, a), + SEQAN_VECTOR_CAST_(const __m128i&, b), + SEQAN_VECTOR_CAST_(const __m128i&, mask))); +} + +// -------------------------------------------------------------------------- +// _storeu (128bit) +// -------------------------------------------------------------------------- + +template +inline void _storeu(T * memAddr, TSimdVector &vec, SimdParams_<16, L>) +{ + _mm_storeu_si128((__m128i*)memAddr, reinterpret_cast(vec)); +} + +// ---------------------------------------------------------------------------- +// Function _load() 128bit +// ---------------------------------------------------------------------------- + +template +inline TSimdVector _load(T const * memAddr, SimdParams_<16, L>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm_load_si128((__m128i const *) memAddr)); +} + +// -------------------------------------------------------------------------- +// _shuffleVector (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector1 +_shuffleVector(TSimdVector1 const &vector, TSimdVector2 const &indices, SimdParams_<16, 16>, SimdParams_<16, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector1, _mm_shuffle_epi8(SEQAN_VECTOR_CAST_(const __m128i &, vector), + SEQAN_VECTOR_CAST_(const __m128i &, indices))); +} + +template +inline TSimdVector1 +_shuffleVector(TSimdVector1 const &vector, TSimdVector2 const &indices, SimdParams_<16, 8>, SimdParams_<8, 8>) +{ +#if SEQAN_IS_32_BIT + __m128i idx = _mm_slli_epi16(_mm_unpacklo_epi32(_mm_cvtsi32_si128(reinterpret_cast(indices)), + _mm_cvtsi32_si128(reinterpret_cast(indices) >> 32)), 1); +#else + __m128i idx = _mm_slli_epi16(_mm_cvtsi64_si128(reinterpret_cast(indices)), 1); +#endif // SEQAN_IS_32_BIT + return SEQAN_VECTOR_CAST_(TSimdVector1, _mm_shuffle_epi8(SEQAN_VECTOR_CAST_(const __m128i &, vector), + _mm_unpacklo_epi8(idx, _mm_add_epi8(idx, _mm_set1_epi8(1))))); +} + +// -------------------------------------------------------------------------- +// _shiftRightLogical (128bit) +// -------------------------------------------------------------------------- + +template +inline TSimdVector _shiftRightLogical(TSimdVector const &vector, const int imm, SimdParams_<16, 16>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm_srli_epi16(SEQAN_VECTOR_CAST_(const __m128i &, vector), imm) & _mm_set1_epi8(0xff >> imm)); +} +template +inline TSimdVector _shiftRightLogical(TSimdVector const &vector, const int imm, SimdParams_<16, 8>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm_srli_epi16(SEQAN_VECTOR_CAST_(const __m128i &, vector), imm)); +} +template +inline TSimdVector _shiftRightLogical(TSimdVector const &vector, const int imm, SimdParams_<16, 4>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm_srli_epi32(SEQAN_VECTOR_CAST_(const __m128i &, vector), imm)); +} +template +inline TSimdVector _shiftRightLogical(TSimdVector const &vector, const int imm, SimdParams_<16, 2>) +{ + return SEQAN_VECTOR_CAST_(TSimdVector, _mm_srli_epi64(SEQAN_VECTOR_CAST_(const __m128i &, vector), imm)); +} + +// -------------------------------------------------------------------------- +// _transposeMatrix (128bit) +// -------------------------------------------------------------------------- + +template +inline void +_transposeMatrix(TSimdVector matrix[], SimdMatrixParams_<8, 8, 8>) +{ + // we need a look-up table to reverse the lowest 4 bits + // in order to place the permute the transposed rows + static const unsigned char bitRev[] = {0,4,2,6,1,5,3,7}; + + // transpose a 8x8 byte matrix + __m64 tmp1[8]; + for (int i = 0; i < 4; ++i) + { + tmp1[i] = _mm_unpacklo_pi8(SEQAN_VECTOR_CAST_(const __m64 &, matrix[2*i]), SEQAN_VECTOR_CAST_(const __m64 &, matrix[2*i+1])); + tmp1[i+4] = _mm_unpackhi_pi8(SEQAN_VECTOR_CAST_(const __m64 &, matrix[2*i]), SEQAN_VECTOR_CAST_(const __m64 &, matrix[2*i+1])); + } + __m64 tmp2[8]; + for (int i = 0; i < 4; ++i) + { + tmp2[i] = _mm_unpacklo_pi16(tmp1[2*i], tmp1[2*i+1]); + tmp2[i+4] = _mm_unpackhi_pi16(tmp1[2*i], tmp1[2*i+1]); + } + for (int i = 0; i < 4; ++i) + { + matrix[bitRev[i]] = SEQAN_VECTOR_CAST_(TSimdVector, _mm_unpacklo_pi32(tmp2[2*i], tmp2[2*i+1])); + matrix[bitRev[i+4]] = SEQAN_VECTOR_CAST_(TSimdVector, _mm_unpackhi_pi32(tmp2[2*i], tmp2[2*i+1])); + } +} + +template +inline void +_transposeMatrix(TSimdVector matrix[], SimdMatrixParams_<16, 16, 8>) +{ + // we need a look-up table to reverse the lowest 4 bits + // in order to place the permute the transposed rows + static const unsigned char bitRev[] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; + + // transpose a 16x16 byte matrix + // + // matrix = + // A0 A1 A2 ... Ae Af + // B0 B1 B2 ... Be Bf + // ... + // P0 P1 P2 ... Pe Pf + __m128i tmp1[16]; + for (int i = 0; i < 8; ++i) + { + tmp1[i] = _mm_unpacklo_epi8(SEQAN_VECTOR_CAST_(const __m128i &, matrix[2*i]), SEQAN_VECTOR_CAST_(const __m128i &, matrix[2*i+1])); + tmp1[i+8] = _mm_unpackhi_epi8(SEQAN_VECTOR_CAST_(const __m128i &, matrix[2*i]), SEQAN_VECTOR_CAST_(const __m128i &, matrix[2*i+1])); + } + // tmp1[0] = A0 B0 A1 B1 ... A7 B7 + // tmp1[1] = C0 D0 C1 D1 ... C7 D7 + // ... + // tmp1[7] = O0 P0 O1 P1 ... O7 P7 + // tmp1[8] = A8 B8 A9 B9 ... Af Bf + // ... + // tmp1[15] = O8 P8 O9 P9 ... Of Pf + __m128i tmp2[16]; + for (int i = 0; i < 8; ++i) + { + tmp2[i] = _mm_unpacklo_epi16(tmp1[2*i], tmp1[2*i+1]); + tmp2[i+8] = _mm_unpackhi_epi16(tmp1[2*i], tmp1[2*i+1]); + } + // tmp2[0] = A0 B0 C0 D0 ... A3 B3 C3 D3 + // tmp2[1] = E0 F0 G0 H0 ... E3 F3 G3 H3 + // ... + // tmp2[3] = M0 N0 O0 P0 ... M3 N3 O3 P3 + // tmp2[4] = A8 B8 C8 D8 ... Ab Bb Cb Db + // ... + // tmp2[7] = M8 N8 O8 P8 ... Mb Nb Ob Pb + // tmp2[8] = A4 B4 C4 D4 ... A7 B7 C7 D7 + // .. + // tmp2[12] = Ac Bc Cc Dc ... Af Bf Cf Df + // ... + // tmp2[15] = Mc Nc Oc Pc ... Mf Nf Of Pf + for (int i = 0; i < 8; ++i) + { + tmp1[i] = _mm_unpacklo_epi32(tmp2[2*i], tmp2[2*i+1]); + tmp1[i+8] = _mm_unpackhi_epi32(tmp2[2*i], tmp2[2*i+1]); + } + // tmp1[0] = A0 B0 .... H0 A1 B1 .... H1 + // tmp1[1] = I0 J0 .... P0 I1 J1 .... P1 + // ... + // tmp1[4] = A0 B0 .... H0 A1 B1 .... H1 + // tmp1[1] = I0 J0 .... P0 I1 J1 .... P1 + for (int i = 0; i < 8; ++i) + { + matrix[bitRev[i]] = SEQAN_VECTOR_CAST_(TSimdVector, _mm_unpacklo_epi64(tmp1[2*i], tmp1[2*i+1])); + matrix[bitRev[i+8]] = SEQAN_VECTOR_CAST_(TSimdVector, _mm_unpackhi_epi64(tmp1[2*i], tmp1[2*i+1])); + } +} + +// -------------------------------------------------------------------------- +// Function _testAllZeros (128bit) +// -------------------------------------------------------------------------- + +template +SEQAN_FUNC_ENABLE_IF(Is >, int) +inline _testAllZeros(TSimdVector const &vector, TSimdVector const &mask, SimdParams_<16>) +{ + return _mm_testz_si128(vector, mask); +} + +// -------------------------------------------------------------------------- +// Function _testAllOnes (128bit) +// -------------------------------------------------------------------------- + +template +inline +SEQAN_FUNC_ENABLE_IF(Is >, int) +_testAllOnes(TSimdVector const &vector, SimdParams_<16>) +{ + return _mm_test_all_ones(SEQAN_VECTOR_CAST_(const __m128i &, vector)); +} +#endif // #ifdef SEQAN_SSE4 + +// ============================================================================ +// +// INTERFACE FUNCTIONS +// - these should be used in the actual code, they will call one of the wrapper +// functions defined above based on the vector type +// +// ============================================================================ + +// -------------------------------------------------------------------------- +// Function transpose() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +transpose(TSimdVector matrix[ROWS]) +{ + typedef typename Value::Type TValue; + _transposeMatrix(matrix, SimdMatrixParams_::VALUE, BitsPerValue::VALUE>()); +} + +// -------------------------------------------------------------------------- +// Function clearVector() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +clearVector(TSimdVector &vector) +{ + typedef typename Value::Type TValue; + _clearVector(vector, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function createVector() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +createVector(TValue x) +{ + typedef typename Value::Type TIVal; + return _createVector(x, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function fillVector() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +fillVector(TSimdVector &vector, TValue const... args) +{ + typedef typename Value::Type TIVal; + _fillVector(vector, std::make_tuple(args...), + std::make_index_sequence{}, + SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function cmpEq() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +cmpEq (TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _cmpEq(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function operator==() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +operator == (TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _cmpEq(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function operatorGt() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +cmpGt (TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _cmpGt(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function operator>() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +operator > (TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _cmpGt(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function max() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +max(TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _max(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function operator|() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +operator | (TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _bitwiseOr(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function operator|=() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector &) +operator |= (TSimdVector &a, TSimdVector const &b) +{ + a = a | b; + return a; +} + +// -------------------------------------------------------------------------- +// Function operator&() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +operator & (TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _bitwiseAnd(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function operator&=() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector &) +operator &= (TSimdVector &a, TSimdVector const &b) +{ + a = a & b; + return a; +} + +// -------------------------------------------------------------------------- +// Function operator~() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +operator ~ (TSimdVector const &a) +{ + typedef typename Value::Type TValue; + return _bitwiseNot(a, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function operator+() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +operator + (TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _add(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function operator-() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +operator - (TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _sub(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function operator*() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +operator * (TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _mult(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function operator/() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +operator/ (TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _div(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function andNot +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +andNot(TSimdVector const &a, TSimdVector const &b) +{ + typedef typename Value::Type TValue; + return _bitwiseAndNot(a, b, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function shuffleVector() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector1) +shuffleVector(TSimdVector1 const &vector, TSimdVector2 const &indices) +{ + typedef typename Value::Type TValue1; + typedef typename Value::Type TValue2; + return _shuffleVector( + vector, + indices, + SimdParams_(), + SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function shiftRightLogical() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +shiftRightLogical(TSimdVector const &vector, const int imm) +{ + typedef typename Value::Type TValue; + return _shiftRightLogical(vector, imm, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function blend() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +blend(TSimdVector const &a, TSimdVector const &b, TSimdVectorMask const & mask) +{ + typedef typename Value::Type TValue; + return _blend(a, b, mask, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function storeu() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +storeu(T * memAddr, TSimdVector const &vec) +{ + typedef typename Value::Type TValue; + _storeu(memAddr, vec, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function load() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +load(T const * memAddr) +{ + typedef typename Value::Type TValue; + return _load(memAddr, SimdParams_()); +} + +// -------------------------------------------------------------------------- +// Function gather() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSimdVector) +gather(TValue const * memAddr, TSimdVector const & idx) +{ + typedef typename Value::Type TInnerValue; + return _gather(memAddr, idx, std::integral_constant(), SimdParams_()); +} + +#endif // SEQAN_SIMD_ENABLED + +// NOTE(rmaerker): Make this function available, also if SIMD is not enabled. +template +inline SEQAN_FUNC_DISABLE_IF(Is >, TSimdVector) +createVector(TValue x) +{ + return x; +} + +// -------------------------------------------------------------------------- +// Function print() +// -------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, std::ostream &) +print(std::ostream &stream, TSimdVector const &vector) +{ + stream << '<'; + for (int i = 0; i < LENGTH::VALUE; ++i) + stream << '\t' << vector[i]; + stream << "\t>\n"; + return stream; +} + +} // namespace seqan + +#endif // SEQAN_INCLUDE_SEQAN_BASIC_SIMD_VECTOR_H_ diff --git a/seqan/basic/basic_smart_pointer.h b/seqan/basic/basic_smart_pointer.h new file mode 100644 index 0000000..deca95f --- /dev/null +++ b/seqan/basic/basic_smart_pointer.h @@ -0,0 +1,59 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Facade header for the basic/smart_pointer sub module. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_SMART_POINTER_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_SMART_POINTER_H_ + +// -------------------------------------------------------------------------- +// Dependencies +// -------------------------------------------------------------------------- + +#include +#include +#include // TODO(holtgrew): Drop dependency, only for pointer holder which does not work anyway. +#include // TODO(holtgrew): Really required? Deprecated header? + +// -------------------------------------------------------------------------- +// Sub Module Headers +// -------------------------------------------------------------------------- + +#include +#include +#include + +#include + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_SMART_POINTER_H_ diff --git a/seqan/basic/basic_stream.h b/seqan/basic/basic_stream.h new file mode 100644 index 0000000..e03dca2 --- /dev/null +++ b/seqan/basic/basic_stream.h @@ -0,0 +1,1303 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// ========================================================================== +// Basic definitions for the stream module. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_STREAM_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BASIC_STREAM_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +template +struct StreamIterator; + +template +inline void writeValue(std::basic_ostream &ostream, TValue2 val); + +template +inline void writeValue(std::ostreambuf_iterator &iter, TValue2 val); + +template +inline void writeValue(Iter > &iter, TValue val); + +template +inline bool atEnd(std::istreambuf_iterator const &it); + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename Size::Type) +length(TContainer const & me); + +template +inline void +appendValue(TContainer && me, TSource && source); + +/*! + * @macro SEQAN_HAS_ZLIB + * @headerfile + * @brief Defined as 0 or 1, depending on zlib being available. + * + * @signature #define SEQAN_HAS_ZLIB 0 // or 1 + */ + +/*! + * @macro SEQAN_HAS_BZIP2 + * @headerfile + * @brief Defined as 0 or 1, depending on bzlib being available. + * + * @signature #define SEQAN_HAS_BZIP 0 // or 1 + */ + +// ============================================================================ +// Tags +// ============================================================================ + +// ============================================================================ +// Concepts +// ============================================================================ + +// -------------------------------------------------------------------------- +// Concept StreamConcept +// -------------------------------------------------------------------------- + +/*! + * @concept StreamConcept + * @headerfile + * + * @brief Base concept for streams. + * + * @signature concept StreamConcept; + */ + +/*! + * @mfn StreamConcept#Value + * @brief Metafunction for retrieving the value type of a stream. + * + * @signature Value::Type; + * + * @tparam TStream The stream type to query for its value type. + * @return Type The resulting value type. + */ + +/*! + * @mfn StreamConcept#Size + * @brief Metafunction for retrieving the type of a stream. + * + * @signature Size::Type; + * + * @tparam TStream The stream type to query for its size type. + * @return Type The resulting size type. + */ + +/*! + * @mfn StreamConcept#Position + * @brief Metafunction for retrieving the position type of a stream. + * + * @signature Position::Type; + * + * @tparam TStream The stream type to query for its position type. + * @return Type The resulting position type. + */ + +/*! + * @fn StreamConcept#position + * @brief Return current stream position. + * + * @signature TPosition position(stream); + * + * @param[in] stream The stream to query. + * @return TPosition Current position in stream, see @link StreamConcept#Position Position @endlink. + */ + +/*! + * @fn StreamConcept#setPosition + * @brief Set stream position. + * + * @signature void setPosition(stream, pos); + * + * @param[in,out] stream The stream to update + * @param[in] pos The positoin to set. + */ + +/*! + * @fn StreamConcept#atEnd + * @brief Return whether stream is at the end. + * + * @signature bool atEnd(stream); + * + * @param[in] stream The stream to check. + * @return bool true if the file at EOF, false otherwise. + */ + +SEQAN_CONCEPT(StreamConcept, (TStream)) +{}; + +// -------------------------------------------------------------------------- +// Concept InputStreamConcept +// -------------------------------------------------------------------------- + +/*! + * @concept InputStreamConcept Input StreamConcept + * @extends StreamConcept + * @headerfile + * + * @signature concept InputStreamConcept : StreamConcept; + * + * @brief Concept for input streams (for reading). + */ + +SEQAN_CONCEPT_REFINE(InputStreamConcept, (TStream), (StreamConcept)) +{ + typedef typename Value::Type TValue; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + + SEQAN_CONCEPT_ASSERT((SignedIntegerConcept)); + + SEQAN_CONCEPT_USAGE(InputStreamConcept) + {} +}; + +// -------------------------------------------------------------------------- +// Concept OutputStreamConcept +// -------------------------------------------------------------------------- + +/*! + * @concept OutputStreamConcept Output StreamConcept + * @extends StreamConcept + * @headerfile + * + * @signature concept OutputStreamConcept : StreamConcept; + * + * @brief Concept for output streams (for writing). + */ + +SEQAN_CONCEPT_REFINE(OutputStreamConcept, (TStream), (StreamConcept)) +{ + typedef typename Value::Type TValue; + typedef typename Size::Type TSize; + typedef typename Position::Type TPosition; + + SEQAN_CONCEPT_ASSERT((SignedIntegerConcept)); + + SEQAN_CONCEPT_USAGE(OutputStreamConcept) + {} +}; + +// -------------------------------------------------------------------------- +// Concept BidirectionalStreamConcept +// -------------------------------------------------------------------------- + +/*! + * @concept BidirectionalStreamConcept Bidirectional StreamConcept + * @extends StreamConcept + * @headerfile + * + * @signature concept BidirectionalStreamConcept : StreamConcept; + * + * @brief Concept for bidirectional streams (both for reading and writing). + */ + +SEQAN_CONCEPT_REFINE(BidirectionalStreamConcept, (TStream), (InputStreamConcept)(OutputStreamConcept)) +{}; + +// ============================================================================ +// Classes +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Struct FormattedNumber +// ---------------------------------------------------------------------------- + +/*! + * @class FormattedNumber + * @implements NumberConcept + * @headerfile + * + * @brief Helper class for storing a numeric value together with a + * printf format string. + * + * @signature template + * struct FormattedNumber; + * + * @tparam The numeric value type. + */ + +template +struct FormattedNumber +{ + char const * format; + TValue value; + + /*! + * @fn FormattedNumber::FormattedNumber + * @brief Constructor. + * + * @signature FormattedNumber::FormattedNumber(format, value); + * + * @param[in] format A char const * for the format string. + * @param[in] value The TValue to store. + * + * The constructed FormattedNumber object store the format pointer "as is". This means that you are + * responsible for keeping this pointer valid until the object is deconstructed. Passing in a C string literal + * (as in FormattedNumber<double>("%.2f", 1.234) is fine. + */ + + FormattedNumber(char const * format, TValue const & value) : + format(format), value(value) + {} + + operator TValue() const + { + return value; + } +}; + +template +struct Is< NumberConcept< FormattedNumber > > : + Is< NumberConcept > {}; + +// ============================================================================ +// Exceptions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Exception ParseError +// ---------------------------------------------------------------------------- + +/*! + * @class ParseError + * @extends RuntimeError + * @headerfile + * + * @brief Exception class for parser errors. + * + * @signature struct ParseError : RuntimeError; + */ + +struct ParseError : RuntimeError +{ + /*! + * @fn ParseError::ParseError + * @headerfile + * + * @brief Constructor. + * + * @signature ParseError::ParseError(message); + * + * @param[in] message The error message to use, std::string or char const * . + */ + + template + ParseError(TString const & message) : + RuntimeError(message) + {} +}; + +// ---------------------------------------------------------------------------- +// Exception UnexpectedEnd +// ---------------------------------------------------------------------------- + +/*! + * @class UnexpectedEnd + * @extends ParseError + * @headerfile + * + * @brief Exception class for "unexpected end of input" errors. + * + * @signature struct UnexpectedEnd : RuntimeError; + */ + +struct UnexpectedEnd : ParseError +{ + /*! + * @fn UnexpectedEnd::UnexpectedEnd + * @headerfile + * + * @brief Default constructor, makes the object use a default message. + * + * @signature UnexpectedEnd::UnexpectedEnd(); + */ + + UnexpectedEnd() : + ParseError("Unexpected end of input.") + {} +}; + +// ---------------------------------------------------------------------------- +// Exception EmptyFieldError +// ---------------------------------------------------------------------------- + +/*! + * @class EmptyFieldError + * @extends ParseError + * @headerfile + * + * @brief Exception class for "empty field" errors. + * + * @signature struct EmptyFieldError : RuntimeError; + */ + +struct EmptyFieldError : ParseError +{ + /*! + * @fn EmptyFieldError::EmptyFieldError + * @headerfile + * + * @brief Construct the exception with fieldName + " field was empty.". + * + * @signature EmptyFieldEror::EmptyFieldError(fieldName); + * + * @param[in] fieldName The field name to use for the message, std::string. + */ + + EmptyFieldError(std::string fieldName): + ParseError(fieldName + " field was empty.") + {} +}; + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction Iterator +// ---------------------------------------------------------------------------- + +/*! + * @mfn StreamConcept#DirectionIterator + * @brief Return the direction iterator for the given direction. + * + * @signature DirectionIterator::Type; + * + * @tparam TStream The stream to query for its direction iterator. + * @return Type The resulting direction iterator. + */ + +/*! + * @mfn ContainerConcept#DirectionIterator + * @brief Return the direction iterator for the given direction. + * + * @signature DirectionIterator::Type; + * + * @tparam TContainer The container to query for its direction iterator. + * @return Type The resulting direction iterator. + */ + +template +struct DirectionIterator : + If >, + Iter >, + typename Iterator::Type> +{}; + +// -------------------------------------------------------------------------- +// Metafunction BasicStream +// -------------------------------------------------------------------------- + +/*! + * @mfn BasicStream + * @headerfile + * @brief Return the stream type to read or write values. + * + * @signature BasicStream::Type; + * + * @tparam TValue The value type of the stream. + * @tparam TDirection The direction of the stream, one of the @link DirectionTags @endlink. + * @tparam TTraits The traits to use for the values, defaults to std::char_traits<TValue>. + * + */ + +template > +struct BasicStream : + If< + IsSameType, + std::basic_istream, + typename If< + IsSameType, + std::basic_ostream, + std::basic_iostream + >::Type + > +{}; + +// -------------------------------------------------------------------------- +// Metafunction IosOpenMode +// -------------------------------------------------------------------------- + +/*! + * @mfn IosOpenMode + * @headerfile + * @brief Return the std::ios open mode for a direction. + * + * @signature IosOpenMode::Type; + * + * @tparam TDirection The direction to query for the open mode, one of the @link DirectionTags @endlink. + * @tparam TDummy Implementation detail, defaults to void and is ignored. + * @return Type The resulting open mode of type const int. + */ + +template +struct IosOpenMode; + + +template +struct IosOpenMode +{ + static const int VALUE; +}; + +template +struct IosOpenMode +{ + static const int VALUE; +}; + +template +struct IosOpenMode +{ + static const int VALUE; +}; + +template +const int IosOpenMode::VALUE = std::ios::in | std::ios::binary; + +template +const int IosOpenMode::VALUE = std::ios::out | std::ios::binary; + +template +const int IosOpenMode::VALUE = std::ios::in | std::ios::out | std::ios::binary; + + +// -------------------------------------------------------------------------- +// Metafunction MagicHeader +// -------------------------------------------------------------------------- + +/*! + * @mfn MagicHeader + * @headerfile + * @brief Returns the magic header for a file format tag. + * + * The magic header is used for recognizing files from the first few bytes. + * + * @signature MagicHeader::VALUE; + * + * @tparam TTag The file format tag to use for the query. + * @tparam TDummy Implementation detail, defaults to void and is ignored. + * @return VALUE The magic header string, of type char const *. + * + * This metafunction must be implemented in the modules implementing the file I/O. The metafunction is predefined when + * TTag is @link Nothing @endlink. In this case, VALUE is NULL. + */ + +template +struct MagicHeader; + +template +struct MagicHeader +{ + static char const * VALUE; +}; + +template +char const * MagicHeader::VALUE = NULL; + +// -------------------------------------------------------------------------- +// Metafunction FileExtensions +// -------------------------------------------------------------------------- + +/*! + * @mfn FileExtensions + * @headerfile + * @brief Returns an array of file format extension strings for file foramt tag. + * + * @signature FileExtensions::VALUE; + * + * @tparam TTag The file format tag to use for the query. + * @tparam TDummy Implementation detail, defaults to void and is ignored. + * @return VALUE The array of file format extension, of type char const *[]. + * + * This metafunction must be implemented in the modules implementing the file I/O. The metafunction is predefined when + * TTag is @link Nothing @endlink. In this case, VALUE is {""}. + */ + +template +struct FileExtensions; + +template +struct FileExtensions +{ + static char const * VALUE[1]; +}; + +template +char const * FileExtensions::VALUE[1] = +{ + "" // default output extension +}; + +// ---------------------------------------------------------------------------- +// Metafunction IntegerFormatString_ +// ---------------------------------------------------------------------------- +// Return the format string for numbers. + +template +struct IntegerFormatString_; + + +template +struct IntegerFormatString_ : + IntegerFormatString_ {}; + + +template +struct IntegerFormatString_ +{ + static const char VALUE[]; + typedef short Type; +}; +template +const char IntegerFormatString_::VALUE[] = "%hi"; + + +template +struct IntegerFormatString_ +{ + static const char VALUE[]; + typedef unsigned short Type; +}; +template +const char IntegerFormatString_::VALUE[] = "%hu"; + + +template +struct IntegerFormatString_ +{ + static const char VALUE[]; + typedef int Type; +}; +template +const char IntegerFormatString_::VALUE[] = "%i"; + + +template +struct IntegerFormatString_ +{ + static const char VALUE[]; + typedef unsigned Type; +}; +template +const char IntegerFormatString_::VALUE[] = "%u"; + + +// helper for the case: typedef long int64_t; +template +struct LongFormatString_; + +template +struct LongFormatString_ +{ + static const char VALUE[]; + typedef long Type; +}; +template +const char LongFormatString_::VALUE[] = "%li"; + +template +struct LongFormatString_ +{ + static const char VALUE[]; + typedef unsigned long Type; +}; +template +const char LongFormatString_::VALUE[] = "%lu"; + +// helper for the case: typedef long long int64_t; +template +struct Int64FormatString_; + +template +struct Int64FormatString_ +{ + static const char VALUE[]; + typedef int64_t Type; +}; +template +const char Int64FormatString_::VALUE[] = "%lli"; + +template +struct Int64FormatString_ +{ + static const char VALUE[]; + typedef uint64_t Type; +}; +template +const char Int64FormatString_::VALUE[] = "%llu"; + + +template +struct IntegerFormatString_ : + If, + LongFormatString_, + Int64FormatString_ >::Type {}; + + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function writeValue() [ContainerConcept] +// ---------------------------------------------------------------------------- + +/*! + * @fn ContainerConcept#writeValue + * @brief Write a value at the end of a container. + * + * @signature void writeValue(container, val); + * + * @param[in,out] container to append to. + * @param[in] val The value to append. + * + * @see ContainerConcept#appendValue + */ + +// resizable containers +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +writeValue(TSequence &cont, TValue val) +{ + appendValue(cont, val); +} + +// ---------------------------------------------------------------------------- +// Function writeValue() [Range] +// ---------------------------------------------------------------------------- + +/*! + * @fn Range#writeValue + * @brief Write a value to a @link Range @endlink. + * + * @signature void writeValue(range, val); + * + * val will be assigned to the first element of the range. Then, the beginning of the range will be advanced + * by one. + * + * @param[in,out] range to append to. + * @param[in] val The value to append. + */ + +// Range +template +inline void +writeValue(Range &range, TValue val) +{ + assignValue(range.begin, val); + ++range.begin; +} + +// ---------------------------------------------------------------------------- +// Function writeValue() [Iter] +// ---------------------------------------------------------------------------- + +/*! + * @fn OutputIteratorConcept#writeValue + * @brief Write a single value to a container by dereferencing its iterator. + * + * @signature void writeValue(iter, val); + * + * @param[in,out] iter The iterator to use for dereferenced writing. + * @param[in] val The value to write into the container. + * + * If the host of iter is a @link ContainerConcept @endlink then container is resized to make space for the + * item. + */ + +// resizable containers +template +inline SEQAN_FUNC_ENABLE_IF(Is >, void) +writeValue(Iter & iter, TValue val) +{ + typedef Iter TIter; + + TSequence &cont = container(iter); + typename Position::Type pos = position(iter); + typename Size::Type len = length(cont); + + if (pos < len) + { + assignValue(iter, val); + ++iter; + } + else + { + if (pos > len) + resize(cont, pos - 1); + appendValue(cont, val); + setPosition(iter, pos + 1); + } +} + +// non-resizable containers +template +inline SEQAN_FUNC_DISABLE_IF(Is >, void) +writeValue(Iter & iter, TValue val) +{ + SEQAN_ASSERT_LT(position(iter), length(container(iter))); + + assignValue(iter, val); + ++iter; +} + +// ---------------------------------------------------------------------------- +// Function writeValue() [pointer] +// ---------------------------------------------------------------------------- + +///*! +// * @fn ContainerConcept#writeValue +// * @brief Write a value by dereferencing a pointer and incrementing its position by one. +// * +// * @signature void writeValue(pointer, val); +// * +// * @param[in,out] iter The pointer to dereference, usually a char *. +// * @param[in] val The value to write to the dereferenced pointer. +// * +// * This function is equivalent to *iter++ = val. +// */ + +template +inline void +writeValue(TTargetValue * & iter, TValue val) +{ + *iter++ = val; +} + +// ---------------------------------------------------------------------------- +// Function _write(); Element-wise +// ---------------------------------------------------------------------------- + +template +inline void _write(TTarget &target, TFwdIterator &iter, TSize n, TIChunk, TOChunk) +{ + for (; n > (TSize)0; --n, ++iter) + writeValue(target, getValue(iter)); +} + +// ---------------------------------------------------------------------------- +// Function _write(); Chunked +// ---------------------------------------------------------------------------- + +template +inline void _write(TTarget &target, TFwdIterator &iter, TSize n, Range *, Range *) +{ + typedef Nothing* TNoChunking; + typedef typename Size::Type TTargetSize; + + Range ichunk; + Range ochunk; + + while (n != (TSize)0) + { + getChunk(ichunk, iter, Input()); + getChunk(ochunk, target, Output()); + + TTargetSize minChunkSize = std::min((TTargetSize)length(ichunk), (TTargetSize)length(ochunk)); + + if (SEQAN_UNLIKELY(minChunkSize == 0u)) + { + reserveChunk(target, n, Output()); + reserveChunk(iter, n, Input()); + getChunk(ochunk, target, Output()); + getChunk(ichunk, iter, Input()); + minChunkSize = std::min((TTargetSize)length(ichunk), (TTargetSize)length(ochunk)); + if (SEQAN_UNLIKELY(minChunkSize == 0u)) + { + _write(target, iter, n, TNoChunking(), TNoChunking()); + return; + } + } + + if (minChunkSize > (TTargetSize)n) + minChunkSize = (TTargetSize)n; + + arrayCopyForward(ichunk.begin, ichunk.begin + minChunkSize, ochunk.begin); + + iter += minChunkSize; // advance input iterator + advanceChunk(target, minChunkSize); + n -= minChunkSize; + } +} + +// chunked, target is pointer (e.g. readRawPod) +template +inline SEQAN_FUNC_DISABLE_IF(IsSameType::Type, Nothing>, void) +write(TOValue *ptr, TFwdIterator &iter, TSize n) +{ + typedef Nothing* TNoChunking; + typedef typename Size::Type TSourceSize; + typedef typename Chunk::Type TIChunk; + + TIChunk ichunk; + + while (n != (TSize)0) + { + getChunk(ichunk, iter, Input()); + TSourceSize chunkSize = length(ichunk); + + if (SEQAN_UNLIKELY(chunkSize == 0u)) + { + reserveChunk(iter, n, Input()); + getChunk(ichunk, iter, Input()); + TSourceSize chunkSize = length(ichunk); + if (SEQAN_UNLIKELY(chunkSize == 0u)) + { + _write(ptr, iter, n, TNoChunking(), TNoChunking()); + return; + } + } + + if (chunkSize > (TSourceSize)n) + chunkSize = (TSourceSize)n; + + arrayCopyForward(ichunk.begin, ichunk.begin + chunkSize, ptr); + + iter += chunkSize; // advance input iterator + ptr += chunkSize; + n -= chunkSize; + } +} + +// non-chunked fallback +template +inline SEQAN_FUNC_ENABLE_IF(And< IsSameType::Type, Nothing>, + Is::Type, TIValue> > >, void) +write(TTarget &target, TIValue *ptr, TSize n) +{ + _write(target, ptr, n, Nothing(), Nothing()); +} + +// ostream shortcut, source is pointer (e.g. readRawPod) +template +inline SEQAN_FUNC_ENABLE_IF(Is< OutputStreamConcept >, void) +write(TTarget &target, const char *ptr, TSize n) +{ + target.write(ptr, n); +} + +// ostream shortcut, source is pointer (e.g. readRawPod) +template +inline SEQAN_FUNC_ENABLE_IF(Is< OutputStreamConcept >, void) +write(TTarget &target, char *ptr, TSize n) +{ + target.write(ptr, n); +} + +// chunked, source is pointer (e.g. readRawPod) +template +inline SEQAN_FUNC_ENABLE_IF(And< Not::Type, Nothing> >, + Is::Type, TIValue> > >, void) +write(TTarget &target, TIValue *ptr, TSize n) +{ + typedef Nothing* TNoChunking; + typedef typename Size::Type TTargetSize; + typedef typename Chunk::Type TOChunk; + + TOChunk ochunk; + + while (n != (TSize)0) + { + getChunk(ochunk, target, Output()); + TTargetSize chunkSize = length(ochunk); + + if (SEQAN_UNLIKELY(chunkSize == 0u)) + { + reserveChunk(target, n, Output()); + getChunk(ochunk, target, Output()); + chunkSize = length(ochunk); + if (SEQAN_UNLIKELY(chunkSize == 0u)) + { + _write(target, ptr, n, TNoChunking(), TNoChunking()); + return; + } + } + + if (chunkSize > (TTargetSize)n) + chunkSize = (TTargetSize)n; + + arrayCopyForward(ptr, ptr + chunkSize, ochunk.begin); + + ptr += chunkSize; // advance input iterator + advanceChunk(target, chunkSize); + n -= chunkSize; + } +} + +template +inline SEQAN_FUNC_ENABLE_IF(And< Is >, + Is > >, void) +write(TOValue * &optr, TIValue *iptr, TSize n) +{ + std::memcpy(optr, iptr, n); + optr += n; +} + +template +inline SEQAN_FUNC_ENABLE_IF(And< Is >, + Is > >, void) +write(TOValue * optr, TIValue * &iptr, TSize n) +{ + std::memcpy(optr, iptr, n); + iptr += n; +} + +// ---------------------------------------------------------------------------- +// Function write(TValue *) +// ---------------------------------------------------------------------------- +// NOTE(esiragusa): should it be defined for Streams and Containers? + +//template +//inline SEQAN_FUNC_ENABLE_IF(Or >, Is > >, void) +//write(TTarget &target, TValue *ptr, TSize n) +//{ +// typedef Range TRange; +// typedef typename Iterator::Type TIterator; +// typedef typename Chunk::Type* TIChunk; +// typedef typename Chunk::Type* TOChunk; +// +// TRange range(ptr, ptr + n); +// TIterator iter = begin(range, Rooted()); +// _write(target, iter, n, TIChunk(), TOChunk()); +//} + +// ---------------------------------------------------------------------------- +// Function write(Iterator) +// ---------------------------------------------------------------------------- + +/*! + * @fn ContainerConcept#write + * @brief Write to a container. + * + * @signature void write(container, iter, n); + * + * @param[in,out] container The container to append to. + * @param[in,out] iter The @link ForwardIteratorConcept forward iterator @endlink to take the values from. + * @param[in] n Number of elements to write from iter. + * + * This function reads n values from iter and appends them to the back of container. + */ + +//TODO(singer): Enable this! +template +//inline SEQAN_FUNC_ENABLE_IF(Or >, Is > >, void) +inline SEQAN_FUNC_ENABLE_IF(And< Is >, + Is::Type, + typename Value::Type> > >, void) +write(TTarget &target, TFwdIterator &iter, TSize n) +{ + typedef typename Chunk::Type* TIChunk; + typedef typename Chunk::Type* TOChunk; + + _write(target, iter, n, TIChunk(), TOChunk()); +} + +// write for more complex values (defer to write of iterator value) +// used for Strings of Pairs +template +//inline SEQAN_FUNC_ENABLE_IF(Or >, Is > >, void) +inline SEQAN_FUNC_ENABLE_IF(And< + Is >, + Not< Is::Type, + typename Value::Type> > > >, void) +write(TTarget &target, TFwdIterator &iter, TSize n) +{ + for (; n > (TSize)0; --n, ++iter) + { + write(target, *iter); + writeValue(target, ' '); + } +} + +// ---------------------------------------------------------------------------- +// Function write(TContainer) but not container of container +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(And< Not >, + And< Is >, + Not::Type> > > > >, void) +write(TTarget &target, TContainer &cont) +{ + typename DirectionIterator::Type iter = directionIterator(cont, Input()); + write(target, iter, length(cont)); +} + +template +inline SEQAN_FUNC_ENABLE_IF(And< IsContiguous, + And< Is >, + Not::Type> > > > >, void) +write(TTarget &target, TContainer &cont) +{ + typename Iterator::Type iter = begin(cont, Standard()); + write(target, iter, length(cont)); +} + +template +inline SEQAN_FUNC_ENABLE_IF(And< Not >, + And< Is >, + Not::Type> > > > >, void) +write(TTarget &target, TContainer const &cont) +{ + typename DirectionIterator::Type iter = directionIterator(cont, Input()); + write(target, iter, length(cont)); +} + +template +inline SEQAN_FUNC_ENABLE_IF(And< IsContiguous, + And< Is >, + Not::Type> > > > >, void) +write(TTarget &target, TContainer const &cont) +{ + typename Iterator::Type iter = begin(cont, Standard()); + write(target, iter, length(cont)); +} + +template +inline void +write(TTarget &target, TValue * ptr) +{ + write(target, ptr, length(ptr)); +} + +// ---------------------------------------------------------------------------- +// Function appendNumber() +// ---------------------------------------------------------------------------- +// Generic version for integers. + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, typename Size::Type) +appendNumber(TTarget & target, TInteger i) +{ + typedef IntegerFormatString_ >::Type, + sizeof(TInteger)> TInt; + + // 1 byte has at most 3 decimal digits (plus 2 for '-' and the NULL character) + char buffer[sizeof(TInteger) * 3 + 2]; + size_t len = snprintf(buffer, sizeof(buffer), + TInt::VALUE, static_cast(i)); + char *bufPtr = buffer; + write(target, bufPtr, len); + return len; +} + +// ---------------------------------------------------------------------------- +// Function appendNumber(bool) +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +appendNumber(TTarget & target, bool source) +{ + writeValue(target, '0' + source); + return 1; +} + +// ---------------------------------------------------------------------------- +// Function appendNumber(float) +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +appendNumber(TTarget & target, float source) +{ + char buffer[32]; + size_t len = snprintf(buffer, sizeof(buffer), "%g", source); + write(target, (char *)buffer, len); + return len; +} + +// ---------------------------------------------------------------------------- +// Function appendNumber(double) +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +appendNumber(TTarget & target, double source) +{ + char buffer[32]; + size_t len = snprintf(buffer, sizeof(buffer), "%g", source); + write(target, (char *)buffer, len); + return len; +} + +// ---------------------------------------------------------------------------- +// Function appendNumber(double) +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +appendNumber(TTarget & target, FormattedNumber const & source) +{ + char buffer[100]; + size_t len = snprintf(buffer, sizeof(buffer), source.format, source.value); + write(target, (char *)buffer, len); + return len; +} + +template +inline FormattedNumber +formattedNumber(const char *format, TValue const & val) +{ + return FormattedNumber(format, val); +} + +// ---------------------------------------------------------------------------- +// Function appendRawPod() +// ---------------------------------------------------------------------------- + +template +inline void +appendRawPod(TTarget & target, TValue const & val) +{ + write(target, (unsigned char*)&val, sizeof(TValue)); +} + +template +inline void +appendRawPod(TTargetValue * &ptr, TValue const & val) +{ + *reinterpret_cast(ptr)++ = val; +} + +// ---------------------------------------------------------------------------- +// Function write(TNumber); write fundamental type +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(And< Is::Type, TValue> >, + Is > >, void) +write(TTarget &target, TValue &number) +{ + if (sizeof(TValue) == 1) + writeValue(target, number); // write chars as chars + else + appendNumber(target, number); +} + +template +inline SEQAN_FUNC_ENABLE_IF(And< Is::Type, TValue> >, + Is > >, void) +write(TTarget &target, TValue const &number) +{ + if (sizeof(TValue) == 1) + writeValue(target, number); // write chars as chars + else + appendNumber(target, number); +} + +// ---------------------------------------------------------------------------- +// Function write(TNumber); write non-fundamental, convertible type +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(And< Is::Type, TValue> >, + Not > > >, void) +write(TTarget &target, TValue &number) +{ + writeValue(target, number); +} + +template +inline SEQAN_FUNC_ENABLE_IF(And< Is::Type, TValue const> >, + Not > > >, void) +write(TTarget &target, TValue const &number) +{ + writeValue(target, number); +} + +// ---------------------------------------------------------------------------- +// Function read(Iterator) +// ---------------------------------------------------------------------------- + +template +inline SEQAN_FUNC_ENABLE_IF(Is >, TSize) +read(TTarget &target, TFwdIterator &iter, TSize n) +{ + TSize i; + for (i = 0; !atEnd(iter) && i < n; ++i, ++iter) + writeValue(target, value(iter)); + return i; +} + +// ---------------------------------------------------------------------------- +// Function read(TContainer) +// ---------------------------------------------------------------------------- + +template +inline typename Size::Type +read(TTarget &target, TContainer &cont) +{ + typename DirectionIterator::Type iter = directionIterator(cont, Input()); + return read(target, iter, length(cont)); +} + +// ---------------------------------------------------------------------------- +// operator<< +// ---------------------------------------------------------------------------- + +template +inline TStream & +operator<<(TStream & target, + Range const & source) +{ + typename DirectionIterator::Type it = directionIterator(target, Output()); + write(it, source); + return target; +} + +template +inline TStream & +operator<<(TStream & target, + FormattedNumber const & source) +{ + typename DirectionIterator::Type it = directionIterator(target, Output()); + write(it, source); + return target; +} + +} // namespace seqean + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BASIC_STREAM_H_ diff --git a/seqan/basic/basic_tangle.h b/seqan/basic/basic_tangle.h new file mode 100644 index 0000000..4190559 --- /dev/null +++ b/seqan/basic/basic_tangle.h @@ -0,0 +1,166 @@ +// ========================================================================== +// basic_tangle.h +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== + +// TODO(holtgrew): This header contains code that does not clearly belongs somewhere else. + +#ifndef INCLUDE_SEQAN_BASIC_BASIC_TANGLE_H_ +#define INCLUDE_SEQAN_BASIC_BASIC_TANGLE_H_ + +namespace seqan { + +// TODO(holtgrew): Remove this define. +#define seqan seqan + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// TODO(holtgrew): Remove auto-sequence! +template +struct Iterator, Standard> +{ + typedef SimpleType * Type; +// typedef Iter, SimpleIterator> * Type; +}; + +template +struct Iterator const, Standard> +{ + typedef SimpleType const * Type; +// typedef Iter const, SimpleIterator> * Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Key +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Is this part of some adaption? + +template +struct Key > +{ + typedef TKey Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction Cargo +// ---------------------------------------------------------------------------- + +// TODO(holtgrew): Is this part of some adaption? + +template +struct Cargo > +{ + typedef TCargo Type; +}; + + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function assignQualities() +// ---------------------------------------------------------------------------- + +/*! + * @fn assignQualities + * @headerfile + * @brief Assign quality values between strings. + * + * @signature void assignQualities(target, source); + * + * @param[out] target Target string, can be a String of DnaQ or Dna5Q characters. + * @param[in] source Source string. Can be a String of int or char. + * + * @section Remarks + * + * The target is resized to the length of source. This function calls assignQualityValue for all entries of + * target and source, look at the documentation of assignQualityValue on how the values of + * source are interpreted. + * + * Note that qualities are expected to be in PHRED scale. + * + * @see AlphabetWithQualitiesConcept#assignQualityValue + */ + +template +inline void +_assignQualities(TDest &dst, TSource const &src, True) +{ + typedef typename Iterator::Type TDestIter; + typedef typename Iterator::Type TSourceIter; + + if (length(dst) < length(src)) + resize(dst, length(src)); + + TDestIter itDst = begin(dst, Standard()); + TSourceIter itSrcEnd = end(src, Standard()); + + for (TSourceIter itSrc = begin(src, Standard()); itSrc != itSrcEnd; ++itDst, ++itSrc) + assignQualityValue(*itDst, *itSrc); +} + +template +inline void +_assignQualities(TDest &, TSource const &, False) +{} + +// TODO(holtgrew): Uncomment, place somewhere that knows both iterators and assignQualityValue, maybe in module sequence? +template +inline void +assignQualities(TDest &dst, TSource const &src) +{ + typedef typename Value::Type TValue; + _assignQualities(dst, src, typename Or, IsSameType >::Type()); +} + +template +inline T +unknownValueImpl(T *) +{ + return 'N'; +} + +} // namespace seqan + +#endif // #ifndef INCLUDE_SEQAN_BASIC_BASIC_TANGLE_H_ diff --git a/seqan/basic/basic_type.h b/seqan/basic/basic_type.h new file mode 100644 index 0000000..1039a24 --- /dev/null +++ b/seqan/basic/basic_type.h @@ -0,0 +1,543 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// Copyright (c) 2013 NVIDIA Corporation +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Andreas Gogol-Döring +// ========================================================================== +// Definition of basic Metafunctions. +// ========================================================================== + +// TODO(holtgrew): Rename to "shared metafunctions.h"? +// TODO(holtgrew): This could use some cleanup. + +#ifndef SEQAN_BASIC_BASIC_TYPE_H_ +#define SEQAN_BASIC_BASIC_TYPE_H_ + +#include + +namespace seqan { + +////////////////////////////////////////////////////////////////////////////// + +// TODO(holtgrew): Remove default implementation. +// SEQREV: elements-are-containers should not have a default implementation + +template +struct Value +{ + typedef T Type; +}; + +template +struct Value +{ + typedef T const Type; +}; + +//____________________________________________________________________________ + + +// TODO(holtgrew): Remove default implementation. +template +struct GetValue +{ + typedef typename Value::Type const & Type; +}; + +template +struct GetValue: + public GetValue +{ +}; + +//____________________________________________________________________________ + +// TODO(holtgrew): Remove default implementation. +template +struct Reference +{ + typedef typename Value::Type & Type; +}; + +template +struct Reference +{ + typedef typename Value::Type const & Type; +}; + +//____________________________________________________________________________ + + +// TODO(holtgrew): Remove default implementation. +template +struct Size +{ + typedef size_t Type; +}; + +template +struct Size: + Size +{ +}; + +//____________________________________________________________________________ + + + +// TODO(holtgrew): Remove default implementation. +template +struct Difference +{ + typedef ptrdiff_t Type; +}; + +template +struct Difference: + Difference +{ +}; + +//____________________________________________________________________________ + + +// TODO(holtgrew): Remove default implementation. +template +struct Position +{ + typedef typename Size::Type Type; +}; + +template +struct Position: + Position +{ +}; + +//____________________________________________________________________________ + +// SEQREV: elements-are-containers should not have a default implementation, if a type has no host, do not return self + +template +struct Host +{ + typedef T Type; +}; + +//____________________________________________________________________________ + +//____________________________________________________________________________ + +/*! + * @mfn Cargo + * @headerfile + * @brief Type of additional data stored in an object. + * + * @signature Cargo::Type; + * + * @tparam T Type for which the cargo tpye is queried. + * + * @return Type The cargo type of T. + * + * The definition of Cargo allows the addition of user-specified data into existing data structures. + */ + +// TODO(holtgrew): Should this have a default implementation? + +template +struct Cargo { + typedef Nothing Type; +}; +template +struct Cargo { + typedef typename Cargo::Type const Type; +}; + +//____________________________________________________________________________ + +/*! + * @mfn VertexDescriptor + * @headerfile + * @brief Type of an object that represents a vertex descriptor. + * + * @signature VertexDescriptor::Type; + * + * @tparam T The graph type to query. + * + * @return Type The resulting vertex descriptor type. + */ + +// TODO(holtgrew): Should this have a default implementation? For all graphs -- OK but for all types? + +template +struct VertexDescriptor { + typedef void* Type; +}; +template +struct VertexDescriptor: + public VertexDescriptor {}; + + +//____________________________________________________________________________ + +/*! + * @mfn Id + * @headerfile + * @brief Type of an object that represents an id. + * + * @signature Id::Type + * + * @tparam T The type to query for its id type. + * + * @return Type The resulting identifier type. + */ + +// TODO(holtgrew): Should this have a default implementation? + +template +struct Id { + typedef unsigned int Type; +}; + +template +struct Id : Id {}; + +//____________________________________________________________________________ + +/*! + * @mfn Key + * @headerfile + * @brief Key type of a key to cargo mapping. + * + * @signature Key::Type; + * + * @tparam T Type for which a key type is determined. + * + * @return Type The key type. + */ + +// TODO(holtgrew): Should this have a default implementation? + +template< typename T > +struct Key +{ + typedef T Type; +}; + +template +struct Key: + Key {}; + +//____________________________________________________________________________ + +template +struct Object; + +template +struct Object: + Object {}; + + +//____________________________________________________________________________ + +// TODO(holtgrew): Move to alignments? +// TODO(holtgrew): Is this default implementation what we want? + +template < typename TSpec = void > +struct Source +{ + typedef TSpec Type; +}; + +template +struct Source: + Source +{ +}; + + +//____________________________________________________________________________ + +/*! + * @mfn IsLightWeight + * @headerfile + * @brief Determines whether an object can efficiently be passed by copy. + * + * @signature IsLightWeight::Type; + * + * @tparam T The type to query. + * + * @return Type Either True or False. True if the object can efficiently be copied. + */ + +template +struct IsLightWeight: + False {}; + +//____________________________________________________________________________ + +// TODO(holtgrew): Really required? + +template +struct Parameter_ +{ + typedef T & Type; +}; + +template +struct Parameter_ +{ + typedef T const & Type; +}; + +template +struct Parameter_ +{ + typedef T * Type; +}; + +template +struct Parameter_ +{ + typedef T const * Type; +}; + +template +struct Parameter_ +{ + typedef T * Type; +}; + +template +struct Parameter_ +{ + typedef T const * Type; +}; + +// TODO(holtgrew): Really required? + +template +typename Parameter_::Type +inline _toParameter(T * _object) +{ + return * _object; +} + +template +typename Parameter_::Type +inline _toParameter(T & _object) +{ + return _object; +} + +template +typename Parameter_::Type +inline _toParameter(T const & _object) +{ + return _object; +} + +//____________________________________________________________________________ + +/*! + * @mfn Member + * @headerfile + * @brief Type of a member of an object. + * + * @signature Member::Type; + * @tparam TObject The object holding the member. + * @tparam TSpec A tag to identify the object's member. + * @return Type The resulting object's member type. + * + * This metafunction is used to control the type of a member of a given object. It works analogously to @link Fibre @endlink. + * For instance, it is used to change the relationship between two objects from aggregation to composition and vice versa. + * + * @see Fibre + */ + +template +struct Member; + +template +struct Member : + Member {}; + +//____________________________________________________________________________ + +// TODO(holtgrew): Really required? + +template +struct Pointer_ +{ + typedef T * Type; +}; + +template +struct Pointer_ +{ + typedef T * Type; +}; +template +struct Pointer_ +{ + typedef T * Type; +}; + +template +struct Pointer_ +{ + typedef T * Type; +}; + +//non const version of Pointer_ for return values + +template +struct NonConstPointer_: + Pointer_ +{ +}; +template +struct NonConstPointer_ +{ + typedef T * Type; +}; + +// TODO(holtgrew): Really required? + +template +inline typename NonConstPointer_::Type +_toPointer(T & _object) +{ + return & _object; +} +template +inline typename NonConstPointer_::Type +_toPointer(T const & _object) +{ + return & _object; +} + +template +inline typename NonConstPointer_::Type +_toPointer(T * _object) +{ + return _object; +} + +// -------------------------------------------------------------------------- +// Function _referenceCast() +// -------------------------------------------------------------------------- + +// explicitly give desired dereferenced type as first argument, +// e.g. _dereference(int*) or _dereference &>(Segment<..> &) +template +inline T +_referenceCast(typename RemoveReference::Type & ptr) +{ + return ptr; +} + +template +inline SEQAN_FUNC_DISABLE_IF(IsSameType::Type>, T) +_referenceCast(typename RemoveReference::Type * ptr) +{ + return *ptr; +} + +template +inline SEQAN_FUNC_DISABLE_IF(IsSameType::Type>, T) +_referenceCast(typename RemovePointer::Type & ptr) +{ + return &ptr; +} + + +//____________________________________________________________________________ + +/*! + * @mfn LENGTH + * @brief Number of elements in a fixed-size container/vector. + * + * @signature LENGTH::VALUE; + * + * @tparam T The type to query for its length. + * + * @return VALUE The length of T. + */ + +// SEQREV: elements-are-containers should probably not have a default implementation +// TODO(holtgrew): Rather switch to static const unsigned VALUE = ? + +template +struct LENGTH +{ + enum { VALUE = 1 }; +}; + +template +struct LENGTH: + LENGTH +{ +}; + +/*! + * @mfn WEIGHT + * @brief Number of relevant positions in a shape. + * + * @signature WEIGHT::VALUE; + * + * @tparam T The Shape type to query. + * @return VALUE The number of relevant positions in a shape. + */ + +// TODO(holtgrew): Should probably go to wherever shapes are defined. + +template +struct WEIGHT: + LENGTH +{ +}; +template +struct WEIGHT: + WEIGHT +{ +}; + +////////////////////////////////////////////////////////////////////////////// + +//Iterator: see basic_iterator.h + +////////////////////////////////////////////////////////////////////////////// + + +} // namespace seqan + +#endif // #ifndef SEQAN_BASIC_BASIC_TYPE_H_ diff --git a/seqan/basic/basic_view.h b/seqan/basic/basic_view.h new file mode 100644 index 0000000..debdcfc --- /dev/null +++ b/seqan/basic/basic_view.h @@ -0,0 +1,190 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2013 NVIDIA Corporation +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of NVIDIA Corporation nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Enrico Siragusa +// ========================================================================== + +#ifndef SEQAN_BASIC_VIEW_H +#define SEQAN_BASIC_VIEW_H + +namespace seqan { + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Metafunction View +// ---------------------------------------------------------------------------- + +/*! + * @mfn View + * @headerfile + * @brief Converts a given type into its view type. + * + * @signature View::Type; + * + * @tparam TObject The type to be converted into a view type. + * @return Type The resulting view type. + * + * This metafunction is used to convert device containers into views of device containers. + * Subsequently, the view of a device container can be safely passed to and used in device space. + * On the host, a view of a @link String @endlink is equivalent to an @link SegmentableConcept#Infix @endlink of the complete string. + * @link RemoveView @endlink is the inverse of this metafunction. + * + * @see RemoveView + * @see Device + * @see SegmentableConcept#Infix + */ + +template +struct View +{ + typedef TObject Type; +}; + +template +struct View +{ + typedef typename View::Type const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction RemoveView +// ---------------------------------------------------------------------------- + +/*! + * @mfn RemoveView + * @headerfile + * @brief Converts a given view type into its original type. + * + * @signature RemoveView::Type; + * + * @tparam TObject The view type to be converted into its original type. + * @return Type The resulting original type. + * + * @link View @endlink is the inverse of this metafunction. + * + * @see View + */ + +template +struct RemoveView +{ + typedef TObject Type; +}; + +template +struct RemoveView +{ + typedef typename RemoveView::Type const Type; +}; + +// ---------------------------------------------------------------------------- +// Metafunction IsView +// ---------------------------------------------------------------------------- + +/*! + * @mfn IsView + * @headerfile + * @brief Tests if a given type is a view type. + * + * @signature IsView::Type; + * + * @tparam TObject The type to be tested for being a view type. + * @return Type @link LogicalValuesTags#True @endlink or @link LogicalValuesTags#False @endlink. + * + * @see View + * @see RemoveView + */ + +template +struct IsView : public False {}; + +template +struct IsView : public IsView {}; + +// ---------------------------------------------------------------------------- +// Metafunction IfView +// ---------------------------------------------------------------------------- + +template +struct IfView +{ + typedef typename If, T1, T2>::Type Type; +}; + +// ============================================================================ +// Functions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Function view() +// ---------------------------------------------------------------------------- + +/*! + * @fn TView view + * @headerfile + * @brief Returns the view of a given object. + * + * @signature TView view(object); + * + * @param[in] object A generic object. + * @return TView The @link View @endlink type of the given object. + * + * @see View + * @see IsView + */ + +template +inline typename View::Type +view(TObject & object) +{ + return typename View::Type(object); +} + +template +inline typename View::Type +view(TObject const & object) +{ + return typename View::Type(object); +} + +template +inline typename View::Type +view(TObject * object) +{ + return typename View::Type(value(object)); +} + +} // namespace seqan + +#endif // #ifndef SEQAN_BASIC_VIEW_H diff --git a/seqan/basic/boost_preprocessor_subset.h b/seqan/basic/boost_preprocessor_subset.h new file mode 100644 index 0000000..634568a --- /dev/null +++ b/seqan/basic/boost_preprocessor_subset.h @@ -0,0 +1,4850 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Taken from Boost preprocessors library, Boost version 1.47. We extracted +// the minimal subset (header-wise) for supporting the concepts. +// +// There is currently no plan to incorporate more of Boost into SeqAn and +// thus this can be seen as a quick hack to get BCCL's nice syntax. It is +// probably a bad idea to repeat this. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_SEQAN_PREPROCESSOR_SUBSET_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_SEQAN_PREPROCESSOR_SUBSET_H_ + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/tuple/rem.hpp <== +// -------------------------------------------------------------------------- + +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_TUPLE_REM_HPP +// # define SEQAN_PREPROCESSOR_TUPLE_REM_HPP +# +// # include +# +# /* SEQAN_PP_TUPLE_REM */ +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_TUPLE_REM(size) SEQAN_PP_TUPLE_REM_I(size) +// # else +// # define SEQAN_PP_TUPLE_REM(size) SEQAN_PP_TUPLE_REM_OO((size)) +// # define SEQAN_PP_TUPLE_REM_OO(par) SEQAN_PP_TUPLE_REM_I ## par +// # endif +# +# define SEQAN_PP_TUPLE_REM_I(size) SEQAN_PP_TUPLE_REM_ ## size +# +# define SEQAN_PP_TUPLE_REM_0() +# define SEQAN_PP_TUPLE_REM_1(a) a +# define SEQAN_PP_TUPLE_REM_2(a, b) a, b +# define SEQAN_PP_TUPLE_REM_3(a, b, c) a, b, c +# define SEQAN_PP_TUPLE_REM_4(a, b, c, d) a, b, c, d +# define SEQAN_PP_TUPLE_REM_5(a, b, c, d, e) a, b, c, d, e +# define SEQAN_PP_TUPLE_REM_6(a, b, c, d, e, f) a, b, c, d, e, f +# define SEQAN_PP_TUPLE_REM_7(a, b, c, d, e, f, g) a, b, c, d, e, f, g +# define SEQAN_PP_TUPLE_REM_8(a, b, c, d, e, f, g, h) a, b, c, d, e, f, g, h +# define SEQAN_PP_TUPLE_REM_9(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i +# define SEQAN_PP_TUPLE_REM_10(a, b, c, d, e, f, g, h, i, j) a, b, c, d, e, f, g, h, i, j +# define SEQAN_PP_TUPLE_REM_11(a, b, c, d, e, f, g, h, i, j, k) a, b, c, d, e, f, g, h, i, j, k +# define SEQAN_PP_TUPLE_REM_12(a, b, c, d, e, f, g, h, i, j, k, l) a, b, c, d, e, f, g, h, i, j, k, l +# define SEQAN_PP_TUPLE_REM_13(a, b, c, d, e, f, g, h, i, j, k, l, m) a, b, c, d, e, f, g, h, i, j, k, l, m +# define SEQAN_PP_TUPLE_REM_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) a, b, c, d, e, f, g, h, i, j, k, l, m, n +# define SEQAN_PP_TUPLE_REM_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o +# define SEQAN_PP_TUPLE_REM_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p +# define SEQAN_PP_TUPLE_REM_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q +# define SEQAN_PP_TUPLE_REM_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r +# define SEQAN_PP_TUPLE_REM_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s +# define SEQAN_PP_TUPLE_REM_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t +# define SEQAN_PP_TUPLE_REM_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u +# define SEQAN_PP_TUPLE_REM_22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v +# define SEQAN_PP_TUPLE_REM_23(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w +# define SEQAN_PP_TUPLE_REM_24(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x +# define SEQAN_PP_TUPLE_REM_25(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y +# +# /* SEQAN_PP_TUPLE_REM_CTOR */ +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() +# define SEQAN_PP_TUPLE_REM_CTOR(size, tuple) SEQAN_PP_TUPLE_REM_CTOR_I(SEQAN_PP_TUPLE_REM(size), tuple) +// # else +// # define SEQAN_PP_TUPLE_REM_CTOR(size, tuple) SEQAN_PP_TUPLE_REM_CTOR_D(size, tuple) +// # define SEQAN_PP_TUPLE_REM_CTOR_D(size, tuple) SEQAN_PP_TUPLE_REM_CTOR_I(SEQAN_PP_TUPLE_REM(size), tuple) +// # endif +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_TUPLE_REM_CTOR_I(ext, tuple) ext tuple +// # else +// # define SEQAN_PP_TUPLE_REM_CTOR_I(ext, tuple) SEQAN_PP_TUPLE_REM_CTOR_OO((ext, tuple)) +// # define SEQAN_PP_TUPLE_REM_CTOR_OO(par) SEQAN_PP_TUPLE_REM_CTOR_II ## par +// # define SEQAN_PP_TUPLE_REM_CTOR_II(ext, tuple) ext ## tuple +// # endif +# +// # endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/tuple/elem.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_TUPLE_ELEM_HPP +// # define SEQAN_PREPROCESSOR_TUPLE_ELEM_HPP +# +// # include +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_TUPLE_ELEM(size, index, tuple) SEQAN_PP_TUPLE_ELEM_I(size, index, tuple) +// # else +// # define SEQAN_PP_TUPLE_ELEM(size, index, tuple) SEQAN_PP_TUPLE_ELEM_OO((size, index, tuple)) +// # define SEQAN_PP_TUPLE_ELEM_OO(par) SEQAN_PP_TUPLE_ELEM_I ## par +// # endif +# +// # if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +// # define SEQAN_PP_TUPLE_ELEM_I(s, i, t) SEQAN_PP_TUPLE_ELEM_ ## s ## _ ## i ## t +#ifdef STDLIB_VS // # elif SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MSVC() +# define SEQAN_PP_TUPLE_ELEM_I(s, i, t) SEQAN_PP_TUPLE_ELEM_II(SEQAN_PP_TUPLE_ELEM_ ## s ## _ ## i t) +# define SEQAN_PP_TUPLE_ELEM_II(res) res +#else // #ifdef STDLIB_VS +# define SEQAN_PP_TUPLE_ELEM_I(s, i, t) SEQAN_PP_TUPLE_ELEM_ ## s ## _ ## i t +#endif // #ifdef STDLIB_VS +# +# define SEQAN_PP_TUPLE_ELEM_1_0(a) a +# +# define SEQAN_PP_TUPLE_ELEM_2_0(a, b) a +# define SEQAN_PP_TUPLE_ELEM_2_1(a, b) b +# +# define SEQAN_PP_TUPLE_ELEM_3_0(a, b, c) a +# define SEQAN_PP_TUPLE_ELEM_3_1(a, b, c) b +# define SEQAN_PP_TUPLE_ELEM_3_2(a, b, c) c +# +# define SEQAN_PP_TUPLE_ELEM_4_0(a, b, c, d) a +# define SEQAN_PP_TUPLE_ELEM_4_1(a, b, c, d) b +# define SEQAN_PP_TUPLE_ELEM_4_2(a, b, c, d) c +# define SEQAN_PP_TUPLE_ELEM_4_3(a, b, c, d) d +# +# define SEQAN_PP_TUPLE_ELEM_5_0(a, b, c, d, e) a +# define SEQAN_PP_TUPLE_ELEM_5_1(a, b, c, d, e) b +# define SEQAN_PP_TUPLE_ELEM_5_2(a, b, c, d, e) c +# define SEQAN_PP_TUPLE_ELEM_5_3(a, b, c, d, e) d +# define SEQAN_PP_TUPLE_ELEM_5_4(a, b, c, d, e) e +# +# define SEQAN_PP_TUPLE_ELEM_6_0(a, b, c, d, e, f) a +# define SEQAN_PP_TUPLE_ELEM_6_1(a, b, c, d, e, f) b +# define SEQAN_PP_TUPLE_ELEM_6_2(a, b, c, d, e, f) c +# define SEQAN_PP_TUPLE_ELEM_6_3(a, b, c, d, e, f) d +# define SEQAN_PP_TUPLE_ELEM_6_4(a, b, c, d, e, f) e +# define SEQAN_PP_TUPLE_ELEM_6_5(a, b, c, d, e, f) f +# +# define SEQAN_PP_TUPLE_ELEM_7_0(a, b, c, d, e, f, g) a +# define SEQAN_PP_TUPLE_ELEM_7_1(a, b, c, d, e, f, g) b +# define SEQAN_PP_TUPLE_ELEM_7_2(a, b, c, d, e, f, g) c +# define SEQAN_PP_TUPLE_ELEM_7_3(a, b, c, d, e, f, g) d +# define SEQAN_PP_TUPLE_ELEM_7_4(a, b, c, d, e, f, g) e +# define SEQAN_PP_TUPLE_ELEM_7_5(a, b, c, d, e, f, g) f +# define SEQAN_PP_TUPLE_ELEM_7_6(a, b, c, d, e, f, g) g +# +# define SEQAN_PP_TUPLE_ELEM_8_0(a, b, c, d, e, f, g, h) a +# define SEQAN_PP_TUPLE_ELEM_8_1(a, b, c, d, e, f, g, h) b +# define SEQAN_PP_TUPLE_ELEM_8_2(a, b, c, d, e, f, g, h) c +# define SEQAN_PP_TUPLE_ELEM_8_3(a, b, c, d, e, f, g, h) d +# define SEQAN_PP_TUPLE_ELEM_8_4(a, b, c, d, e, f, g, h) e +# define SEQAN_PP_TUPLE_ELEM_8_5(a, b, c, d, e, f, g, h) f +# define SEQAN_PP_TUPLE_ELEM_8_6(a, b, c, d, e, f, g, h) g +# define SEQAN_PP_TUPLE_ELEM_8_7(a, b, c, d, e, f, g, h) h +# +# define SEQAN_PP_TUPLE_ELEM_9_0(a, b, c, d, e, f, g, h, i) a +# define SEQAN_PP_TUPLE_ELEM_9_1(a, b, c, d, e, f, g, h, i) b +# define SEQAN_PP_TUPLE_ELEM_9_2(a, b, c, d, e, f, g, h, i) c +# define SEQAN_PP_TUPLE_ELEM_9_3(a, b, c, d, e, f, g, h, i) d +# define SEQAN_PP_TUPLE_ELEM_9_4(a, b, c, d, e, f, g, h, i) e +# define SEQAN_PP_TUPLE_ELEM_9_5(a, b, c, d, e, f, g, h, i) f +# define SEQAN_PP_TUPLE_ELEM_9_6(a, b, c, d, e, f, g, h, i) g +# define SEQAN_PP_TUPLE_ELEM_9_7(a, b, c, d, e, f, g, h, i) h +# define SEQAN_PP_TUPLE_ELEM_9_8(a, b, c, d, e, f, g, h, i) i +# +# define SEQAN_PP_TUPLE_ELEM_10_0(a, b, c, d, e, f, g, h, i, j) a +# define SEQAN_PP_TUPLE_ELEM_10_1(a, b, c, d, e, f, g, h, i, j) b +# define SEQAN_PP_TUPLE_ELEM_10_2(a, b, c, d, e, f, g, h, i, j) c +# define SEQAN_PP_TUPLE_ELEM_10_3(a, b, c, d, e, f, g, h, i, j) d +# define SEQAN_PP_TUPLE_ELEM_10_4(a, b, c, d, e, f, g, h, i, j) e +# define SEQAN_PP_TUPLE_ELEM_10_5(a, b, c, d, e, f, g, h, i, j) f +# define SEQAN_PP_TUPLE_ELEM_10_6(a, b, c, d, e, f, g, h, i, j) g +# define SEQAN_PP_TUPLE_ELEM_10_7(a, b, c, d, e, f, g, h, i, j) h +# define SEQAN_PP_TUPLE_ELEM_10_8(a, b, c, d, e, f, g, h, i, j) i +# define SEQAN_PP_TUPLE_ELEM_10_9(a, b, c, d, e, f, g, h, i, j) j +# +# define SEQAN_PP_TUPLE_ELEM_11_0(a, b, c, d, e, f, g, h, i, j, k) a +# define SEQAN_PP_TUPLE_ELEM_11_1(a, b, c, d, e, f, g, h, i, j, k) b +# define SEQAN_PP_TUPLE_ELEM_11_2(a, b, c, d, e, f, g, h, i, j, k) c +# define SEQAN_PP_TUPLE_ELEM_11_3(a, b, c, d, e, f, g, h, i, j, k) d +# define SEQAN_PP_TUPLE_ELEM_11_4(a, b, c, d, e, f, g, h, i, j, k) e +# define SEQAN_PP_TUPLE_ELEM_11_5(a, b, c, d, e, f, g, h, i, j, k) f +# define SEQAN_PP_TUPLE_ELEM_11_6(a, b, c, d, e, f, g, h, i, j, k) g +# define SEQAN_PP_TUPLE_ELEM_11_7(a, b, c, d, e, f, g, h, i, j, k) h +# define SEQAN_PP_TUPLE_ELEM_11_8(a, b, c, d, e, f, g, h, i, j, k) i +# define SEQAN_PP_TUPLE_ELEM_11_9(a, b, c, d, e, f, g, h, i, j, k) j +# define SEQAN_PP_TUPLE_ELEM_11_10(a, b, c, d, e, f, g, h, i, j, k) k +# +# define SEQAN_PP_TUPLE_ELEM_12_0(a, b, c, d, e, f, g, h, i, j, k, l) a +# define SEQAN_PP_TUPLE_ELEM_12_1(a, b, c, d, e, f, g, h, i, j, k, l) b +# define SEQAN_PP_TUPLE_ELEM_12_2(a, b, c, d, e, f, g, h, i, j, k, l) c +# define SEQAN_PP_TUPLE_ELEM_12_3(a, b, c, d, e, f, g, h, i, j, k, l) d +# define SEQAN_PP_TUPLE_ELEM_12_4(a, b, c, d, e, f, g, h, i, j, k, l) e +# define SEQAN_PP_TUPLE_ELEM_12_5(a, b, c, d, e, f, g, h, i, j, k, l) f +# define SEQAN_PP_TUPLE_ELEM_12_6(a, b, c, d, e, f, g, h, i, j, k, l) g +# define SEQAN_PP_TUPLE_ELEM_12_7(a, b, c, d, e, f, g, h, i, j, k, l) h +# define SEQAN_PP_TUPLE_ELEM_12_8(a, b, c, d, e, f, g, h, i, j, k, l) i +# define SEQAN_PP_TUPLE_ELEM_12_9(a, b, c, d, e, f, g, h, i, j, k, l) j +# define SEQAN_PP_TUPLE_ELEM_12_10(a, b, c, d, e, f, g, h, i, j, k, l) k +# define SEQAN_PP_TUPLE_ELEM_12_11(a, b, c, d, e, f, g, h, i, j, k, l) l +# +# define SEQAN_PP_TUPLE_ELEM_13_0(a, b, c, d, e, f, g, h, i, j, k, l, m) a +# define SEQAN_PP_TUPLE_ELEM_13_1(a, b, c, d, e, f, g, h, i, j, k, l, m) b +# define SEQAN_PP_TUPLE_ELEM_13_2(a, b, c, d, e, f, g, h, i, j, k, l, m) c +# define SEQAN_PP_TUPLE_ELEM_13_3(a, b, c, d, e, f, g, h, i, j, k, l, m) d +# define SEQAN_PP_TUPLE_ELEM_13_4(a, b, c, d, e, f, g, h, i, j, k, l, m) e +# define SEQAN_PP_TUPLE_ELEM_13_5(a, b, c, d, e, f, g, h, i, j, k, l, m) f +# define SEQAN_PP_TUPLE_ELEM_13_6(a, b, c, d, e, f, g, h, i, j, k, l, m) g +# define SEQAN_PP_TUPLE_ELEM_13_7(a, b, c, d, e, f, g, h, i, j, k, l, m) h +# define SEQAN_PP_TUPLE_ELEM_13_8(a, b, c, d, e, f, g, h, i, j, k, l, m) i +# define SEQAN_PP_TUPLE_ELEM_13_9(a, b, c, d, e, f, g, h, i, j, k, l, m) j +# define SEQAN_PP_TUPLE_ELEM_13_10(a, b, c, d, e, f, g, h, i, j, k, l, m) k +# define SEQAN_PP_TUPLE_ELEM_13_11(a, b, c, d, e, f, g, h, i, j, k, l, m) l +# define SEQAN_PP_TUPLE_ELEM_13_12(a, b, c, d, e, f, g, h, i, j, k, l, m) m +# +# define SEQAN_PP_TUPLE_ELEM_14_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n) a +# define SEQAN_PP_TUPLE_ELEM_14_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n) b +# define SEQAN_PP_TUPLE_ELEM_14_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n) c +# define SEQAN_PP_TUPLE_ELEM_14_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n) d +# define SEQAN_PP_TUPLE_ELEM_14_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n) e +# define SEQAN_PP_TUPLE_ELEM_14_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n) f +# define SEQAN_PP_TUPLE_ELEM_14_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n) g +# define SEQAN_PP_TUPLE_ELEM_14_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n) h +# define SEQAN_PP_TUPLE_ELEM_14_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n) i +# define SEQAN_PP_TUPLE_ELEM_14_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n) j +# define SEQAN_PP_TUPLE_ELEM_14_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n) k +# define SEQAN_PP_TUPLE_ELEM_14_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n) l +# define SEQAN_PP_TUPLE_ELEM_14_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n) m +# define SEQAN_PP_TUPLE_ELEM_14_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n) n +# +# define SEQAN_PP_TUPLE_ELEM_15_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) a +# define SEQAN_PP_TUPLE_ELEM_15_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) b +# define SEQAN_PP_TUPLE_ELEM_15_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) c +# define SEQAN_PP_TUPLE_ELEM_15_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) d +# define SEQAN_PP_TUPLE_ELEM_15_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) e +# define SEQAN_PP_TUPLE_ELEM_15_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) f +# define SEQAN_PP_TUPLE_ELEM_15_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) g +# define SEQAN_PP_TUPLE_ELEM_15_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) h +# define SEQAN_PP_TUPLE_ELEM_15_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) i +# define SEQAN_PP_TUPLE_ELEM_15_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) j +# define SEQAN_PP_TUPLE_ELEM_15_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) k +# define SEQAN_PP_TUPLE_ELEM_15_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) l +# define SEQAN_PP_TUPLE_ELEM_15_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) m +# define SEQAN_PP_TUPLE_ELEM_15_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) n +# define SEQAN_PP_TUPLE_ELEM_15_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) o +# +# define SEQAN_PP_TUPLE_ELEM_16_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) a +# define SEQAN_PP_TUPLE_ELEM_16_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) b +# define SEQAN_PP_TUPLE_ELEM_16_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) c +# define SEQAN_PP_TUPLE_ELEM_16_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) d +# define SEQAN_PP_TUPLE_ELEM_16_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) e +# define SEQAN_PP_TUPLE_ELEM_16_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) f +# define SEQAN_PP_TUPLE_ELEM_16_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) g +# define SEQAN_PP_TUPLE_ELEM_16_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) h +# define SEQAN_PP_TUPLE_ELEM_16_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) i +# define SEQAN_PP_TUPLE_ELEM_16_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) j +# define SEQAN_PP_TUPLE_ELEM_16_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) k +# define SEQAN_PP_TUPLE_ELEM_16_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) l +# define SEQAN_PP_TUPLE_ELEM_16_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) m +# define SEQAN_PP_TUPLE_ELEM_16_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) n +# define SEQAN_PP_TUPLE_ELEM_16_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) o +# define SEQAN_PP_TUPLE_ELEM_16_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) p +# +# define SEQAN_PP_TUPLE_ELEM_17_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) a +# define SEQAN_PP_TUPLE_ELEM_17_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) b +# define SEQAN_PP_TUPLE_ELEM_17_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) c +# define SEQAN_PP_TUPLE_ELEM_17_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) d +# define SEQAN_PP_TUPLE_ELEM_17_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) e +# define SEQAN_PP_TUPLE_ELEM_17_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) f +# define SEQAN_PP_TUPLE_ELEM_17_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) g +# define SEQAN_PP_TUPLE_ELEM_17_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) h +# define SEQAN_PP_TUPLE_ELEM_17_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) i +# define SEQAN_PP_TUPLE_ELEM_17_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) j +# define SEQAN_PP_TUPLE_ELEM_17_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) k +# define SEQAN_PP_TUPLE_ELEM_17_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) l +# define SEQAN_PP_TUPLE_ELEM_17_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) m +# define SEQAN_PP_TUPLE_ELEM_17_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) n +# define SEQAN_PP_TUPLE_ELEM_17_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) o +# define SEQAN_PP_TUPLE_ELEM_17_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) p +# define SEQAN_PP_TUPLE_ELEM_17_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) q +# +# define SEQAN_PP_TUPLE_ELEM_18_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) a +# define SEQAN_PP_TUPLE_ELEM_18_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) b +# define SEQAN_PP_TUPLE_ELEM_18_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) c +# define SEQAN_PP_TUPLE_ELEM_18_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) d +# define SEQAN_PP_TUPLE_ELEM_18_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) e +# define SEQAN_PP_TUPLE_ELEM_18_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) f +# define SEQAN_PP_TUPLE_ELEM_18_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) g +# define SEQAN_PP_TUPLE_ELEM_18_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) h +# define SEQAN_PP_TUPLE_ELEM_18_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) i +# define SEQAN_PP_TUPLE_ELEM_18_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) j +# define SEQAN_PP_TUPLE_ELEM_18_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) k +# define SEQAN_PP_TUPLE_ELEM_18_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) l +# define SEQAN_PP_TUPLE_ELEM_18_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) m +# define SEQAN_PP_TUPLE_ELEM_18_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) n +# define SEQAN_PP_TUPLE_ELEM_18_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) o +# define SEQAN_PP_TUPLE_ELEM_18_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) p +# define SEQAN_PP_TUPLE_ELEM_18_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) q +# define SEQAN_PP_TUPLE_ELEM_18_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) r +# +# define SEQAN_PP_TUPLE_ELEM_19_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) a +# define SEQAN_PP_TUPLE_ELEM_19_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) b +# define SEQAN_PP_TUPLE_ELEM_19_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) c +# define SEQAN_PP_TUPLE_ELEM_19_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) d +# define SEQAN_PP_TUPLE_ELEM_19_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) e +# define SEQAN_PP_TUPLE_ELEM_19_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) f +# define SEQAN_PP_TUPLE_ELEM_19_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) g +# define SEQAN_PP_TUPLE_ELEM_19_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) h +# define SEQAN_PP_TUPLE_ELEM_19_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) i +# define SEQAN_PP_TUPLE_ELEM_19_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) j +# define SEQAN_PP_TUPLE_ELEM_19_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) k +# define SEQAN_PP_TUPLE_ELEM_19_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) l +# define SEQAN_PP_TUPLE_ELEM_19_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) m +# define SEQAN_PP_TUPLE_ELEM_19_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) n +# define SEQAN_PP_TUPLE_ELEM_19_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) o +# define SEQAN_PP_TUPLE_ELEM_19_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) p +# define SEQAN_PP_TUPLE_ELEM_19_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) q +# define SEQAN_PP_TUPLE_ELEM_19_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) r +# define SEQAN_PP_TUPLE_ELEM_19_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) s +# +# define SEQAN_PP_TUPLE_ELEM_20_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) a +# define SEQAN_PP_TUPLE_ELEM_20_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) b +# define SEQAN_PP_TUPLE_ELEM_20_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) c +# define SEQAN_PP_TUPLE_ELEM_20_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) d +# define SEQAN_PP_TUPLE_ELEM_20_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) e +# define SEQAN_PP_TUPLE_ELEM_20_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) f +# define SEQAN_PP_TUPLE_ELEM_20_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) g +# define SEQAN_PP_TUPLE_ELEM_20_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) h +# define SEQAN_PP_TUPLE_ELEM_20_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) i +# define SEQAN_PP_TUPLE_ELEM_20_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) j +# define SEQAN_PP_TUPLE_ELEM_20_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) k +# define SEQAN_PP_TUPLE_ELEM_20_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) l +# define SEQAN_PP_TUPLE_ELEM_20_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) m +# define SEQAN_PP_TUPLE_ELEM_20_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) n +# define SEQAN_PP_TUPLE_ELEM_20_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) o +# define SEQAN_PP_TUPLE_ELEM_20_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) p +# define SEQAN_PP_TUPLE_ELEM_20_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) q +# define SEQAN_PP_TUPLE_ELEM_20_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) r +# define SEQAN_PP_TUPLE_ELEM_20_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) s +# define SEQAN_PP_TUPLE_ELEM_20_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) t +# +# define SEQAN_PP_TUPLE_ELEM_21_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) a +# define SEQAN_PP_TUPLE_ELEM_21_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) b +# define SEQAN_PP_TUPLE_ELEM_21_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) c +# define SEQAN_PP_TUPLE_ELEM_21_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) d +# define SEQAN_PP_TUPLE_ELEM_21_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) e +# define SEQAN_PP_TUPLE_ELEM_21_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) f +# define SEQAN_PP_TUPLE_ELEM_21_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) g +# define SEQAN_PP_TUPLE_ELEM_21_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) h +# define SEQAN_PP_TUPLE_ELEM_21_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) i +# define SEQAN_PP_TUPLE_ELEM_21_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) j +# define SEQAN_PP_TUPLE_ELEM_21_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) k +# define SEQAN_PP_TUPLE_ELEM_21_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) l +# define SEQAN_PP_TUPLE_ELEM_21_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) m +# define SEQAN_PP_TUPLE_ELEM_21_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) n +# define SEQAN_PP_TUPLE_ELEM_21_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) o +# define SEQAN_PP_TUPLE_ELEM_21_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) p +# define SEQAN_PP_TUPLE_ELEM_21_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) q +# define SEQAN_PP_TUPLE_ELEM_21_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) r +# define SEQAN_PP_TUPLE_ELEM_21_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) s +# define SEQAN_PP_TUPLE_ELEM_21_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) t +# define SEQAN_PP_TUPLE_ELEM_21_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) u +# +# define SEQAN_PP_TUPLE_ELEM_22_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) a +# define SEQAN_PP_TUPLE_ELEM_22_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) b +# define SEQAN_PP_TUPLE_ELEM_22_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) c +# define SEQAN_PP_TUPLE_ELEM_22_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) d +# define SEQAN_PP_TUPLE_ELEM_22_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) e +# define SEQAN_PP_TUPLE_ELEM_22_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) f +# define SEQAN_PP_TUPLE_ELEM_22_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) g +# define SEQAN_PP_TUPLE_ELEM_22_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) h +# define SEQAN_PP_TUPLE_ELEM_22_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) i +# define SEQAN_PP_TUPLE_ELEM_22_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) j +# define SEQAN_PP_TUPLE_ELEM_22_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) k +# define SEQAN_PP_TUPLE_ELEM_22_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) l +# define SEQAN_PP_TUPLE_ELEM_22_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) m +# define SEQAN_PP_TUPLE_ELEM_22_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) n +# define SEQAN_PP_TUPLE_ELEM_22_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) o +# define SEQAN_PP_TUPLE_ELEM_22_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) p +# define SEQAN_PP_TUPLE_ELEM_22_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) q +# define SEQAN_PP_TUPLE_ELEM_22_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) r +# define SEQAN_PP_TUPLE_ELEM_22_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) s +# define SEQAN_PP_TUPLE_ELEM_22_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) t +# define SEQAN_PP_TUPLE_ELEM_22_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) u +# define SEQAN_PP_TUPLE_ELEM_22_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) v +# +# define SEQAN_PP_TUPLE_ELEM_23_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) a +# define SEQAN_PP_TUPLE_ELEM_23_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) b +# define SEQAN_PP_TUPLE_ELEM_23_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) c +# define SEQAN_PP_TUPLE_ELEM_23_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) d +# define SEQAN_PP_TUPLE_ELEM_23_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) e +# define SEQAN_PP_TUPLE_ELEM_23_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) f +# define SEQAN_PP_TUPLE_ELEM_23_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) g +# define SEQAN_PP_TUPLE_ELEM_23_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) h +# define SEQAN_PP_TUPLE_ELEM_23_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) i +# define SEQAN_PP_TUPLE_ELEM_23_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) j +# define SEQAN_PP_TUPLE_ELEM_23_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) k +# define SEQAN_PP_TUPLE_ELEM_23_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) l +# define SEQAN_PP_TUPLE_ELEM_23_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) m +# define SEQAN_PP_TUPLE_ELEM_23_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) n +# define SEQAN_PP_TUPLE_ELEM_23_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) o +# define SEQAN_PP_TUPLE_ELEM_23_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) p +# define SEQAN_PP_TUPLE_ELEM_23_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) q +# define SEQAN_PP_TUPLE_ELEM_23_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) r +# define SEQAN_PP_TUPLE_ELEM_23_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) s +# define SEQAN_PP_TUPLE_ELEM_23_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) t +# define SEQAN_PP_TUPLE_ELEM_23_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) u +# define SEQAN_PP_TUPLE_ELEM_23_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) v +# define SEQAN_PP_TUPLE_ELEM_23_22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) w +# +# define SEQAN_PP_TUPLE_ELEM_24_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) a +# define SEQAN_PP_TUPLE_ELEM_24_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) b +# define SEQAN_PP_TUPLE_ELEM_24_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) c +# define SEQAN_PP_TUPLE_ELEM_24_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) d +# define SEQAN_PP_TUPLE_ELEM_24_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) e +# define SEQAN_PP_TUPLE_ELEM_24_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) f +# define SEQAN_PP_TUPLE_ELEM_24_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) g +# define SEQAN_PP_TUPLE_ELEM_24_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) h +# define SEQAN_PP_TUPLE_ELEM_24_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) i +# define SEQAN_PP_TUPLE_ELEM_24_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) j +# define SEQAN_PP_TUPLE_ELEM_24_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) k +# define SEQAN_PP_TUPLE_ELEM_24_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) l +# define SEQAN_PP_TUPLE_ELEM_24_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) m +# define SEQAN_PP_TUPLE_ELEM_24_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) n +# define SEQAN_PP_TUPLE_ELEM_24_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) o +# define SEQAN_PP_TUPLE_ELEM_24_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) p +# define SEQAN_PP_TUPLE_ELEM_24_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) q +# define SEQAN_PP_TUPLE_ELEM_24_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) r +# define SEQAN_PP_TUPLE_ELEM_24_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) s +# define SEQAN_PP_TUPLE_ELEM_24_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) t +# define SEQAN_PP_TUPLE_ELEM_24_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) u +# define SEQAN_PP_TUPLE_ELEM_24_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) v +# define SEQAN_PP_TUPLE_ELEM_24_22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) w +# define SEQAN_PP_TUPLE_ELEM_24_23(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) x +# +# define SEQAN_PP_TUPLE_ELEM_25_0(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) a +# define SEQAN_PP_TUPLE_ELEM_25_1(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) b +# define SEQAN_PP_TUPLE_ELEM_25_2(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) c +# define SEQAN_PP_TUPLE_ELEM_25_3(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) d +# define SEQAN_PP_TUPLE_ELEM_25_4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) e +# define SEQAN_PP_TUPLE_ELEM_25_5(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) f +# define SEQAN_PP_TUPLE_ELEM_25_6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) g +# define SEQAN_PP_TUPLE_ELEM_25_7(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) h +# define SEQAN_PP_TUPLE_ELEM_25_8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) i +# define SEQAN_PP_TUPLE_ELEM_25_9(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) j +# define SEQAN_PP_TUPLE_ELEM_25_10(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) k +# define SEQAN_PP_TUPLE_ELEM_25_11(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) l +# define SEQAN_PP_TUPLE_ELEM_25_12(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) m +# define SEQAN_PP_TUPLE_ELEM_25_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) n +# define SEQAN_PP_TUPLE_ELEM_25_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) o +# define SEQAN_PP_TUPLE_ELEM_25_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) p +# define SEQAN_PP_TUPLE_ELEM_25_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) q +# define SEQAN_PP_TUPLE_ELEM_25_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) r +# define SEQAN_PP_TUPLE_ELEM_25_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) s +# define SEQAN_PP_TUPLE_ELEM_25_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) t +# define SEQAN_PP_TUPLE_ELEM_25_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) u +# define SEQAN_PP_TUPLE_ELEM_25_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) v +# define SEQAN_PP_TUPLE_ELEM_25_22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) w +# define SEQAN_PP_TUPLE_ELEM_25_23(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) x +# define SEQAN_PP_TUPLE_ELEM_25_24(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) y + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/seq/size.hpp <== +// -------------------------------------------------------------------------- + +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_SEQ_SIZE_HPP +// # define SEQAN_PREPROCESSOR_SEQ_SIZE_HPP +# +// # include +// # include +# +// # if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +// # define SEQAN_PP_SEQ_SIZE(seq) SEQAN_PP_SEQ_SIZE_I((seq)) +// # define SEQAN_PP_SEQ_SIZE_I(par) SEQAN_PP_SEQ_SIZE_II ## par +// # define SEQAN_PP_SEQ_SIZE_II(seq) SEQAN_PP_CAT(SEQAN_PP_SEQ_SIZE_, SEQAN_PP_SEQ_SIZE_0 ## seq) +// # elif SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() || SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MSVC() +#ifdef STDLIB_VS +# define SEQAN_PP_SEQ_SIZE(seq) SEQAN_PP_SEQ_SIZE_I(seq) +# define SEQAN_PP_SEQ_SIZE_I(seq) SEQAN_PP_CAT(SEQAN_PP_SEQ_SIZE_, SEQAN_PP_SEQ_SIZE_0 seq) +#else // #ifdef STDLIB_VS +// # elif defined(__IBMC__) || defined(__IBMCPP__) +// # define SEQAN_PP_SEQ_SIZE(seq) SEQAN_PP_CAT(SEQAN_PP_SEQ_SIZE_, SEQAN_PP_CAT(SEQAN_PP_SEQ_SIZE_0, seq)) +// # else +# define SEQAN_PP_SEQ_SIZE(seq) SEQAN_PP_CAT(SEQAN_PP_SEQ_SIZE_, SEQAN_PP_SEQ_SIZE_0 seq) +#endif // #ifdef STDLIB_VS + +# define SEQAN_PP_SEQ_SIZE_0(_) SEQAN_PP_SEQ_SIZE_1 +# define SEQAN_PP_SEQ_SIZE_1(_) SEQAN_PP_SEQ_SIZE_2 +# define SEQAN_PP_SEQ_SIZE_2(_) SEQAN_PP_SEQ_SIZE_3 +# define SEQAN_PP_SEQ_SIZE_3(_) SEQAN_PP_SEQ_SIZE_4 +# define SEQAN_PP_SEQ_SIZE_4(_) SEQAN_PP_SEQ_SIZE_5 +# define SEQAN_PP_SEQ_SIZE_5(_) SEQAN_PP_SEQ_SIZE_6 +# define SEQAN_PP_SEQ_SIZE_6(_) SEQAN_PP_SEQ_SIZE_7 +# define SEQAN_PP_SEQ_SIZE_7(_) SEQAN_PP_SEQ_SIZE_8 +# define SEQAN_PP_SEQ_SIZE_8(_) SEQAN_PP_SEQ_SIZE_9 +# define SEQAN_PP_SEQ_SIZE_9(_) SEQAN_PP_SEQ_SIZE_10 +# define SEQAN_PP_SEQ_SIZE_10(_) SEQAN_PP_SEQ_SIZE_11 +# define SEQAN_PP_SEQ_SIZE_11(_) SEQAN_PP_SEQ_SIZE_12 +# define SEQAN_PP_SEQ_SIZE_12(_) SEQAN_PP_SEQ_SIZE_13 +# define SEQAN_PP_SEQ_SIZE_13(_) SEQAN_PP_SEQ_SIZE_14 +# define SEQAN_PP_SEQ_SIZE_14(_) SEQAN_PP_SEQ_SIZE_15 +# define SEQAN_PP_SEQ_SIZE_15(_) SEQAN_PP_SEQ_SIZE_16 +# define SEQAN_PP_SEQ_SIZE_16(_) SEQAN_PP_SEQ_SIZE_17 +# define SEQAN_PP_SEQ_SIZE_17(_) SEQAN_PP_SEQ_SIZE_18 +# define SEQAN_PP_SEQ_SIZE_18(_) SEQAN_PP_SEQ_SIZE_19 +# define SEQAN_PP_SEQ_SIZE_19(_) SEQAN_PP_SEQ_SIZE_20 +# define SEQAN_PP_SEQ_SIZE_20(_) SEQAN_PP_SEQ_SIZE_21 +# define SEQAN_PP_SEQ_SIZE_21(_) SEQAN_PP_SEQ_SIZE_22 +# define SEQAN_PP_SEQ_SIZE_22(_) SEQAN_PP_SEQ_SIZE_23 +# define SEQAN_PP_SEQ_SIZE_23(_) SEQAN_PP_SEQ_SIZE_24 +# define SEQAN_PP_SEQ_SIZE_24(_) SEQAN_PP_SEQ_SIZE_25 +# define SEQAN_PP_SEQ_SIZE_25(_) SEQAN_PP_SEQ_SIZE_26 +# define SEQAN_PP_SEQ_SIZE_26(_) SEQAN_PP_SEQ_SIZE_27 +# define SEQAN_PP_SEQ_SIZE_27(_) SEQAN_PP_SEQ_SIZE_28 +# define SEQAN_PP_SEQ_SIZE_28(_) SEQAN_PP_SEQ_SIZE_29 +# define SEQAN_PP_SEQ_SIZE_29(_) SEQAN_PP_SEQ_SIZE_30 +# define SEQAN_PP_SEQ_SIZE_30(_) SEQAN_PP_SEQ_SIZE_31 +# define SEQAN_PP_SEQ_SIZE_31(_) SEQAN_PP_SEQ_SIZE_32 +# define SEQAN_PP_SEQ_SIZE_32(_) SEQAN_PP_SEQ_SIZE_33 +# define SEQAN_PP_SEQ_SIZE_33(_) SEQAN_PP_SEQ_SIZE_34 +# define SEQAN_PP_SEQ_SIZE_34(_) SEQAN_PP_SEQ_SIZE_35 +# define SEQAN_PP_SEQ_SIZE_35(_) SEQAN_PP_SEQ_SIZE_36 +# define SEQAN_PP_SEQ_SIZE_36(_) SEQAN_PP_SEQ_SIZE_37 +# define SEQAN_PP_SEQ_SIZE_37(_) SEQAN_PP_SEQ_SIZE_38 +# define SEQAN_PP_SEQ_SIZE_38(_) SEQAN_PP_SEQ_SIZE_39 +# define SEQAN_PP_SEQ_SIZE_39(_) SEQAN_PP_SEQ_SIZE_40 +# define SEQAN_PP_SEQ_SIZE_40(_) SEQAN_PP_SEQ_SIZE_41 +# define SEQAN_PP_SEQ_SIZE_41(_) SEQAN_PP_SEQ_SIZE_42 +# define SEQAN_PP_SEQ_SIZE_42(_) SEQAN_PP_SEQ_SIZE_43 +# define SEQAN_PP_SEQ_SIZE_43(_) SEQAN_PP_SEQ_SIZE_44 +# define SEQAN_PP_SEQ_SIZE_44(_) SEQAN_PP_SEQ_SIZE_45 +# define SEQAN_PP_SEQ_SIZE_45(_) SEQAN_PP_SEQ_SIZE_46 +# define SEQAN_PP_SEQ_SIZE_46(_) SEQAN_PP_SEQ_SIZE_47 +# define SEQAN_PP_SEQ_SIZE_47(_) SEQAN_PP_SEQ_SIZE_48 +# define SEQAN_PP_SEQ_SIZE_48(_) SEQAN_PP_SEQ_SIZE_49 +# define SEQAN_PP_SEQ_SIZE_49(_) SEQAN_PP_SEQ_SIZE_50 +# define SEQAN_PP_SEQ_SIZE_50(_) SEQAN_PP_SEQ_SIZE_51 +# define SEQAN_PP_SEQ_SIZE_51(_) SEQAN_PP_SEQ_SIZE_52 +# define SEQAN_PP_SEQ_SIZE_52(_) SEQAN_PP_SEQ_SIZE_53 +# define SEQAN_PP_SEQ_SIZE_53(_) SEQAN_PP_SEQ_SIZE_54 +# define SEQAN_PP_SEQ_SIZE_54(_) SEQAN_PP_SEQ_SIZE_55 +# define SEQAN_PP_SEQ_SIZE_55(_) SEQAN_PP_SEQ_SIZE_56 +# define SEQAN_PP_SEQ_SIZE_56(_) SEQAN_PP_SEQ_SIZE_57 +# define SEQAN_PP_SEQ_SIZE_57(_) SEQAN_PP_SEQ_SIZE_58 +# define SEQAN_PP_SEQ_SIZE_58(_) SEQAN_PP_SEQ_SIZE_59 +# define SEQAN_PP_SEQ_SIZE_59(_) SEQAN_PP_SEQ_SIZE_60 +# define SEQAN_PP_SEQ_SIZE_60(_) SEQAN_PP_SEQ_SIZE_61 +# define SEQAN_PP_SEQ_SIZE_61(_) SEQAN_PP_SEQ_SIZE_62 +# define SEQAN_PP_SEQ_SIZE_62(_) SEQAN_PP_SEQ_SIZE_63 +# define SEQAN_PP_SEQ_SIZE_63(_) SEQAN_PP_SEQ_SIZE_64 +# define SEQAN_PP_SEQ_SIZE_64(_) SEQAN_PP_SEQ_SIZE_65 +# define SEQAN_PP_SEQ_SIZE_65(_) SEQAN_PP_SEQ_SIZE_66 +# define SEQAN_PP_SEQ_SIZE_66(_) SEQAN_PP_SEQ_SIZE_67 +# define SEQAN_PP_SEQ_SIZE_67(_) SEQAN_PP_SEQ_SIZE_68 +# define SEQAN_PP_SEQ_SIZE_68(_) SEQAN_PP_SEQ_SIZE_69 +# define SEQAN_PP_SEQ_SIZE_69(_) SEQAN_PP_SEQ_SIZE_70 +# define SEQAN_PP_SEQ_SIZE_70(_) SEQAN_PP_SEQ_SIZE_71 +# define SEQAN_PP_SEQ_SIZE_71(_) SEQAN_PP_SEQ_SIZE_72 +# define SEQAN_PP_SEQ_SIZE_72(_) SEQAN_PP_SEQ_SIZE_73 +# define SEQAN_PP_SEQ_SIZE_73(_) SEQAN_PP_SEQ_SIZE_74 +# define SEQAN_PP_SEQ_SIZE_74(_) SEQAN_PP_SEQ_SIZE_75 +# define SEQAN_PP_SEQ_SIZE_75(_) SEQAN_PP_SEQ_SIZE_76 +# define SEQAN_PP_SEQ_SIZE_76(_) SEQAN_PP_SEQ_SIZE_77 +# define SEQAN_PP_SEQ_SIZE_77(_) SEQAN_PP_SEQ_SIZE_78 +# define SEQAN_PP_SEQ_SIZE_78(_) SEQAN_PP_SEQ_SIZE_79 +# define SEQAN_PP_SEQ_SIZE_79(_) SEQAN_PP_SEQ_SIZE_80 +# define SEQAN_PP_SEQ_SIZE_80(_) SEQAN_PP_SEQ_SIZE_81 +# define SEQAN_PP_SEQ_SIZE_81(_) SEQAN_PP_SEQ_SIZE_82 +# define SEQAN_PP_SEQ_SIZE_82(_) SEQAN_PP_SEQ_SIZE_83 +# define SEQAN_PP_SEQ_SIZE_83(_) SEQAN_PP_SEQ_SIZE_84 +# define SEQAN_PP_SEQ_SIZE_84(_) SEQAN_PP_SEQ_SIZE_85 +# define SEQAN_PP_SEQ_SIZE_85(_) SEQAN_PP_SEQ_SIZE_86 +# define SEQAN_PP_SEQ_SIZE_86(_) SEQAN_PP_SEQ_SIZE_87 +# define SEQAN_PP_SEQ_SIZE_87(_) SEQAN_PP_SEQ_SIZE_88 +# define SEQAN_PP_SEQ_SIZE_88(_) SEQAN_PP_SEQ_SIZE_89 +# define SEQAN_PP_SEQ_SIZE_89(_) SEQAN_PP_SEQ_SIZE_90 +# define SEQAN_PP_SEQ_SIZE_90(_) SEQAN_PP_SEQ_SIZE_91 +# define SEQAN_PP_SEQ_SIZE_91(_) SEQAN_PP_SEQ_SIZE_92 +# define SEQAN_PP_SEQ_SIZE_92(_) SEQAN_PP_SEQ_SIZE_93 +# define SEQAN_PP_SEQ_SIZE_93(_) SEQAN_PP_SEQ_SIZE_94 +# define SEQAN_PP_SEQ_SIZE_94(_) SEQAN_PP_SEQ_SIZE_95 +# define SEQAN_PP_SEQ_SIZE_95(_) SEQAN_PP_SEQ_SIZE_96 +# define SEQAN_PP_SEQ_SIZE_96(_) SEQAN_PP_SEQ_SIZE_97 +# define SEQAN_PP_SEQ_SIZE_97(_) SEQAN_PP_SEQ_SIZE_98 +# define SEQAN_PP_SEQ_SIZE_98(_) SEQAN_PP_SEQ_SIZE_99 +# define SEQAN_PP_SEQ_SIZE_99(_) SEQAN_PP_SEQ_SIZE_100 +# define SEQAN_PP_SEQ_SIZE_100(_) SEQAN_PP_SEQ_SIZE_101 +# define SEQAN_PP_SEQ_SIZE_101(_) SEQAN_PP_SEQ_SIZE_102 +# define SEQAN_PP_SEQ_SIZE_102(_) SEQAN_PP_SEQ_SIZE_103 +# define SEQAN_PP_SEQ_SIZE_103(_) SEQAN_PP_SEQ_SIZE_104 +# define SEQAN_PP_SEQ_SIZE_104(_) SEQAN_PP_SEQ_SIZE_105 +# define SEQAN_PP_SEQ_SIZE_105(_) SEQAN_PP_SEQ_SIZE_106 +# define SEQAN_PP_SEQ_SIZE_106(_) SEQAN_PP_SEQ_SIZE_107 +# define SEQAN_PP_SEQ_SIZE_107(_) SEQAN_PP_SEQ_SIZE_108 +# define SEQAN_PP_SEQ_SIZE_108(_) SEQAN_PP_SEQ_SIZE_109 +# define SEQAN_PP_SEQ_SIZE_109(_) SEQAN_PP_SEQ_SIZE_110 +# define SEQAN_PP_SEQ_SIZE_110(_) SEQAN_PP_SEQ_SIZE_111 +# define SEQAN_PP_SEQ_SIZE_111(_) SEQAN_PP_SEQ_SIZE_112 +# define SEQAN_PP_SEQ_SIZE_112(_) SEQAN_PP_SEQ_SIZE_113 +# define SEQAN_PP_SEQ_SIZE_113(_) SEQAN_PP_SEQ_SIZE_114 +# define SEQAN_PP_SEQ_SIZE_114(_) SEQAN_PP_SEQ_SIZE_115 +# define SEQAN_PP_SEQ_SIZE_115(_) SEQAN_PP_SEQ_SIZE_116 +# define SEQAN_PP_SEQ_SIZE_116(_) SEQAN_PP_SEQ_SIZE_117 +# define SEQAN_PP_SEQ_SIZE_117(_) SEQAN_PP_SEQ_SIZE_118 +# define SEQAN_PP_SEQ_SIZE_118(_) SEQAN_PP_SEQ_SIZE_119 +# define SEQAN_PP_SEQ_SIZE_119(_) SEQAN_PP_SEQ_SIZE_120 +# define SEQAN_PP_SEQ_SIZE_120(_) SEQAN_PP_SEQ_SIZE_121 +# define SEQAN_PP_SEQ_SIZE_121(_) SEQAN_PP_SEQ_SIZE_122 +# define SEQAN_PP_SEQ_SIZE_122(_) SEQAN_PP_SEQ_SIZE_123 +# define SEQAN_PP_SEQ_SIZE_123(_) SEQAN_PP_SEQ_SIZE_124 +# define SEQAN_PP_SEQ_SIZE_124(_) SEQAN_PP_SEQ_SIZE_125 +# define SEQAN_PP_SEQ_SIZE_125(_) SEQAN_PP_SEQ_SIZE_126 +# define SEQAN_PP_SEQ_SIZE_126(_) SEQAN_PP_SEQ_SIZE_127 +# define SEQAN_PP_SEQ_SIZE_127(_) SEQAN_PP_SEQ_SIZE_128 +# define SEQAN_PP_SEQ_SIZE_128(_) SEQAN_PP_SEQ_SIZE_129 +# define SEQAN_PP_SEQ_SIZE_129(_) SEQAN_PP_SEQ_SIZE_130 +# define SEQAN_PP_SEQ_SIZE_130(_) SEQAN_PP_SEQ_SIZE_131 +# define SEQAN_PP_SEQ_SIZE_131(_) SEQAN_PP_SEQ_SIZE_132 +# define SEQAN_PP_SEQ_SIZE_132(_) SEQAN_PP_SEQ_SIZE_133 +# define SEQAN_PP_SEQ_SIZE_133(_) SEQAN_PP_SEQ_SIZE_134 +# define SEQAN_PP_SEQ_SIZE_134(_) SEQAN_PP_SEQ_SIZE_135 +# define SEQAN_PP_SEQ_SIZE_135(_) SEQAN_PP_SEQ_SIZE_136 +# define SEQAN_PP_SEQ_SIZE_136(_) SEQAN_PP_SEQ_SIZE_137 +# define SEQAN_PP_SEQ_SIZE_137(_) SEQAN_PP_SEQ_SIZE_138 +# define SEQAN_PP_SEQ_SIZE_138(_) SEQAN_PP_SEQ_SIZE_139 +# define SEQAN_PP_SEQ_SIZE_139(_) SEQAN_PP_SEQ_SIZE_140 +# define SEQAN_PP_SEQ_SIZE_140(_) SEQAN_PP_SEQ_SIZE_141 +# define SEQAN_PP_SEQ_SIZE_141(_) SEQAN_PP_SEQ_SIZE_142 +# define SEQAN_PP_SEQ_SIZE_142(_) SEQAN_PP_SEQ_SIZE_143 +# define SEQAN_PP_SEQ_SIZE_143(_) SEQAN_PP_SEQ_SIZE_144 +# define SEQAN_PP_SEQ_SIZE_144(_) SEQAN_PP_SEQ_SIZE_145 +# define SEQAN_PP_SEQ_SIZE_145(_) SEQAN_PP_SEQ_SIZE_146 +# define SEQAN_PP_SEQ_SIZE_146(_) SEQAN_PP_SEQ_SIZE_147 +# define SEQAN_PP_SEQ_SIZE_147(_) SEQAN_PP_SEQ_SIZE_148 +# define SEQAN_PP_SEQ_SIZE_148(_) SEQAN_PP_SEQ_SIZE_149 +# define SEQAN_PP_SEQ_SIZE_149(_) SEQAN_PP_SEQ_SIZE_150 +# define SEQAN_PP_SEQ_SIZE_150(_) SEQAN_PP_SEQ_SIZE_151 +# define SEQAN_PP_SEQ_SIZE_151(_) SEQAN_PP_SEQ_SIZE_152 +# define SEQAN_PP_SEQ_SIZE_152(_) SEQAN_PP_SEQ_SIZE_153 +# define SEQAN_PP_SEQ_SIZE_153(_) SEQAN_PP_SEQ_SIZE_154 +# define SEQAN_PP_SEQ_SIZE_154(_) SEQAN_PP_SEQ_SIZE_155 +# define SEQAN_PP_SEQ_SIZE_155(_) SEQAN_PP_SEQ_SIZE_156 +# define SEQAN_PP_SEQ_SIZE_156(_) SEQAN_PP_SEQ_SIZE_157 +# define SEQAN_PP_SEQ_SIZE_157(_) SEQAN_PP_SEQ_SIZE_158 +# define SEQAN_PP_SEQ_SIZE_158(_) SEQAN_PP_SEQ_SIZE_159 +# define SEQAN_PP_SEQ_SIZE_159(_) SEQAN_PP_SEQ_SIZE_160 +# define SEQAN_PP_SEQ_SIZE_160(_) SEQAN_PP_SEQ_SIZE_161 +# define SEQAN_PP_SEQ_SIZE_161(_) SEQAN_PP_SEQ_SIZE_162 +# define SEQAN_PP_SEQ_SIZE_162(_) SEQAN_PP_SEQ_SIZE_163 +# define SEQAN_PP_SEQ_SIZE_163(_) SEQAN_PP_SEQ_SIZE_164 +# define SEQAN_PP_SEQ_SIZE_164(_) SEQAN_PP_SEQ_SIZE_165 +# define SEQAN_PP_SEQ_SIZE_165(_) SEQAN_PP_SEQ_SIZE_166 +# define SEQAN_PP_SEQ_SIZE_166(_) SEQAN_PP_SEQ_SIZE_167 +# define SEQAN_PP_SEQ_SIZE_167(_) SEQAN_PP_SEQ_SIZE_168 +# define SEQAN_PP_SEQ_SIZE_168(_) SEQAN_PP_SEQ_SIZE_169 +# define SEQAN_PP_SEQ_SIZE_169(_) SEQAN_PP_SEQ_SIZE_170 +# define SEQAN_PP_SEQ_SIZE_170(_) SEQAN_PP_SEQ_SIZE_171 +# define SEQAN_PP_SEQ_SIZE_171(_) SEQAN_PP_SEQ_SIZE_172 +# define SEQAN_PP_SEQ_SIZE_172(_) SEQAN_PP_SEQ_SIZE_173 +# define SEQAN_PP_SEQ_SIZE_173(_) SEQAN_PP_SEQ_SIZE_174 +# define SEQAN_PP_SEQ_SIZE_174(_) SEQAN_PP_SEQ_SIZE_175 +# define SEQAN_PP_SEQ_SIZE_175(_) SEQAN_PP_SEQ_SIZE_176 +# define SEQAN_PP_SEQ_SIZE_176(_) SEQAN_PP_SEQ_SIZE_177 +# define SEQAN_PP_SEQ_SIZE_177(_) SEQAN_PP_SEQ_SIZE_178 +# define SEQAN_PP_SEQ_SIZE_178(_) SEQAN_PP_SEQ_SIZE_179 +# define SEQAN_PP_SEQ_SIZE_179(_) SEQAN_PP_SEQ_SIZE_180 +# define SEQAN_PP_SEQ_SIZE_180(_) SEQAN_PP_SEQ_SIZE_181 +# define SEQAN_PP_SEQ_SIZE_181(_) SEQAN_PP_SEQ_SIZE_182 +# define SEQAN_PP_SEQ_SIZE_182(_) SEQAN_PP_SEQ_SIZE_183 +# define SEQAN_PP_SEQ_SIZE_183(_) SEQAN_PP_SEQ_SIZE_184 +# define SEQAN_PP_SEQ_SIZE_184(_) SEQAN_PP_SEQ_SIZE_185 +# define SEQAN_PP_SEQ_SIZE_185(_) SEQAN_PP_SEQ_SIZE_186 +# define SEQAN_PP_SEQ_SIZE_186(_) SEQAN_PP_SEQ_SIZE_187 +# define SEQAN_PP_SEQ_SIZE_187(_) SEQAN_PP_SEQ_SIZE_188 +# define SEQAN_PP_SEQ_SIZE_188(_) SEQAN_PP_SEQ_SIZE_189 +# define SEQAN_PP_SEQ_SIZE_189(_) SEQAN_PP_SEQ_SIZE_190 +# define SEQAN_PP_SEQ_SIZE_190(_) SEQAN_PP_SEQ_SIZE_191 +# define SEQAN_PP_SEQ_SIZE_191(_) SEQAN_PP_SEQ_SIZE_192 +# define SEQAN_PP_SEQ_SIZE_192(_) SEQAN_PP_SEQ_SIZE_193 +# define SEQAN_PP_SEQ_SIZE_193(_) SEQAN_PP_SEQ_SIZE_194 +# define SEQAN_PP_SEQ_SIZE_194(_) SEQAN_PP_SEQ_SIZE_195 +# define SEQAN_PP_SEQ_SIZE_195(_) SEQAN_PP_SEQ_SIZE_196 +# define SEQAN_PP_SEQ_SIZE_196(_) SEQAN_PP_SEQ_SIZE_197 +# define SEQAN_PP_SEQ_SIZE_197(_) SEQAN_PP_SEQ_SIZE_198 +# define SEQAN_PP_SEQ_SIZE_198(_) SEQAN_PP_SEQ_SIZE_199 +# define SEQAN_PP_SEQ_SIZE_199(_) SEQAN_PP_SEQ_SIZE_200 +# define SEQAN_PP_SEQ_SIZE_200(_) SEQAN_PP_SEQ_SIZE_201 +# define SEQAN_PP_SEQ_SIZE_201(_) SEQAN_PP_SEQ_SIZE_202 +# define SEQAN_PP_SEQ_SIZE_202(_) SEQAN_PP_SEQ_SIZE_203 +# define SEQAN_PP_SEQ_SIZE_203(_) SEQAN_PP_SEQ_SIZE_204 +# define SEQAN_PP_SEQ_SIZE_204(_) SEQAN_PP_SEQ_SIZE_205 +# define SEQAN_PP_SEQ_SIZE_205(_) SEQAN_PP_SEQ_SIZE_206 +# define SEQAN_PP_SEQ_SIZE_206(_) SEQAN_PP_SEQ_SIZE_207 +# define SEQAN_PP_SEQ_SIZE_207(_) SEQAN_PP_SEQ_SIZE_208 +# define SEQAN_PP_SEQ_SIZE_208(_) SEQAN_PP_SEQ_SIZE_209 +# define SEQAN_PP_SEQ_SIZE_209(_) SEQAN_PP_SEQ_SIZE_210 +# define SEQAN_PP_SEQ_SIZE_210(_) SEQAN_PP_SEQ_SIZE_211 +# define SEQAN_PP_SEQ_SIZE_211(_) SEQAN_PP_SEQ_SIZE_212 +# define SEQAN_PP_SEQ_SIZE_212(_) SEQAN_PP_SEQ_SIZE_213 +# define SEQAN_PP_SEQ_SIZE_213(_) SEQAN_PP_SEQ_SIZE_214 +# define SEQAN_PP_SEQ_SIZE_214(_) SEQAN_PP_SEQ_SIZE_215 +# define SEQAN_PP_SEQ_SIZE_215(_) SEQAN_PP_SEQ_SIZE_216 +# define SEQAN_PP_SEQ_SIZE_216(_) SEQAN_PP_SEQ_SIZE_217 +# define SEQAN_PP_SEQ_SIZE_217(_) SEQAN_PP_SEQ_SIZE_218 +# define SEQAN_PP_SEQ_SIZE_218(_) SEQAN_PP_SEQ_SIZE_219 +# define SEQAN_PP_SEQ_SIZE_219(_) SEQAN_PP_SEQ_SIZE_220 +# define SEQAN_PP_SEQ_SIZE_220(_) SEQAN_PP_SEQ_SIZE_221 +# define SEQAN_PP_SEQ_SIZE_221(_) SEQAN_PP_SEQ_SIZE_222 +# define SEQAN_PP_SEQ_SIZE_222(_) SEQAN_PP_SEQ_SIZE_223 +# define SEQAN_PP_SEQ_SIZE_223(_) SEQAN_PP_SEQ_SIZE_224 +# define SEQAN_PP_SEQ_SIZE_224(_) SEQAN_PP_SEQ_SIZE_225 +# define SEQAN_PP_SEQ_SIZE_225(_) SEQAN_PP_SEQ_SIZE_226 +# define SEQAN_PP_SEQ_SIZE_226(_) SEQAN_PP_SEQ_SIZE_227 +# define SEQAN_PP_SEQ_SIZE_227(_) SEQAN_PP_SEQ_SIZE_228 +# define SEQAN_PP_SEQ_SIZE_228(_) SEQAN_PP_SEQ_SIZE_229 +# define SEQAN_PP_SEQ_SIZE_229(_) SEQAN_PP_SEQ_SIZE_230 +# define SEQAN_PP_SEQ_SIZE_230(_) SEQAN_PP_SEQ_SIZE_231 +# define SEQAN_PP_SEQ_SIZE_231(_) SEQAN_PP_SEQ_SIZE_232 +# define SEQAN_PP_SEQ_SIZE_232(_) SEQAN_PP_SEQ_SIZE_233 +# define SEQAN_PP_SEQ_SIZE_233(_) SEQAN_PP_SEQ_SIZE_234 +# define SEQAN_PP_SEQ_SIZE_234(_) SEQAN_PP_SEQ_SIZE_235 +# define SEQAN_PP_SEQ_SIZE_235(_) SEQAN_PP_SEQ_SIZE_236 +# define SEQAN_PP_SEQ_SIZE_236(_) SEQAN_PP_SEQ_SIZE_237 +# define SEQAN_PP_SEQ_SIZE_237(_) SEQAN_PP_SEQ_SIZE_238 +# define SEQAN_PP_SEQ_SIZE_238(_) SEQAN_PP_SEQ_SIZE_239 +# define SEQAN_PP_SEQ_SIZE_239(_) SEQAN_PP_SEQ_SIZE_240 +# define SEQAN_PP_SEQ_SIZE_240(_) SEQAN_PP_SEQ_SIZE_241 +# define SEQAN_PP_SEQ_SIZE_241(_) SEQAN_PP_SEQ_SIZE_242 +# define SEQAN_PP_SEQ_SIZE_242(_) SEQAN_PP_SEQ_SIZE_243 +# define SEQAN_PP_SEQ_SIZE_243(_) SEQAN_PP_SEQ_SIZE_244 +# define SEQAN_PP_SEQ_SIZE_244(_) SEQAN_PP_SEQ_SIZE_245 +# define SEQAN_PP_SEQ_SIZE_245(_) SEQAN_PP_SEQ_SIZE_246 +# define SEQAN_PP_SEQ_SIZE_246(_) SEQAN_PP_SEQ_SIZE_247 +# define SEQAN_PP_SEQ_SIZE_247(_) SEQAN_PP_SEQ_SIZE_248 +# define SEQAN_PP_SEQ_SIZE_248(_) SEQAN_PP_SEQ_SIZE_249 +# define SEQAN_PP_SEQ_SIZE_249(_) SEQAN_PP_SEQ_SIZE_250 +# define SEQAN_PP_SEQ_SIZE_250(_) SEQAN_PP_SEQ_SIZE_251 +# define SEQAN_PP_SEQ_SIZE_251(_) SEQAN_PP_SEQ_SIZE_252 +# define SEQAN_PP_SEQ_SIZE_252(_) SEQAN_PP_SEQ_SIZE_253 +# define SEQAN_PP_SEQ_SIZE_253(_) SEQAN_PP_SEQ_SIZE_254 +# define SEQAN_PP_SEQ_SIZE_254(_) SEQAN_PP_SEQ_SIZE_255 +# define SEQAN_PP_SEQ_SIZE_255(_) SEQAN_PP_SEQ_SIZE_256 +# define SEQAN_PP_SEQ_SIZE_256(_) SEQAN_PP_SEQ_SIZE_257 +# +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_0 0 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_1 1 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_2 2 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_3 3 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_4 4 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_5 5 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_6 6 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_7 7 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_8 8 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_9 9 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_10 10 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_11 11 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_12 12 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_13 13 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_14 14 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_15 15 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_16 16 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_17 17 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_18 18 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_19 19 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_20 20 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_21 21 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_22 22 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_23 23 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_24 24 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_25 25 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_26 26 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_27 27 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_28 28 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_29 29 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_30 30 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_31 31 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_32 32 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_33 33 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_34 34 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_35 35 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_36 36 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_37 37 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_38 38 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_39 39 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_40 40 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_41 41 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_42 42 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_43 43 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_44 44 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_45 45 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_46 46 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_47 47 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_48 48 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_49 49 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_50 50 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_51 51 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_52 52 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_53 53 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_54 54 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_55 55 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_56 56 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_57 57 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_58 58 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_59 59 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_60 60 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_61 61 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_62 62 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_63 63 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_64 64 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_65 65 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_66 66 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_67 67 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_68 68 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_69 69 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_70 70 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_71 71 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_72 72 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_73 73 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_74 74 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_75 75 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_76 76 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_77 77 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_78 78 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_79 79 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_80 80 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_81 81 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_82 82 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_83 83 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_84 84 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_85 85 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_86 86 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_87 87 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_88 88 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_89 89 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_90 90 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_91 91 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_92 92 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_93 93 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_94 94 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_95 95 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_96 96 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_97 97 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_98 98 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_99 99 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_100 100 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_101 101 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_102 102 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_103 103 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_104 104 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_105 105 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_106 106 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_107 107 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_108 108 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_109 109 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_110 110 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_111 111 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_112 112 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_113 113 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_114 114 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_115 115 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_116 116 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_117 117 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_118 118 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_119 119 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_120 120 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_121 121 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_122 122 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_123 123 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_124 124 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_125 125 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_126 126 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_127 127 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_128 128 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_129 129 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_130 130 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_131 131 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_132 132 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_133 133 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_134 134 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_135 135 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_136 136 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_137 137 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_138 138 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_139 139 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_140 140 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_141 141 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_142 142 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_143 143 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_144 144 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_145 145 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_146 146 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_147 147 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_148 148 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_149 149 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_150 150 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_151 151 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_152 152 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_153 153 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_154 154 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_155 155 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_156 156 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_157 157 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_158 158 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_159 159 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_160 160 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_161 161 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_162 162 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_163 163 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_164 164 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_165 165 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_166 166 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_167 167 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_168 168 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_169 169 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_170 170 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_171 171 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_172 172 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_173 173 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_174 174 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_175 175 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_176 176 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_177 177 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_178 178 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_179 179 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_180 180 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_181 181 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_182 182 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_183 183 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_184 184 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_185 185 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_186 186 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_187 187 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_188 188 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_189 189 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_190 190 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_191 191 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_192 192 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_193 193 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_194 194 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_195 195 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_196 196 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_197 197 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_198 198 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_199 199 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_200 200 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_201 201 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_202 202 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_203 203 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_204 204 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_205 205 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_206 206 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_207 207 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_208 208 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_209 209 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_210 210 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_211 211 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_212 212 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_213 213 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_214 214 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_215 215 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_216 216 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_217 217 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_218 218 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_219 219 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_220 220 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_221 221 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_222 222 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_223 223 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_224 224 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_225 225 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_226 226 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_227 227 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_228 228 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_229 229 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_230 230 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_231 231 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_232 232 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_233 233 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_234 234 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_235 235 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_236 236 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_237 237 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_238 238 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_239 239 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_240 240 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_241 241 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_242 242 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_243 243 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_244 244 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_245 245 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_246 246 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_247 247 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_248 248 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_249 249 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_250 250 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_251 251 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_252 252 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_253 253 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_254 254 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_255 255 +# define SEQAN_PP_SEQ_SIZE_SEQAN_PP_SEQ_SIZE_256 256 + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/cat.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_CAT_HPP +// # define SEQAN_PREPROCESSOR_CAT_HPP +# +// # include +# +# /* SEQAN_PP_CAT */ +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_CAT(a, b) SEQAN_PP_CAT_I(a, b) +// # else +// # define SEQAN_PP_CAT(a, b) SEQAN_PP_CAT_OO((a, b)) +// # define SEQAN_PP_CAT_OO(par) SEQAN_PP_CAT_I ## par +// # endif +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MSVC() +#ifndef STDLIB_VS +# define SEQAN_PP_CAT_I(a, b) a ## b +#else // #ifndef STDLIB_VS +# define SEQAN_PP_CAT_I(a, b) SEQAN_PP_CAT_II(a ## b) +# define SEQAN_PP_CAT_II(res) res +#endif // #ifndef STDLIB_VS +# +// # endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/seq/enum.hpp <== +// -------------------------------------------------------------------------- + +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +//# ifndef SEQAN_PREPROCESSOR_SEQ_ENUM_HPP +//# define SEQAN_PREPROCESSOR_SEQ_ENUM_HPP +# +//# include +//# include +//# include +# +# /* SEQAN_PP_SEQ_ENUM */ +# +//# if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() +# define SEQAN_PP_SEQ_ENUM(seq) SEQAN_PP_SEQ_ENUM_I(seq) +# define SEQAN_PP_SEQ_ENUM_I(seq) SEQAN_PP_CAT(SEQAN_PP_SEQ_ENUM_, SEQAN_PP_SEQ_SIZE(seq)) seq +//# elif SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +//# define SEQAN_PP_SEQ_ENUM(seq) SEQAN_PP_SEQ_ENUM_I(SEQAN_PP_SEQ_SIZE(seq), seq) +//# define SEQAN_PP_SEQ_ENUM_I(size, seq) SEQAN_PP_CAT(SEQAN_PP_SEQ_ENUM_, size) seq +//# else +//# define SEQAN_PP_SEQ_ENUM(seq) SEQAN_PP_CAT(SEQAN_PP_SEQ_ENUM_, SEQAN_PP_SEQ_SIZE(seq)) seq +//# endif +# +# define SEQAN_PP_SEQ_ENUM_1(x) x +# define SEQAN_PP_SEQ_ENUM_2(x) x, SEQAN_PP_SEQ_ENUM_1 +# define SEQAN_PP_SEQ_ENUM_3(x) x, SEQAN_PP_SEQ_ENUM_2 +# define SEQAN_PP_SEQ_ENUM_4(x) x, SEQAN_PP_SEQ_ENUM_3 +# define SEQAN_PP_SEQ_ENUM_5(x) x, SEQAN_PP_SEQ_ENUM_4 +# define SEQAN_PP_SEQ_ENUM_6(x) x, SEQAN_PP_SEQ_ENUM_5 +# define SEQAN_PP_SEQ_ENUM_7(x) x, SEQAN_PP_SEQ_ENUM_6 +# define SEQAN_PP_SEQ_ENUM_8(x) x, SEQAN_PP_SEQ_ENUM_7 +# define SEQAN_PP_SEQ_ENUM_9(x) x, SEQAN_PP_SEQ_ENUM_8 +# define SEQAN_PP_SEQ_ENUM_10(x) x, SEQAN_PP_SEQ_ENUM_9 +# define SEQAN_PP_SEQ_ENUM_11(x) x, SEQAN_PP_SEQ_ENUM_10 +# define SEQAN_PP_SEQ_ENUM_12(x) x, SEQAN_PP_SEQ_ENUM_11 +# define SEQAN_PP_SEQ_ENUM_13(x) x, SEQAN_PP_SEQ_ENUM_12 +# define SEQAN_PP_SEQ_ENUM_14(x) x, SEQAN_PP_SEQ_ENUM_13 +# define SEQAN_PP_SEQ_ENUM_15(x) x, SEQAN_PP_SEQ_ENUM_14 +# define SEQAN_PP_SEQ_ENUM_16(x) x, SEQAN_PP_SEQ_ENUM_15 +# define SEQAN_PP_SEQ_ENUM_17(x) x, SEQAN_PP_SEQ_ENUM_16 +# define SEQAN_PP_SEQ_ENUM_18(x) x, SEQAN_PP_SEQ_ENUM_17 +# define SEQAN_PP_SEQ_ENUM_19(x) x, SEQAN_PP_SEQ_ENUM_18 +# define SEQAN_PP_SEQ_ENUM_20(x) x, SEQAN_PP_SEQ_ENUM_19 +# define SEQAN_PP_SEQ_ENUM_21(x) x, SEQAN_PP_SEQ_ENUM_20 +# define SEQAN_PP_SEQ_ENUM_22(x) x, SEQAN_PP_SEQ_ENUM_21 +# define SEQAN_PP_SEQ_ENUM_23(x) x, SEQAN_PP_SEQ_ENUM_22 +# define SEQAN_PP_SEQ_ENUM_24(x) x, SEQAN_PP_SEQ_ENUM_23 +# define SEQAN_PP_SEQ_ENUM_25(x) x, SEQAN_PP_SEQ_ENUM_24 +# define SEQAN_PP_SEQ_ENUM_26(x) x, SEQAN_PP_SEQ_ENUM_25 +# define SEQAN_PP_SEQ_ENUM_27(x) x, SEQAN_PP_SEQ_ENUM_26 +# define SEQAN_PP_SEQ_ENUM_28(x) x, SEQAN_PP_SEQ_ENUM_27 +# define SEQAN_PP_SEQ_ENUM_29(x) x, SEQAN_PP_SEQ_ENUM_28 +# define SEQAN_PP_SEQ_ENUM_30(x) x, SEQAN_PP_SEQ_ENUM_29 +# define SEQAN_PP_SEQ_ENUM_31(x) x, SEQAN_PP_SEQ_ENUM_30 +# define SEQAN_PP_SEQ_ENUM_32(x) x, SEQAN_PP_SEQ_ENUM_31 +# define SEQAN_PP_SEQ_ENUM_33(x) x, SEQAN_PP_SEQ_ENUM_32 +# define SEQAN_PP_SEQ_ENUM_34(x) x, SEQAN_PP_SEQ_ENUM_33 +# define SEQAN_PP_SEQ_ENUM_35(x) x, SEQAN_PP_SEQ_ENUM_34 +# define SEQAN_PP_SEQ_ENUM_36(x) x, SEQAN_PP_SEQ_ENUM_35 +# define SEQAN_PP_SEQ_ENUM_37(x) x, SEQAN_PP_SEQ_ENUM_36 +# define SEQAN_PP_SEQ_ENUM_38(x) x, SEQAN_PP_SEQ_ENUM_37 +# define SEQAN_PP_SEQ_ENUM_39(x) x, SEQAN_PP_SEQ_ENUM_38 +# define SEQAN_PP_SEQ_ENUM_40(x) x, SEQAN_PP_SEQ_ENUM_39 +# define SEQAN_PP_SEQ_ENUM_41(x) x, SEQAN_PP_SEQ_ENUM_40 +# define SEQAN_PP_SEQ_ENUM_42(x) x, SEQAN_PP_SEQ_ENUM_41 +# define SEQAN_PP_SEQ_ENUM_43(x) x, SEQAN_PP_SEQ_ENUM_42 +# define SEQAN_PP_SEQ_ENUM_44(x) x, SEQAN_PP_SEQ_ENUM_43 +# define SEQAN_PP_SEQ_ENUM_45(x) x, SEQAN_PP_SEQ_ENUM_44 +# define SEQAN_PP_SEQ_ENUM_46(x) x, SEQAN_PP_SEQ_ENUM_45 +# define SEQAN_PP_SEQ_ENUM_47(x) x, SEQAN_PP_SEQ_ENUM_46 +# define SEQAN_PP_SEQ_ENUM_48(x) x, SEQAN_PP_SEQ_ENUM_47 +# define SEQAN_PP_SEQ_ENUM_49(x) x, SEQAN_PP_SEQ_ENUM_48 +# define SEQAN_PP_SEQ_ENUM_50(x) x, SEQAN_PP_SEQ_ENUM_49 +# define SEQAN_PP_SEQ_ENUM_51(x) x, SEQAN_PP_SEQ_ENUM_50 +# define SEQAN_PP_SEQ_ENUM_52(x) x, SEQAN_PP_SEQ_ENUM_51 +# define SEQAN_PP_SEQ_ENUM_53(x) x, SEQAN_PP_SEQ_ENUM_52 +# define SEQAN_PP_SEQ_ENUM_54(x) x, SEQAN_PP_SEQ_ENUM_53 +# define SEQAN_PP_SEQ_ENUM_55(x) x, SEQAN_PP_SEQ_ENUM_54 +# define SEQAN_PP_SEQ_ENUM_56(x) x, SEQAN_PP_SEQ_ENUM_55 +# define SEQAN_PP_SEQ_ENUM_57(x) x, SEQAN_PP_SEQ_ENUM_56 +# define SEQAN_PP_SEQ_ENUM_58(x) x, SEQAN_PP_SEQ_ENUM_57 +# define SEQAN_PP_SEQ_ENUM_59(x) x, SEQAN_PP_SEQ_ENUM_58 +# define SEQAN_PP_SEQ_ENUM_60(x) x, SEQAN_PP_SEQ_ENUM_59 +# define SEQAN_PP_SEQ_ENUM_61(x) x, SEQAN_PP_SEQ_ENUM_60 +# define SEQAN_PP_SEQ_ENUM_62(x) x, SEQAN_PP_SEQ_ENUM_61 +# define SEQAN_PP_SEQ_ENUM_63(x) x, SEQAN_PP_SEQ_ENUM_62 +# define SEQAN_PP_SEQ_ENUM_64(x) x, SEQAN_PP_SEQ_ENUM_63 +# define SEQAN_PP_SEQ_ENUM_65(x) x, SEQAN_PP_SEQ_ENUM_64 +# define SEQAN_PP_SEQ_ENUM_66(x) x, SEQAN_PP_SEQ_ENUM_65 +# define SEQAN_PP_SEQ_ENUM_67(x) x, SEQAN_PP_SEQ_ENUM_66 +# define SEQAN_PP_SEQ_ENUM_68(x) x, SEQAN_PP_SEQ_ENUM_67 +# define SEQAN_PP_SEQ_ENUM_69(x) x, SEQAN_PP_SEQ_ENUM_68 +# define SEQAN_PP_SEQ_ENUM_70(x) x, SEQAN_PP_SEQ_ENUM_69 +# define SEQAN_PP_SEQ_ENUM_71(x) x, SEQAN_PP_SEQ_ENUM_70 +# define SEQAN_PP_SEQ_ENUM_72(x) x, SEQAN_PP_SEQ_ENUM_71 +# define SEQAN_PP_SEQ_ENUM_73(x) x, SEQAN_PP_SEQ_ENUM_72 +# define SEQAN_PP_SEQ_ENUM_74(x) x, SEQAN_PP_SEQ_ENUM_73 +# define SEQAN_PP_SEQ_ENUM_75(x) x, SEQAN_PP_SEQ_ENUM_74 +# define SEQAN_PP_SEQ_ENUM_76(x) x, SEQAN_PP_SEQ_ENUM_75 +# define SEQAN_PP_SEQ_ENUM_77(x) x, SEQAN_PP_SEQ_ENUM_76 +# define SEQAN_PP_SEQ_ENUM_78(x) x, SEQAN_PP_SEQ_ENUM_77 +# define SEQAN_PP_SEQ_ENUM_79(x) x, SEQAN_PP_SEQ_ENUM_78 +# define SEQAN_PP_SEQ_ENUM_80(x) x, SEQAN_PP_SEQ_ENUM_79 +# define SEQAN_PP_SEQ_ENUM_81(x) x, SEQAN_PP_SEQ_ENUM_80 +# define SEQAN_PP_SEQ_ENUM_82(x) x, SEQAN_PP_SEQ_ENUM_81 +# define SEQAN_PP_SEQ_ENUM_83(x) x, SEQAN_PP_SEQ_ENUM_82 +# define SEQAN_PP_SEQ_ENUM_84(x) x, SEQAN_PP_SEQ_ENUM_83 +# define SEQAN_PP_SEQ_ENUM_85(x) x, SEQAN_PP_SEQ_ENUM_84 +# define SEQAN_PP_SEQ_ENUM_86(x) x, SEQAN_PP_SEQ_ENUM_85 +# define SEQAN_PP_SEQ_ENUM_87(x) x, SEQAN_PP_SEQ_ENUM_86 +# define SEQAN_PP_SEQ_ENUM_88(x) x, SEQAN_PP_SEQ_ENUM_87 +# define SEQAN_PP_SEQ_ENUM_89(x) x, SEQAN_PP_SEQ_ENUM_88 +# define SEQAN_PP_SEQ_ENUM_90(x) x, SEQAN_PP_SEQ_ENUM_89 +# define SEQAN_PP_SEQ_ENUM_91(x) x, SEQAN_PP_SEQ_ENUM_90 +# define SEQAN_PP_SEQ_ENUM_92(x) x, SEQAN_PP_SEQ_ENUM_91 +# define SEQAN_PP_SEQ_ENUM_93(x) x, SEQAN_PP_SEQ_ENUM_92 +# define SEQAN_PP_SEQ_ENUM_94(x) x, SEQAN_PP_SEQ_ENUM_93 +# define SEQAN_PP_SEQ_ENUM_95(x) x, SEQAN_PP_SEQ_ENUM_94 +# define SEQAN_PP_SEQ_ENUM_96(x) x, SEQAN_PP_SEQ_ENUM_95 +# define SEQAN_PP_SEQ_ENUM_97(x) x, SEQAN_PP_SEQ_ENUM_96 +# define SEQAN_PP_SEQ_ENUM_98(x) x, SEQAN_PP_SEQ_ENUM_97 +# define SEQAN_PP_SEQ_ENUM_99(x) x, SEQAN_PP_SEQ_ENUM_98 +# define SEQAN_PP_SEQ_ENUM_100(x) x, SEQAN_PP_SEQ_ENUM_99 +# define SEQAN_PP_SEQ_ENUM_101(x) x, SEQAN_PP_SEQ_ENUM_100 +# define SEQAN_PP_SEQ_ENUM_102(x) x, SEQAN_PP_SEQ_ENUM_101 +# define SEQAN_PP_SEQ_ENUM_103(x) x, SEQAN_PP_SEQ_ENUM_102 +# define SEQAN_PP_SEQ_ENUM_104(x) x, SEQAN_PP_SEQ_ENUM_103 +# define SEQAN_PP_SEQ_ENUM_105(x) x, SEQAN_PP_SEQ_ENUM_104 +# define SEQAN_PP_SEQ_ENUM_106(x) x, SEQAN_PP_SEQ_ENUM_105 +# define SEQAN_PP_SEQ_ENUM_107(x) x, SEQAN_PP_SEQ_ENUM_106 +# define SEQAN_PP_SEQ_ENUM_108(x) x, SEQAN_PP_SEQ_ENUM_107 +# define SEQAN_PP_SEQ_ENUM_109(x) x, SEQAN_PP_SEQ_ENUM_108 +# define SEQAN_PP_SEQ_ENUM_110(x) x, SEQAN_PP_SEQ_ENUM_109 +# define SEQAN_PP_SEQ_ENUM_111(x) x, SEQAN_PP_SEQ_ENUM_110 +# define SEQAN_PP_SEQ_ENUM_112(x) x, SEQAN_PP_SEQ_ENUM_111 +# define SEQAN_PP_SEQ_ENUM_113(x) x, SEQAN_PP_SEQ_ENUM_112 +# define SEQAN_PP_SEQ_ENUM_114(x) x, SEQAN_PP_SEQ_ENUM_113 +# define SEQAN_PP_SEQ_ENUM_115(x) x, SEQAN_PP_SEQ_ENUM_114 +# define SEQAN_PP_SEQ_ENUM_116(x) x, SEQAN_PP_SEQ_ENUM_115 +# define SEQAN_PP_SEQ_ENUM_117(x) x, SEQAN_PP_SEQ_ENUM_116 +# define SEQAN_PP_SEQ_ENUM_118(x) x, SEQAN_PP_SEQ_ENUM_117 +# define SEQAN_PP_SEQ_ENUM_119(x) x, SEQAN_PP_SEQ_ENUM_118 +# define SEQAN_PP_SEQ_ENUM_120(x) x, SEQAN_PP_SEQ_ENUM_119 +# define SEQAN_PP_SEQ_ENUM_121(x) x, SEQAN_PP_SEQ_ENUM_120 +# define SEQAN_PP_SEQ_ENUM_122(x) x, SEQAN_PP_SEQ_ENUM_121 +# define SEQAN_PP_SEQ_ENUM_123(x) x, SEQAN_PP_SEQ_ENUM_122 +# define SEQAN_PP_SEQ_ENUM_124(x) x, SEQAN_PP_SEQ_ENUM_123 +# define SEQAN_PP_SEQ_ENUM_125(x) x, SEQAN_PP_SEQ_ENUM_124 +# define SEQAN_PP_SEQ_ENUM_126(x) x, SEQAN_PP_SEQ_ENUM_125 +# define SEQAN_PP_SEQ_ENUM_127(x) x, SEQAN_PP_SEQ_ENUM_126 +# define SEQAN_PP_SEQ_ENUM_128(x) x, SEQAN_PP_SEQ_ENUM_127 +# define SEQAN_PP_SEQ_ENUM_129(x) x, SEQAN_PP_SEQ_ENUM_128 +# define SEQAN_PP_SEQ_ENUM_130(x) x, SEQAN_PP_SEQ_ENUM_129 +# define SEQAN_PP_SEQ_ENUM_131(x) x, SEQAN_PP_SEQ_ENUM_130 +# define SEQAN_PP_SEQ_ENUM_132(x) x, SEQAN_PP_SEQ_ENUM_131 +# define SEQAN_PP_SEQ_ENUM_133(x) x, SEQAN_PP_SEQ_ENUM_132 +# define SEQAN_PP_SEQ_ENUM_134(x) x, SEQAN_PP_SEQ_ENUM_133 +# define SEQAN_PP_SEQ_ENUM_135(x) x, SEQAN_PP_SEQ_ENUM_134 +# define SEQAN_PP_SEQ_ENUM_136(x) x, SEQAN_PP_SEQ_ENUM_135 +# define SEQAN_PP_SEQ_ENUM_137(x) x, SEQAN_PP_SEQ_ENUM_136 +# define SEQAN_PP_SEQ_ENUM_138(x) x, SEQAN_PP_SEQ_ENUM_137 +# define SEQAN_PP_SEQ_ENUM_139(x) x, SEQAN_PP_SEQ_ENUM_138 +# define SEQAN_PP_SEQ_ENUM_140(x) x, SEQAN_PP_SEQ_ENUM_139 +# define SEQAN_PP_SEQ_ENUM_141(x) x, SEQAN_PP_SEQ_ENUM_140 +# define SEQAN_PP_SEQ_ENUM_142(x) x, SEQAN_PP_SEQ_ENUM_141 +# define SEQAN_PP_SEQ_ENUM_143(x) x, SEQAN_PP_SEQ_ENUM_142 +# define SEQAN_PP_SEQ_ENUM_144(x) x, SEQAN_PP_SEQ_ENUM_143 +# define SEQAN_PP_SEQ_ENUM_145(x) x, SEQAN_PP_SEQ_ENUM_144 +# define SEQAN_PP_SEQ_ENUM_146(x) x, SEQAN_PP_SEQ_ENUM_145 +# define SEQAN_PP_SEQ_ENUM_147(x) x, SEQAN_PP_SEQ_ENUM_146 +# define SEQAN_PP_SEQ_ENUM_148(x) x, SEQAN_PP_SEQ_ENUM_147 +# define SEQAN_PP_SEQ_ENUM_149(x) x, SEQAN_PP_SEQ_ENUM_148 +# define SEQAN_PP_SEQ_ENUM_150(x) x, SEQAN_PP_SEQ_ENUM_149 +# define SEQAN_PP_SEQ_ENUM_151(x) x, SEQAN_PP_SEQ_ENUM_150 +# define SEQAN_PP_SEQ_ENUM_152(x) x, SEQAN_PP_SEQ_ENUM_151 +# define SEQAN_PP_SEQ_ENUM_153(x) x, SEQAN_PP_SEQ_ENUM_152 +# define SEQAN_PP_SEQ_ENUM_154(x) x, SEQAN_PP_SEQ_ENUM_153 +# define SEQAN_PP_SEQ_ENUM_155(x) x, SEQAN_PP_SEQ_ENUM_154 +# define SEQAN_PP_SEQ_ENUM_156(x) x, SEQAN_PP_SEQ_ENUM_155 +# define SEQAN_PP_SEQ_ENUM_157(x) x, SEQAN_PP_SEQ_ENUM_156 +# define SEQAN_PP_SEQ_ENUM_158(x) x, SEQAN_PP_SEQ_ENUM_157 +# define SEQAN_PP_SEQ_ENUM_159(x) x, SEQAN_PP_SEQ_ENUM_158 +# define SEQAN_PP_SEQ_ENUM_160(x) x, SEQAN_PP_SEQ_ENUM_159 +# define SEQAN_PP_SEQ_ENUM_161(x) x, SEQAN_PP_SEQ_ENUM_160 +# define SEQAN_PP_SEQ_ENUM_162(x) x, SEQAN_PP_SEQ_ENUM_161 +# define SEQAN_PP_SEQ_ENUM_163(x) x, SEQAN_PP_SEQ_ENUM_162 +# define SEQAN_PP_SEQ_ENUM_164(x) x, SEQAN_PP_SEQ_ENUM_163 +# define SEQAN_PP_SEQ_ENUM_165(x) x, SEQAN_PP_SEQ_ENUM_164 +# define SEQAN_PP_SEQ_ENUM_166(x) x, SEQAN_PP_SEQ_ENUM_165 +# define SEQAN_PP_SEQ_ENUM_167(x) x, SEQAN_PP_SEQ_ENUM_166 +# define SEQAN_PP_SEQ_ENUM_168(x) x, SEQAN_PP_SEQ_ENUM_167 +# define SEQAN_PP_SEQ_ENUM_169(x) x, SEQAN_PP_SEQ_ENUM_168 +# define SEQAN_PP_SEQ_ENUM_170(x) x, SEQAN_PP_SEQ_ENUM_169 +# define SEQAN_PP_SEQ_ENUM_171(x) x, SEQAN_PP_SEQ_ENUM_170 +# define SEQAN_PP_SEQ_ENUM_172(x) x, SEQAN_PP_SEQ_ENUM_171 +# define SEQAN_PP_SEQ_ENUM_173(x) x, SEQAN_PP_SEQ_ENUM_172 +# define SEQAN_PP_SEQ_ENUM_174(x) x, SEQAN_PP_SEQ_ENUM_173 +# define SEQAN_PP_SEQ_ENUM_175(x) x, SEQAN_PP_SEQ_ENUM_174 +# define SEQAN_PP_SEQ_ENUM_176(x) x, SEQAN_PP_SEQ_ENUM_175 +# define SEQAN_PP_SEQ_ENUM_177(x) x, SEQAN_PP_SEQ_ENUM_176 +# define SEQAN_PP_SEQ_ENUM_178(x) x, SEQAN_PP_SEQ_ENUM_177 +# define SEQAN_PP_SEQ_ENUM_179(x) x, SEQAN_PP_SEQ_ENUM_178 +# define SEQAN_PP_SEQ_ENUM_180(x) x, SEQAN_PP_SEQ_ENUM_179 +# define SEQAN_PP_SEQ_ENUM_181(x) x, SEQAN_PP_SEQ_ENUM_180 +# define SEQAN_PP_SEQ_ENUM_182(x) x, SEQAN_PP_SEQ_ENUM_181 +# define SEQAN_PP_SEQ_ENUM_183(x) x, SEQAN_PP_SEQ_ENUM_182 +# define SEQAN_PP_SEQ_ENUM_184(x) x, SEQAN_PP_SEQ_ENUM_183 +# define SEQAN_PP_SEQ_ENUM_185(x) x, SEQAN_PP_SEQ_ENUM_184 +# define SEQAN_PP_SEQ_ENUM_186(x) x, SEQAN_PP_SEQ_ENUM_185 +# define SEQAN_PP_SEQ_ENUM_187(x) x, SEQAN_PP_SEQ_ENUM_186 +# define SEQAN_PP_SEQ_ENUM_188(x) x, SEQAN_PP_SEQ_ENUM_187 +# define SEQAN_PP_SEQ_ENUM_189(x) x, SEQAN_PP_SEQ_ENUM_188 +# define SEQAN_PP_SEQ_ENUM_190(x) x, SEQAN_PP_SEQ_ENUM_189 +# define SEQAN_PP_SEQ_ENUM_191(x) x, SEQAN_PP_SEQ_ENUM_190 +# define SEQAN_PP_SEQ_ENUM_192(x) x, SEQAN_PP_SEQ_ENUM_191 +# define SEQAN_PP_SEQ_ENUM_193(x) x, SEQAN_PP_SEQ_ENUM_192 +# define SEQAN_PP_SEQ_ENUM_194(x) x, SEQAN_PP_SEQ_ENUM_193 +# define SEQAN_PP_SEQ_ENUM_195(x) x, SEQAN_PP_SEQ_ENUM_194 +# define SEQAN_PP_SEQ_ENUM_196(x) x, SEQAN_PP_SEQ_ENUM_195 +# define SEQAN_PP_SEQ_ENUM_197(x) x, SEQAN_PP_SEQ_ENUM_196 +# define SEQAN_PP_SEQ_ENUM_198(x) x, SEQAN_PP_SEQ_ENUM_197 +# define SEQAN_PP_SEQ_ENUM_199(x) x, SEQAN_PP_SEQ_ENUM_198 +# define SEQAN_PP_SEQ_ENUM_200(x) x, SEQAN_PP_SEQ_ENUM_199 +# define SEQAN_PP_SEQ_ENUM_201(x) x, SEQAN_PP_SEQ_ENUM_200 +# define SEQAN_PP_SEQ_ENUM_202(x) x, SEQAN_PP_SEQ_ENUM_201 +# define SEQAN_PP_SEQ_ENUM_203(x) x, SEQAN_PP_SEQ_ENUM_202 +# define SEQAN_PP_SEQ_ENUM_204(x) x, SEQAN_PP_SEQ_ENUM_203 +# define SEQAN_PP_SEQ_ENUM_205(x) x, SEQAN_PP_SEQ_ENUM_204 +# define SEQAN_PP_SEQ_ENUM_206(x) x, SEQAN_PP_SEQ_ENUM_205 +# define SEQAN_PP_SEQ_ENUM_207(x) x, SEQAN_PP_SEQ_ENUM_206 +# define SEQAN_PP_SEQ_ENUM_208(x) x, SEQAN_PP_SEQ_ENUM_207 +# define SEQAN_PP_SEQ_ENUM_209(x) x, SEQAN_PP_SEQ_ENUM_208 +# define SEQAN_PP_SEQ_ENUM_210(x) x, SEQAN_PP_SEQ_ENUM_209 +# define SEQAN_PP_SEQ_ENUM_211(x) x, SEQAN_PP_SEQ_ENUM_210 +# define SEQAN_PP_SEQ_ENUM_212(x) x, SEQAN_PP_SEQ_ENUM_211 +# define SEQAN_PP_SEQ_ENUM_213(x) x, SEQAN_PP_SEQ_ENUM_212 +# define SEQAN_PP_SEQ_ENUM_214(x) x, SEQAN_PP_SEQ_ENUM_213 +# define SEQAN_PP_SEQ_ENUM_215(x) x, SEQAN_PP_SEQ_ENUM_214 +# define SEQAN_PP_SEQ_ENUM_216(x) x, SEQAN_PP_SEQ_ENUM_215 +# define SEQAN_PP_SEQ_ENUM_217(x) x, SEQAN_PP_SEQ_ENUM_216 +# define SEQAN_PP_SEQ_ENUM_218(x) x, SEQAN_PP_SEQ_ENUM_217 +# define SEQAN_PP_SEQ_ENUM_219(x) x, SEQAN_PP_SEQ_ENUM_218 +# define SEQAN_PP_SEQ_ENUM_220(x) x, SEQAN_PP_SEQ_ENUM_219 +# define SEQAN_PP_SEQ_ENUM_221(x) x, SEQAN_PP_SEQ_ENUM_220 +# define SEQAN_PP_SEQ_ENUM_222(x) x, SEQAN_PP_SEQ_ENUM_221 +# define SEQAN_PP_SEQ_ENUM_223(x) x, SEQAN_PP_SEQ_ENUM_222 +# define SEQAN_PP_SEQ_ENUM_224(x) x, SEQAN_PP_SEQ_ENUM_223 +# define SEQAN_PP_SEQ_ENUM_225(x) x, SEQAN_PP_SEQ_ENUM_224 +# define SEQAN_PP_SEQ_ENUM_226(x) x, SEQAN_PP_SEQ_ENUM_225 +# define SEQAN_PP_SEQ_ENUM_227(x) x, SEQAN_PP_SEQ_ENUM_226 +# define SEQAN_PP_SEQ_ENUM_228(x) x, SEQAN_PP_SEQ_ENUM_227 +# define SEQAN_PP_SEQ_ENUM_229(x) x, SEQAN_PP_SEQ_ENUM_228 +# define SEQAN_PP_SEQ_ENUM_230(x) x, SEQAN_PP_SEQ_ENUM_229 +# define SEQAN_PP_SEQ_ENUM_231(x) x, SEQAN_PP_SEQ_ENUM_230 +# define SEQAN_PP_SEQ_ENUM_232(x) x, SEQAN_PP_SEQ_ENUM_231 +# define SEQAN_PP_SEQ_ENUM_233(x) x, SEQAN_PP_SEQ_ENUM_232 +# define SEQAN_PP_SEQ_ENUM_234(x) x, SEQAN_PP_SEQ_ENUM_233 +# define SEQAN_PP_SEQ_ENUM_235(x) x, SEQAN_PP_SEQ_ENUM_234 +# define SEQAN_PP_SEQ_ENUM_236(x) x, SEQAN_PP_SEQ_ENUM_235 +# define SEQAN_PP_SEQ_ENUM_237(x) x, SEQAN_PP_SEQ_ENUM_236 +# define SEQAN_PP_SEQ_ENUM_238(x) x, SEQAN_PP_SEQ_ENUM_237 +# define SEQAN_PP_SEQ_ENUM_239(x) x, SEQAN_PP_SEQ_ENUM_238 +# define SEQAN_PP_SEQ_ENUM_240(x) x, SEQAN_PP_SEQ_ENUM_239 +# define SEQAN_PP_SEQ_ENUM_241(x) x, SEQAN_PP_SEQ_ENUM_240 +# define SEQAN_PP_SEQ_ENUM_242(x) x, SEQAN_PP_SEQ_ENUM_241 +# define SEQAN_PP_SEQ_ENUM_243(x) x, SEQAN_PP_SEQ_ENUM_242 +# define SEQAN_PP_SEQ_ENUM_244(x) x, SEQAN_PP_SEQ_ENUM_243 +# define SEQAN_PP_SEQ_ENUM_245(x) x, SEQAN_PP_SEQ_ENUM_244 +# define SEQAN_PP_SEQ_ENUM_246(x) x, SEQAN_PP_SEQ_ENUM_245 +# define SEQAN_PP_SEQ_ENUM_247(x) x, SEQAN_PP_SEQ_ENUM_246 +# define SEQAN_PP_SEQ_ENUM_248(x) x, SEQAN_PP_SEQ_ENUM_247 +# define SEQAN_PP_SEQ_ENUM_249(x) x, SEQAN_PP_SEQ_ENUM_248 +# define SEQAN_PP_SEQ_ENUM_250(x) x, SEQAN_PP_SEQ_ENUM_249 +# define SEQAN_PP_SEQ_ENUM_251(x) x, SEQAN_PP_SEQ_ENUM_250 +# define SEQAN_PP_SEQ_ENUM_252(x) x, SEQAN_PP_SEQ_ENUM_251 +# define SEQAN_PP_SEQ_ENUM_253(x) x, SEQAN_PP_SEQ_ENUM_252 +# define SEQAN_PP_SEQ_ENUM_254(x) x, SEQAN_PP_SEQ_ENUM_253 +# define SEQAN_PP_SEQ_ENUM_255(x) x, SEQAN_PP_SEQ_ENUM_254 +# define SEQAN_PP_SEQ_ENUM_256(x) x, SEQAN_PP_SEQ_ENUM_255 +# +//# endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/tuple/eat.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_TUPLE_EAT_HPP +// # define SEQAN_PREPROCESSOR_TUPLE_EAT_HPP +# +// # include +# +# /* SEQAN_PP_TUPLE_EAT */ +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_TUPLE_EAT(size) SEQAN_PP_TUPLE_EAT_I(size) +// # else +// # define SEQAN_PP_TUPLE_EAT(size) SEQAN_PP_TUPLE_EAT_OO((size)) +// # define SEQAN_PP_TUPLE_EAT_OO(par) SEQAN_PP_TUPLE_EAT_I ## par +// # endif +# +# define SEQAN_PP_TUPLE_EAT_I(size) SEQAN_PP_TUPLE_EAT_ ## size +# +# define SEQAN_PP_TUPLE_EAT_0() +# define SEQAN_PP_TUPLE_EAT_1(a) +# define SEQAN_PP_TUPLE_EAT_2(a, b) +# define SEQAN_PP_TUPLE_EAT_3(a, b, c) +# define SEQAN_PP_TUPLE_EAT_4(a, b, c, d) +# define SEQAN_PP_TUPLE_EAT_5(a, b, c, d, e) +# define SEQAN_PP_TUPLE_EAT_6(a, b, c, d, e, f) +# define SEQAN_PP_TUPLE_EAT_7(a, b, c, d, e, f, g) +# define SEQAN_PP_TUPLE_EAT_8(a, b, c, d, e, f, g, h) +# define SEQAN_PP_TUPLE_EAT_9(a, b, c, d, e, f, g, h, i) +# define SEQAN_PP_TUPLE_EAT_10(a, b, c, d, e, f, g, h, i, j) +# define SEQAN_PP_TUPLE_EAT_11(a, b, c, d, e, f, g, h, i, j, k) +# define SEQAN_PP_TUPLE_EAT_12(a, b, c, d, e, f, g, h, i, j, k, l) +# define SEQAN_PP_TUPLE_EAT_13(a, b, c, d, e, f, g, h, i, j, k, l, m) +# define SEQAN_PP_TUPLE_EAT_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) +# define SEQAN_PP_TUPLE_EAT_15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) +# define SEQAN_PP_TUPLE_EAT_16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) +# define SEQAN_PP_TUPLE_EAT_17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) +# define SEQAN_PP_TUPLE_EAT_18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) +# define SEQAN_PP_TUPLE_EAT_19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) +# define SEQAN_PP_TUPLE_EAT_20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) +# define SEQAN_PP_TUPLE_EAT_21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) +# define SEQAN_PP_TUPLE_EAT_22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) +# define SEQAN_PP_TUPLE_EAT_23(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w) +# define SEQAN_PP_TUPLE_EAT_24(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x) +# define SEQAN_PP_TUPLE_EAT_25(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y) +# +// # endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/repetition/detail/for.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_REPETITION_DETAIL_FOR_HPP +// # define SEQAN_PREPROCESSOR_REPETITION_DETAIL_FOR_HPP +// # +// # include +// # include +// # include +// # include +# +# define SEQAN_PP_FOR_1(s, p, o, m) SEQAN_PP_FOR_1_C(SEQAN_PP_BOOL(p(2, s)), s, p, o, m) +# define SEQAN_PP_FOR_2(s, p, o, m) SEQAN_PP_FOR_2_C(SEQAN_PP_BOOL(p(3, s)), s, p, o, m) +# define SEQAN_PP_FOR_3(s, p, o, m) SEQAN_PP_FOR_3_C(SEQAN_PP_BOOL(p(4, s)), s, p, o, m) +# define SEQAN_PP_FOR_4(s, p, o, m) SEQAN_PP_FOR_4_C(SEQAN_PP_BOOL(p(5, s)), s, p, o, m) +# define SEQAN_PP_FOR_5(s, p, o, m) SEQAN_PP_FOR_5_C(SEQAN_PP_BOOL(p(6, s)), s, p, o, m) +# define SEQAN_PP_FOR_6(s, p, o, m) SEQAN_PP_FOR_6_C(SEQAN_PP_BOOL(p(7, s)), s, p, o, m) +# define SEQAN_PP_FOR_7(s, p, o, m) SEQAN_PP_FOR_7_C(SEQAN_PP_BOOL(p(8, s)), s, p, o, m) +# define SEQAN_PP_FOR_8(s, p, o, m) SEQAN_PP_FOR_8_C(SEQAN_PP_BOOL(p(9, s)), s, p, o, m) +# define SEQAN_PP_FOR_9(s, p, o, m) SEQAN_PP_FOR_9_C(SEQAN_PP_BOOL(p(10, s)), s, p, o, m) +# define SEQAN_PP_FOR_10(s, p, o, m) SEQAN_PP_FOR_10_C(SEQAN_PP_BOOL(p(11, s)), s, p, o, m) +# define SEQAN_PP_FOR_11(s, p, o, m) SEQAN_PP_FOR_11_C(SEQAN_PP_BOOL(p(12, s)), s, p, o, m) +# define SEQAN_PP_FOR_12(s, p, o, m) SEQAN_PP_FOR_12_C(SEQAN_PP_BOOL(p(13, s)), s, p, o, m) +# define SEQAN_PP_FOR_13(s, p, o, m) SEQAN_PP_FOR_13_C(SEQAN_PP_BOOL(p(14, s)), s, p, o, m) +# define SEQAN_PP_FOR_14(s, p, o, m) SEQAN_PP_FOR_14_C(SEQAN_PP_BOOL(p(15, s)), s, p, o, m) +# define SEQAN_PP_FOR_15(s, p, o, m) SEQAN_PP_FOR_15_C(SEQAN_PP_BOOL(p(16, s)), s, p, o, m) +# define SEQAN_PP_FOR_16(s, p, o, m) SEQAN_PP_FOR_16_C(SEQAN_PP_BOOL(p(17, s)), s, p, o, m) +# define SEQAN_PP_FOR_17(s, p, o, m) SEQAN_PP_FOR_17_C(SEQAN_PP_BOOL(p(18, s)), s, p, o, m) +# define SEQAN_PP_FOR_18(s, p, o, m) SEQAN_PP_FOR_18_C(SEQAN_PP_BOOL(p(19, s)), s, p, o, m) +# define SEQAN_PP_FOR_19(s, p, o, m) SEQAN_PP_FOR_19_C(SEQAN_PP_BOOL(p(20, s)), s, p, o, m) +# define SEQAN_PP_FOR_20(s, p, o, m) SEQAN_PP_FOR_20_C(SEQAN_PP_BOOL(p(21, s)), s, p, o, m) +# define SEQAN_PP_FOR_21(s, p, o, m) SEQAN_PP_FOR_21_C(SEQAN_PP_BOOL(p(22, s)), s, p, o, m) +# define SEQAN_PP_FOR_22(s, p, o, m) SEQAN_PP_FOR_22_C(SEQAN_PP_BOOL(p(23, s)), s, p, o, m) +# define SEQAN_PP_FOR_23(s, p, o, m) SEQAN_PP_FOR_23_C(SEQAN_PP_BOOL(p(24, s)), s, p, o, m) +# define SEQAN_PP_FOR_24(s, p, o, m) SEQAN_PP_FOR_24_C(SEQAN_PP_BOOL(p(25, s)), s, p, o, m) +# define SEQAN_PP_FOR_25(s, p, o, m) SEQAN_PP_FOR_25_C(SEQAN_PP_BOOL(p(26, s)), s, p, o, m) +# define SEQAN_PP_FOR_26(s, p, o, m) SEQAN_PP_FOR_26_C(SEQAN_PP_BOOL(p(27, s)), s, p, o, m) +# define SEQAN_PP_FOR_27(s, p, o, m) SEQAN_PP_FOR_27_C(SEQAN_PP_BOOL(p(28, s)), s, p, o, m) +# define SEQAN_PP_FOR_28(s, p, o, m) SEQAN_PP_FOR_28_C(SEQAN_PP_BOOL(p(29, s)), s, p, o, m) +# define SEQAN_PP_FOR_29(s, p, o, m) SEQAN_PP_FOR_29_C(SEQAN_PP_BOOL(p(30, s)), s, p, o, m) +# define SEQAN_PP_FOR_30(s, p, o, m) SEQAN_PP_FOR_30_C(SEQAN_PP_BOOL(p(31, s)), s, p, o, m) +# define SEQAN_PP_FOR_31(s, p, o, m) SEQAN_PP_FOR_31_C(SEQAN_PP_BOOL(p(32, s)), s, p, o, m) +# define SEQAN_PP_FOR_32(s, p, o, m) SEQAN_PP_FOR_32_C(SEQAN_PP_BOOL(p(33, s)), s, p, o, m) +# define SEQAN_PP_FOR_33(s, p, o, m) SEQAN_PP_FOR_33_C(SEQAN_PP_BOOL(p(34, s)), s, p, o, m) +# define SEQAN_PP_FOR_34(s, p, o, m) SEQAN_PP_FOR_34_C(SEQAN_PP_BOOL(p(35, s)), s, p, o, m) +# define SEQAN_PP_FOR_35(s, p, o, m) SEQAN_PP_FOR_35_C(SEQAN_PP_BOOL(p(36, s)), s, p, o, m) +# define SEQAN_PP_FOR_36(s, p, o, m) SEQAN_PP_FOR_36_C(SEQAN_PP_BOOL(p(37, s)), s, p, o, m) +# define SEQAN_PP_FOR_37(s, p, o, m) SEQAN_PP_FOR_37_C(SEQAN_PP_BOOL(p(38, s)), s, p, o, m) +# define SEQAN_PP_FOR_38(s, p, o, m) SEQAN_PP_FOR_38_C(SEQAN_PP_BOOL(p(39, s)), s, p, o, m) +# define SEQAN_PP_FOR_39(s, p, o, m) SEQAN_PP_FOR_39_C(SEQAN_PP_BOOL(p(40, s)), s, p, o, m) +# define SEQAN_PP_FOR_40(s, p, o, m) SEQAN_PP_FOR_40_C(SEQAN_PP_BOOL(p(41, s)), s, p, o, m) +# define SEQAN_PP_FOR_41(s, p, o, m) SEQAN_PP_FOR_41_C(SEQAN_PP_BOOL(p(42, s)), s, p, o, m) +# define SEQAN_PP_FOR_42(s, p, o, m) SEQAN_PP_FOR_42_C(SEQAN_PP_BOOL(p(43, s)), s, p, o, m) +# define SEQAN_PP_FOR_43(s, p, o, m) SEQAN_PP_FOR_43_C(SEQAN_PP_BOOL(p(44, s)), s, p, o, m) +# define SEQAN_PP_FOR_44(s, p, o, m) SEQAN_PP_FOR_44_C(SEQAN_PP_BOOL(p(45, s)), s, p, o, m) +# define SEQAN_PP_FOR_45(s, p, o, m) SEQAN_PP_FOR_45_C(SEQAN_PP_BOOL(p(46, s)), s, p, o, m) +# define SEQAN_PP_FOR_46(s, p, o, m) SEQAN_PP_FOR_46_C(SEQAN_PP_BOOL(p(47, s)), s, p, o, m) +# define SEQAN_PP_FOR_47(s, p, o, m) SEQAN_PP_FOR_47_C(SEQAN_PP_BOOL(p(48, s)), s, p, o, m) +# define SEQAN_PP_FOR_48(s, p, o, m) SEQAN_PP_FOR_48_C(SEQAN_PP_BOOL(p(49, s)), s, p, o, m) +# define SEQAN_PP_FOR_49(s, p, o, m) SEQAN_PP_FOR_49_C(SEQAN_PP_BOOL(p(50, s)), s, p, o, m) +# define SEQAN_PP_FOR_50(s, p, o, m) SEQAN_PP_FOR_50_C(SEQAN_PP_BOOL(p(51, s)), s, p, o, m) +# define SEQAN_PP_FOR_51(s, p, o, m) SEQAN_PP_FOR_51_C(SEQAN_PP_BOOL(p(52, s)), s, p, o, m) +# define SEQAN_PP_FOR_52(s, p, o, m) SEQAN_PP_FOR_52_C(SEQAN_PP_BOOL(p(53, s)), s, p, o, m) +# define SEQAN_PP_FOR_53(s, p, o, m) SEQAN_PP_FOR_53_C(SEQAN_PP_BOOL(p(54, s)), s, p, o, m) +# define SEQAN_PP_FOR_54(s, p, o, m) SEQAN_PP_FOR_54_C(SEQAN_PP_BOOL(p(55, s)), s, p, o, m) +# define SEQAN_PP_FOR_55(s, p, o, m) SEQAN_PP_FOR_55_C(SEQAN_PP_BOOL(p(56, s)), s, p, o, m) +# define SEQAN_PP_FOR_56(s, p, o, m) SEQAN_PP_FOR_56_C(SEQAN_PP_BOOL(p(57, s)), s, p, o, m) +# define SEQAN_PP_FOR_57(s, p, o, m) SEQAN_PP_FOR_57_C(SEQAN_PP_BOOL(p(58, s)), s, p, o, m) +# define SEQAN_PP_FOR_58(s, p, o, m) SEQAN_PP_FOR_58_C(SEQAN_PP_BOOL(p(59, s)), s, p, o, m) +# define SEQAN_PP_FOR_59(s, p, o, m) SEQAN_PP_FOR_59_C(SEQAN_PP_BOOL(p(60, s)), s, p, o, m) +# define SEQAN_PP_FOR_60(s, p, o, m) SEQAN_PP_FOR_60_C(SEQAN_PP_BOOL(p(61, s)), s, p, o, m) +# define SEQAN_PP_FOR_61(s, p, o, m) SEQAN_PP_FOR_61_C(SEQAN_PP_BOOL(p(62, s)), s, p, o, m) +# define SEQAN_PP_FOR_62(s, p, o, m) SEQAN_PP_FOR_62_C(SEQAN_PP_BOOL(p(63, s)), s, p, o, m) +# define SEQAN_PP_FOR_63(s, p, o, m) SEQAN_PP_FOR_63_C(SEQAN_PP_BOOL(p(64, s)), s, p, o, m) +# define SEQAN_PP_FOR_64(s, p, o, m) SEQAN_PP_FOR_64_C(SEQAN_PP_BOOL(p(65, s)), s, p, o, m) +# define SEQAN_PP_FOR_65(s, p, o, m) SEQAN_PP_FOR_65_C(SEQAN_PP_BOOL(p(66, s)), s, p, o, m) +# define SEQAN_PP_FOR_66(s, p, o, m) SEQAN_PP_FOR_66_C(SEQAN_PP_BOOL(p(67, s)), s, p, o, m) +# define SEQAN_PP_FOR_67(s, p, o, m) SEQAN_PP_FOR_67_C(SEQAN_PP_BOOL(p(68, s)), s, p, o, m) +# define SEQAN_PP_FOR_68(s, p, o, m) SEQAN_PP_FOR_68_C(SEQAN_PP_BOOL(p(69, s)), s, p, o, m) +# define SEQAN_PP_FOR_69(s, p, o, m) SEQAN_PP_FOR_69_C(SEQAN_PP_BOOL(p(70, s)), s, p, o, m) +# define SEQAN_PP_FOR_70(s, p, o, m) SEQAN_PP_FOR_70_C(SEQAN_PP_BOOL(p(71, s)), s, p, o, m) +# define SEQAN_PP_FOR_71(s, p, o, m) SEQAN_PP_FOR_71_C(SEQAN_PP_BOOL(p(72, s)), s, p, o, m) +# define SEQAN_PP_FOR_72(s, p, o, m) SEQAN_PP_FOR_72_C(SEQAN_PP_BOOL(p(73, s)), s, p, o, m) +# define SEQAN_PP_FOR_73(s, p, o, m) SEQAN_PP_FOR_73_C(SEQAN_PP_BOOL(p(74, s)), s, p, o, m) +# define SEQAN_PP_FOR_74(s, p, o, m) SEQAN_PP_FOR_74_C(SEQAN_PP_BOOL(p(75, s)), s, p, o, m) +# define SEQAN_PP_FOR_75(s, p, o, m) SEQAN_PP_FOR_75_C(SEQAN_PP_BOOL(p(76, s)), s, p, o, m) +# define SEQAN_PP_FOR_76(s, p, o, m) SEQAN_PP_FOR_76_C(SEQAN_PP_BOOL(p(77, s)), s, p, o, m) +# define SEQAN_PP_FOR_77(s, p, o, m) SEQAN_PP_FOR_77_C(SEQAN_PP_BOOL(p(78, s)), s, p, o, m) +# define SEQAN_PP_FOR_78(s, p, o, m) SEQAN_PP_FOR_78_C(SEQAN_PP_BOOL(p(79, s)), s, p, o, m) +# define SEQAN_PP_FOR_79(s, p, o, m) SEQAN_PP_FOR_79_C(SEQAN_PP_BOOL(p(80, s)), s, p, o, m) +# define SEQAN_PP_FOR_80(s, p, o, m) SEQAN_PP_FOR_80_C(SEQAN_PP_BOOL(p(81, s)), s, p, o, m) +# define SEQAN_PP_FOR_81(s, p, o, m) SEQAN_PP_FOR_81_C(SEQAN_PP_BOOL(p(82, s)), s, p, o, m) +# define SEQAN_PP_FOR_82(s, p, o, m) SEQAN_PP_FOR_82_C(SEQAN_PP_BOOL(p(83, s)), s, p, o, m) +# define SEQAN_PP_FOR_83(s, p, o, m) SEQAN_PP_FOR_83_C(SEQAN_PP_BOOL(p(84, s)), s, p, o, m) +# define SEQAN_PP_FOR_84(s, p, o, m) SEQAN_PP_FOR_84_C(SEQAN_PP_BOOL(p(85, s)), s, p, o, m) +# define SEQAN_PP_FOR_85(s, p, o, m) SEQAN_PP_FOR_85_C(SEQAN_PP_BOOL(p(86, s)), s, p, o, m) +# define SEQAN_PP_FOR_86(s, p, o, m) SEQAN_PP_FOR_86_C(SEQAN_PP_BOOL(p(87, s)), s, p, o, m) +# define SEQAN_PP_FOR_87(s, p, o, m) SEQAN_PP_FOR_87_C(SEQAN_PP_BOOL(p(88, s)), s, p, o, m) +# define SEQAN_PP_FOR_88(s, p, o, m) SEQAN_PP_FOR_88_C(SEQAN_PP_BOOL(p(89, s)), s, p, o, m) +# define SEQAN_PP_FOR_89(s, p, o, m) SEQAN_PP_FOR_89_C(SEQAN_PP_BOOL(p(90, s)), s, p, o, m) +# define SEQAN_PP_FOR_90(s, p, o, m) SEQAN_PP_FOR_90_C(SEQAN_PP_BOOL(p(91, s)), s, p, o, m) +# define SEQAN_PP_FOR_91(s, p, o, m) SEQAN_PP_FOR_91_C(SEQAN_PP_BOOL(p(92, s)), s, p, o, m) +# define SEQAN_PP_FOR_92(s, p, o, m) SEQAN_PP_FOR_92_C(SEQAN_PP_BOOL(p(93, s)), s, p, o, m) +# define SEQAN_PP_FOR_93(s, p, o, m) SEQAN_PP_FOR_93_C(SEQAN_PP_BOOL(p(94, s)), s, p, o, m) +# define SEQAN_PP_FOR_94(s, p, o, m) SEQAN_PP_FOR_94_C(SEQAN_PP_BOOL(p(95, s)), s, p, o, m) +# define SEQAN_PP_FOR_95(s, p, o, m) SEQAN_PP_FOR_95_C(SEQAN_PP_BOOL(p(96, s)), s, p, o, m) +# define SEQAN_PP_FOR_96(s, p, o, m) SEQAN_PP_FOR_96_C(SEQAN_PP_BOOL(p(97, s)), s, p, o, m) +# define SEQAN_PP_FOR_97(s, p, o, m) SEQAN_PP_FOR_97_C(SEQAN_PP_BOOL(p(98, s)), s, p, o, m) +# define SEQAN_PP_FOR_98(s, p, o, m) SEQAN_PP_FOR_98_C(SEQAN_PP_BOOL(p(99, s)), s, p, o, m) +# define SEQAN_PP_FOR_99(s, p, o, m) SEQAN_PP_FOR_99_C(SEQAN_PP_BOOL(p(100, s)), s, p, o, m) +# define SEQAN_PP_FOR_100(s, p, o, m) SEQAN_PP_FOR_100_C(SEQAN_PP_BOOL(p(101, s)), s, p, o, m) +# define SEQAN_PP_FOR_101(s, p, o, m) SEQAN_PP_FOR_101_C(SEQAN_PP_BOOL(p(102, s)), s, p, o, m) +# define SEQAN_PP_FOR_102(s, p, o, m) SEQAN_PP_FOR_102_C(SEQAN_PP_BOOL(p(103, s)), s, p, o, m) +# define SEQAN_PP_FOR_103(s, p, o, m) SEQAN_PP_FOR_103_C(SEQAN_PP_BOOL(p(104, s)), s, p, o, m) +# define SEQAN_PP_FOR_104(s, p, o, m) SEQAN_PP_FOR_104_C(SEQAN_PP_BOOL(p(105, s)), s, p, o, m) +# define SEQAN_PP_FOR_105(s, p, o, m) SEQAN_PP_FOR_105_C(SEQAN_PP_BOOL(p(106, s)), s, p, o, m) +# define SEQAN_PP_FOR_106(s, p, o, m) SEQAN_PP_FOR_106_C(SEQAN_PP_BOOL(p(107, s)), s, p, o, m) +# define SEQAN_PP_FOR_107(s, p, o, m) SEQAN_PP_FOR_107_C(SEQAN_PP_BOOL(p(108, s)), s, p, o, m) +# define SEQAN_PP_FOR_108(s, p, o, m) SEQAN_PP_FOR_108_C(SEQAN_PP_BOOL(p(109, s)), s, p, o, m) +# define SEQAN_PP_FOR_109(s, p, o, m) SEQAN_PP_FOR_109_C(SEQAN_PP_BOOL(p(110, s)), s, p, o, m) +# define SEQAN_PP_FOR_110(s, p, o, m) SEQAN_PP_FOR_110_C(SEQAN_PP_BOOL(p(111, s)), s, p, o, m) +# define SEQAN_PP_FOR_111(s, p, o, m) SEQAN_PP_FOR_111_C(SEQAN_PP_BOOL(p(112, s)), s, p, o, m) +# define SEQAN_PP_FOR_112(s, p, o, m) SEQAN_PP_FOR_112_C(SEQAN_PP_BOOL(p(113, s)), s, p, o, m) +# define SEQAN_PP_FOR_113(s, p, o, m) SEQAN_PP_FOR_113_C(SEQAN_PP_BOOL(p(114, s)), s, p, o, m) +# define SEQAN_PP_FOR_114(s, p, o, m) SEQAN_PP_FOR_114_C(SEQAN_PP_BOOL(p(115, s)), s, p, o, m) +# define SEQAN_PP_FOR_115(s, p, o, m) SEQAN_PP_FOR_115_C(SEQAN_PP_BOOL(p(116, s)), s, p, o, m) +# define SEQAN_PP_FOR_116(s, p, o, m) SEQAN_PP_FOR_116_C(SEQAN_PP_BOOL(p(117, s)), s, p, o, m) +# define SEQAN_PP_FOR_117(s, p, o, m) SEQAN_PP_FOR_117_C(SEQAN_PP_BOOL(p(118, s)), s, p, o, m) +# define SEQAN_PP_FOR_118(s, p, o, m) SEQAN_PP_FOR_118_C(SEQAN_PP_BOOL(p(119, s)), s, p, o, m) +# define SEQAN_PP_FOR_119(s, p, o, m) SEQAN_PP_FOR_119_C(SEQAN_PP_BOOL(p(120, s)), s, p, o, m) +# define SEQAN_PP_FOR_120(s, p, o, m) SEQAN_PP_FOR_120_C(SEQAN_PP_BOOL(p(121, s)), s, p, o, m) +# define SEQAN_PP_FOR_121(s, p, o, m) SEQAN_PP_FOR_121_C(SEQAN_PP_BOOL(p(122, s)), s, p, o, m) +# define SEQAN_PP_FOR_122(s, p, o, m) SEQAN_PP_FOR_122_C(SEQAN_PP_BOOL(p(123, s)), s, p, o, m) +# define SEQAN_PP_FOR_123(s, p, o, m) SEQAN_PP_FOR_123_C(SEQAN_PP_BOOL(p(124, s)), s, p, o, m) +# define SEQAN_PP_FOR_124(s, p, o, m) SEQAN_PP_FOR_124_C(SEQAN_PP_BOOL(p(125, s)), s, p, o, m) +# define SEQAN_PP_FOR_125(s, p, o, m) SEQAN_PP_FOR_125_C(SEQAN_PP_BOOL(p(126, s)), s, p, o, m) +# define SEQAN_PP_FOR_126(s, p, o, m) SEQAN_PP_FOR_126_C(SEQAN_PP_BOOL(p(127, s)), s, p, o, m) +# define SEQAN_PP_FOR_127(s, p, o, m) SEQAN_PP_FOR_127_C(SEQAN_PP_BOOL(p(128, s)), s, p, o, m) +# define SEQAN_PP_FOR_128(s, p, o, m) SEQAN_PP_FOR_128_C(SEQAN_PP_BOOL(p(129, s)), s, p, o, m) +# define SEQAN_PP_FOR_129(s, p, o, m) SEQAN_PP_FOR_129_C(SEQAN_PP_BOOL(p(130, s)), s, p, o, m) +# define SEQAN_PP_FOR_130(s, p, o, m) SEQAN_PP_FOR_130_C(SEQAN_PP_BOOL(p(131, s)), s, p, o, m) +# define SEQAN_PP_FOR_131(s, p, o, m) SEQAN_PP_FOR_131_C(SEQAN_PP_BOOL(p(132, s)), s, p, o, m) +# define SEQAN_PP_FOR_132(s, p, o, m) SEQAN_PP_FOR_132_C(SEQAN_PP_BOOL(p(133, s)), s, p, o, m) +# define SEQAN_PP_FOR_133(s, p, o, m) SEQAN_PP_FOR_133_C(SEQAN_PP_BOOL(p(134, s)), s, p, o, m) +# define SEQAN_PP_FOR_134(s, p, o, m) SEQAN_PP_FOR_134_C(SEQAN_PP_BOOL(p(135, s)), s, p, o, m) +# define SEQAN_PP_FOR_135(s, p, o, m) SEQAN_PP_FOR_135_C(SEQAN_PP_BOOL(p(136, s)), s, p, o, m) +# define SEQAN_PP_FOR_136(s, p, o, m) SEQAN_PP_FOR_136_C(SEQAN_PP_BOOL(p(137, s)), s, p, o, m) +# define SEQAN_PP_FOR_137(s, p, o, m) SEQAN_PP_FOR_137_C(SEQAN_PP_BOOL(p(138, s)), s, p, o, m) +# define SEQAN_PP_FOR_138(s, p, o, m) SEQAN_PP_FOR_138_C(SEQAN_PP_BOOL(p(139, s)), s, p, o, m) +# define SEQAN_PP_FOR_139(s, p, o, m) SEQAN_PP_FOR_139_C(SEQAN_PP_BOOL(p(140, s)), s, p, o, m) +# define SEQAN_PP_FOR_140(s, p, o, m) SEQAN_PP_FOR_140_C(SEQAN_PP_BOOL(p(141, s)), s, p, o, m) +# define SEQAN_PP_FOR_141(s, p, o, m) SEQAN_PP_FOR_141_C(SEQAN_PP_BOOL(p(142, s)), s, p, o, m) +# define SEQAN_PP_FOR_142(s, p, o, m) SEQAN_PP_FOR_142_C(SEQAN_PP_BOOL(p(143, s)), s, p, o, m) +# define SEQAN_PP_FOR_143(s, p, o, m) SEQAN_PP_FOR_143_C(SEQAN_PP_BOOL(p(144, s)), s, p, o, m) +# define SEQAN_PP_FOR_144(s, p, o, m) SEQAN_PP_FOR_144_C(SEQAN_PP_BOOL(p(145, s)), s, p, o, m) +# define SEQAN_PP_FOR_145(s, p, o, m) SEQAN_PP_FOR_145_C(SEQAN_PP_BOOL(p(146, s)), s, p, o, m) +# define SEQAN_PP_FOR_146(s, p, o, m) SEQAN_PP_FOR_146_C(SEQAN_PP_BOOL(p(147, s)), s, p, o, m) +# define SEQAN_PP_FOR_147(s, p, o, m) SEQAN_PP_FOR_147_C(SEQAN_PP_BOOL(p(148, s)), s, p, o, m) +# define SEQAN_PP_FOR_148(s, p, o, m) SEQAN_PP_FOR_148_C(SEQAN_PP_BOOL(p(149, s)), s, p, o, m) +# define SEQAN_PP_FOR_149(s, p, o, m) SEQAN_PP_FOR_149_C(SEQAN_PP_BOOL(p(150, s)), s, p, o, m) +# define SEQAN_PP_FOR_150(s, p, o, m) SEQAN_PP_FOR_150_C(SEQAN_PP_BOOL(p(151, s)), s, p, o, m) +# define SEQAN_PP_FOR_151(s, p, o, m) SEQAN_PP_FOR_151_C(SEQAN_PP_BOOL(p(152, s)), s, p, o, m) +# define SEQAN_PP_FOR_152(s, p, o, m) SEQAN_PP_FOR_152_C(SEQAN_PP_BOOL(p(153, s)), s, p, o, m) +# define SEQAN_PP_FOR_153(s, p, o, m) SEQAN_PP_FOR_153_C(SEQAN_PP_BOOL(p(154, s)), s, p, o, m) +# define SEQAN_PP_FOR_154(s, p, o, m) SEQAN_PP_FOR_154_C(SEQAN_PP_BOOL(p(155, s)), s, p, o, m) +# define SEQAN_PP_FOR_155(s, p, o, m) SEQAN_PP_FOR_155_C(SEQAN_PP_BOOL(p(156, s)), s, p, o, m) +# define SEQAN_PP_FOR_156(s, p, o, m) SEQAN_PP_FOR_156_C(SEQAN_PP_BOOL(p(157, s)), s, p, o, m) +# define SEQAN_PP_FOR_157(s, p, o, m) SEQAN_PP_FOR_157_C(SEQAN_PP_BOOL(p(158, s)), s, p, o, m) +# define SEQAN_PP_FOR_158(s, p, o, m) SEQAN_PP_FOR_158_C(SEQAN_PP_BOOL(p(159, s)), s, p, o, m) +# define SEQAN_PP_FOR_159(s, p, o, m) SEQAN_PP_FOR_159_C(SEQAN_PP_BOOL(p(160, s)), s, p, o, m) +# define SEQAN_PP_FOR_160(s, p, o, m) SEQAN_PP_FOR_160_C(SEQAN_PP_BOOL(p(161, s)), s, p, o, m) +# define SEQAN_PP_FOR_161(s, p, o, m) SEQAN_PP_FOR_161_C(SEQAN_PP_BOOL(p(162, s)), s, p, o, m) +# define SEQAN_PP_FOR_162(s, p, o, m) SEQAN_PP_FOR_162_C(SEQAN_PP_BOOL(p(163, s)), s, p, o, m) +# define SEQAN_PP_FOR_163(s, p, o, m) SEQAN_PP_FOR_163_C(SEQAN_PP_BOOL(p(164, s)), s, p, o, m) +# define SEQAN_PP_FOR_164(s, p, o, m) SEQAN_PP_FOR_164_C(SEQAN_PP_BOOL(p(165, s)), s, p, o, m) +# define SEQAN_PP_FOR_165(s, p, o, m) SEQAN_PP_FOR_165_C(SEQAN_PP_BOOL(p(166, s)), s, p, o, m) +# define SEQAN_PP_FOR_166(s, p, o, m) SEQAN_PP_FOR_166_C(SEQAN_PP_BOOL(p(167, s)), s, p, o, m) +# define SEQAN_PP_FOR_167(s, p, o, m) SEQAN_PP_FOR_167_C(SEQAN_PP_BOOL(p(168, s)), s, p, o, m) +# define SEQAN_PP_FOR_168(s, p, o, m) SEQAN_PP_FOR_168_C(SEQAN_PP_BOOL(p(169, s)), s, p, o, m) +# define SEQAN_PP_FOR_169(s, p, o, m) SEQAN_PP_FOR_169_C(SEQAN_PP_BOOL(p(170, s)), s, p, o, m) +# define SEQAN_PP_FOR_170(s, p, o, m) SEQAN_PP_FOR_170_C(SEQAN_PP_BOOL(p(171, s)), s, p, o, m) +# define SEQAN_PP_FOR_171(s, p, o, m) SEQAN_PP_FOR_171_C(SEQAN_PP_BOOL(p(172, s)), s, p, o, m) +# define SEQAN_PP_FOR_172(s, p, o, m) SEQAN_PP_FOR_172_C(SEQAN_PP_BOOL(p(173, s)), s, p, o, m) +# define SEQAN_PP_FOR_173(s, p, o, m) SEQAN_PP_FOR_173_C(SEQAN_PP_BOOL(p(174, s)), s, p, o, m) +# define SEQAN_PP_FOR_174(s, p, o, m) SEQAN_PP_FOR_174_C(SEQAN_PP_BOOL(p(175, s)), s, p, o, m) +# define SEQAN_PP_FOR_175(s, p, o, m) SEQAN_PP_FOR_175_C(SEQAN_PP_BOOL(p(176, s)), s, p, o, m) +# define SEQAN_PP_FOR_176(s, p, o, m) SEQAN_PP_FOR_176_C(SEQAN_PP_BOOL(p(177, s)), s, p, o, m) +# define SEQAN_PP_FOR_177(s, p, o, m) SEQAN_PP_FOR_177_C(SEQAN_PP_BOOL(p(178, s)), s, p, o, m) +# define SEQAN_PP_FOR_178(s, p, o, m) SEQAN_PP_FOR_178_C(SEQAN_PP_BOOL(p(179, s)), s, p, o, m) +# define SEQAN_PP_FOR_179(s, p, o, m) SEQAN_PP_FOR_179_C(SEQAN_PP_BOOL(p(180, s)), s, p, o, m) +# define SEQAN_PP_FOR_180(s, p, o, m) SEQAN_PP_FOR_180_C(SEQAN_PP_BOOL(p(181, s)), s, p, o, m) +# define SEQAN_PP_FOR_181(s, p, o, m) SEQAN_PP_FOR_181_C(SEQAN_PP_BOOL(p(182, s)), s, p, o, m) +# define SEQAN_PP_FOR_182(s, p, o, m) SEQAN_PP_FOR_182_C(SEQAN_PP_BOOL(p(183, s)), s, p, o, m) +# define SEQAN_PP_FOR_183(s, p, o, m) SEQAN_PP_FOR_183_C(SEQAN_PP_BOOL(p(184, s)), s, p, o, m) +# define SEQAN_PP_FOR_184(s, p, o, m) SEQAN_PP_FOR_184_C(SEQAN_PP_BOOL(p(185, s)), s, p, o, m) +# define SEQAN_PP_FOR_185(s, p, o, m) SEQAN_PP_FOR_185_C(SEQAN_PP_BOOL(p(186, s)), s, p, o, m) +# define SEQAN_PP_FOR_186(s, p, o, m) SEQAN_PP_FOR_186_C(SEQAN_PP_BOOL(p(187, s)), s, p, o, m) +# define SEQAN_PP_FOR_187(s, p, o, m) SEQAN_PP_FOR_187_C(SEQAN_PP_BOOL(p(188, s)), s, p, o, m) +# define SEQAN_PP_FOR_188(s, p, o, m) SEQAN_PP_FOR_188_C(SEQAN_PP_BOOL(p(189, s)), s, p, o, m) +# define SEQAN_PP_FOR_189(s, p, o, m) SEQAN_PP_FOR_189_C(SEQAN_PP_BOOL(p(190, s)), s, p, o, m) +# define SEQAN_PP_FOR_190(s, p, o, m) SEQAN_PP_FOR_190_C(SEQAN_PP_BOOL(p(191, s)), s, p, o, m) +# define SEQAN_PP_FOR_191(s, p, o, m) SEQAN_PP_FOR_191_C(SEQAN_PP_BOOL(p(192, s)), s, p, o, m) +# define SEQAN_PP_FOR_192(s, p, o, m) SEQAN_PP_FOR_192_C(SEQAN_PP_BOOL(p(193, s)), s, p, o, m) +# define SEQAN_PP_FOR_193(s, p, o, m) SEQAN_PP_FOR_193_C(SEQAN_PP_BOOL(p(194, s)), s, p, o, m) +# define SEQAN_PP_FOR_194(s, p, o, m) SEQAN_PP_FOR_194_C(SEQAN_PP_BOOL(p(195, s)), s, p, o, m) +# define SEQAN_PP_FOR_195(s, p, o, m) SEQAN_PP_FOR_195_C(SEQAN_PP_BOOL(p(196, s)), s, p, o, m) +# define SEQAN_PP_FOR_196(s, p, o, m) SEQAN_PP_FOR_196_C(SEQAN_PP_BOOL(p(197, s)), s, p, o, m) +# define SEQAN_PP_FOR_197(s, p, o, m) SEQAN_PP_FOR_197_C(SEQAN_PP_BOOL(p(198, s)), s, p, o, m) +# define SEQAN_PP_FOR_198(s, p, o, m) SEQAN_PP_FOR_198_C(SEQAN_PP_BOOL(p(199, s)), s, p, o, m) +# define SEQAN_PP_FOR_199(s, p, o, m) SEQAN_PP_FOR_199_C(SEQAN_PP_BOOL(p(200, s)), s, p, o, m) +# define SEQAN_PP_FOR_200(s, p, o, m) SEQAN_PP_FOR_200_C(SEQAN_PP_BOOL(p(201, s)), s, p, o, m) +# define SEQAN_PP_FOR_201(s, p, o, m) SEQAN_PP_FOR_201_C(SEQAN_PP_BOOL(p(202, s)), s, p, o, m) +# define SEQAN_PP_FOR_202(s, p, o, m) SEQAN_PP_FOR_202_C(SEQAN_PP_BOOL(p(203, s)), s, p, o, m) +# define SEQAN_PP_FOR_203(s, p, o, m) SEQAN_PP_FOR_203_C(SEQAN_PP_BOOL(p(204, s)), s, p, o, m) +# define SEQAN_PP_FOR_204(s, p, o, m) SEQAN_PP_FOR_204_C(SEQAN_PP_BOOL(p(205, s)), s, p, o, m) +# define SEQAN_PP_FOR_205(s, p, o, m) SEQAN_PP_FOR_205_C(SEQAN_PP_BOOL(p(206, s)), s, p, o, m) +# define SEQAN_PP_FOR_206(s, p, o, m) SEQAN_PP_FOR_206_C(SEQAN_PP_BOOL(p(207, s)), s, p, o, m) +# define SEQAN_PP_FOR_207(s, p, o, m) SEQAN_PP_FOR_207_C(SEQAN_PP_BOOL(p(208, s)), s, p, o, m) +# define SEQAN_PP_FOR_208(s, p, o, m) SEQAN_PP_FOR_208_C(SEQAN_PP_BOOL(p(209, s)), s, p, o, m) +# define SEQAN_PP_FOR_209(s, p, o, m) SEQAN_PP_FOR_209_C(SEQAN_PP_BOOL(p(210, s)), s, p, o, m) +# define SEQAN_PP_FOR_210(s, p, o, m) SEQAN_PP_FOR_210_C(SEQAN_PP_BOOL(p(211, s)), s, p, o, m) +# define SEQAN_PP_FOR_211(s, p, o, m) SEQAN_PP_FOR_211_C(SEQAN_PP_BOOL(p(212, s)), s, p, o, m) +# define SEQAN_PP_FOR_212(s, p, o, m) SEQAN_PP_FOR_212_C(SEQAN_PP_BOOL(p(213, s)), s, p, o, m) +# define SEQAN_PP_FOR_213(s, p, o, m) SEQAN_PP_FOR_213_C(SEQAN_PP_BOOL(p(214, s)), s, p, o, m) +# define SEQAN_PP_FOR_214(s, p, o, m) SEQAN_PP_FOR_214_C(SEQAN_PP_BOOL(p(215, s)), s, p, o, m) +# define SEQAN_PP_FOR_215(s, p, o, m) SEQAN_PP_FOR_215_C(SEQAN_PP_BOOL(p(216, s)), s, p, o, m) +# define SEQAN_PP_FOR_216(s, p, o, m) SEQAN_PP_FOR_216_C(SEQAN_PP_BOOL(p(217, s)), s, p, o, m) +# define SEQAN_PP_FOR_217(s, p, o, m) SEQAN_PP_FOR_217_C(SEQAN_PP_BOOL(p(218, s)), s, p, o, m) +# define SEQAN_PP_FOR_218(s, p, o, m) SEQAN_PP_FOR_218_C(SEQAN_PP_BOOL(p(219, s)), s, p, o, m) +# define SEQAN_PP_FOR_219(s, p, o, m) SEQAN_PP_FOR_219_C(SEQAN_PP_BOOL(p(220, s)), s, p, o, m) +# define SEQAN_PP_FOR_220(s, p, o, m) SEQAN_PP_FOR_220_C(SEQAN_PP_BOOL(p(221, s)), s, p, o, m) +# define SEQAN_PP_FOR_221(s, p, o, m) SEQAN_PP_FOR_221_C(SEQAN_PP_BOOL(p(222, s)), s, p, o, m) +# define SEQAN_PP_FOR_222(s, p, o, m) SEQAN_PP_FOR_222_C(SEQAN_PP_BOOL(p(223, s)), s, p, o, m) +# define SEQAN_PP_FOR_223(s, p, o, m) SEQAN_PP_FOR_223_C(SEQAN_PP_BOOL(p(224, s)), s, p, o, m) +# define SEQAN_PP_FOR_224(s, p, o, m) SEQAN_PP_FOR_224_C(SEQAN_PP_BOOL(p(225, s)), s, p, o, m) +# define SEQAN_PP_FOR_225(s, p, o, m) SEQAN_PP_FOR_225_C(SEQAN_PP_BOOL(p(226, s)), s, p, o, m) +# define SEQAN_PP_FOR_226(s, p, o, m) SEQAN_PP_FOR_226_C(SEQAN_PP_BOOL(p(227, s)), s, p, o, m) +# define SEQAN_PP_FOR_227(s, p, o, m) SEQAN_PP_FOR_227_C(SEQAN_PP_BOOL(p(228, s)), s, p, o, m) +# define SEQAN_PP_FOR_228(s, p, o, m) SEQAN_PP_FOR_228_C(SEQAN_PP_BOOL(p(229, s)), s, p, o, m) +# define SEQAN_PP_FOR_229(s, p, o, m) SEQAN_PP_FOR_229_C(SEQAN_PP_BOOL(p(230, s)), s, p, o, m) +# define SEQAN_PP_FOR_230(s, p, o, m) SEQAN_PP_FOR_230_C(SEQAN_PP_BOOL(p(231, s)), s, p, o, m) +# define SEQAN_PP_FOR_231(s, p, o, m) SEQAN_PP_FOR_231_C(SEQAN_PP_BOOL(p(232, s)), s, p, o, m) +# define SEQAN_PP_FOR_232(s, p, o, m) SEQAN_PP_FOR_232_C(SEQAN_PP_BOOL(p(233, s)), s, p, o, m) +# define SEQAN_PP_FOR_233(s, p, o, m) SEQAN_PP_FOR_233_C(SEQAN_PP_BOOL(p(234, s)), s, p, o, m) +# define SEQAN_PP_FOR_234(s, p, o, m) SEQAN_PP_FOR_234_C(SEQAN_PP_BOOL(p(235, s)), s, p, o, m) +# define SEQAN_PP_FOR_235(s, p, o, m) SEQAN_PP_FOR_235_C(SEQAN_PP_BOOL(p(236, s)), s, p, o, m) +# define SEQAN_PP_FOR_236(s, p, o, m) SEQAN_PP_FOR_236_C(SEQAN_PP_BOOL(p(237, s)), s, p, o, m) +# define SEQAN_PP_FOR_237(s, p, o, m) SEQAN_PP_FOR_237_C(SEQAN_PP_BOOL(p(238, s)), s, p, o, m) +# define SEQAN_PP_FOR_238(s, p, o, m) SEQAN_PP_FOR_238_C(SEQAN_PP_BOOL(p(239, s)), s, p, o, m) +# define SEQAN_PP_FOR_239(s, p, o, m) SEQAN_PP_FOR_239_C(SEQAN_PP_BOOL(p(240, s)), s, p, o, m) +# define SEQAN_PP_FOR_240(s, p, o, m) SEQAN_PP_FOR_240_C(SEQAN_PP_BOOL(p(241, s)), s, p, o, m) +# define SEQAN_PP_FOR_241(s, p, o, m) SEQAN_PP_FOR_241_C(SEQAN_PP_BOOL(p(242, s)), s, p, o, m) +# define SEQAN_PP_FOR_242(s, p, o, m) SEQAN_PP_FOR_242_C(SEQAN_PP_BOOL(p(243, s)), s, p, o, m) +# define SEQAN_PP_FOR_243(s, p, o, m) SEQAN_PP_FOR_243_C(SEQAN_PP_BOOL(p(244, s)), s, p, o, m) +# define SEQAN_PP_FOR_244(s, p, o, m) SEQAN_PP_FOR_244_C(SEQAN_PP_BOOL(p(245, s)), s, p, o, m) +# define SEQAN_PP_FOR_245(s, p, o, m) SEQAN_PP_FOR_245_C(SEQAN_PP_BOOL(p(246, s)), s, p, o, m) +# define SEQAN_PP_FOR_246(s, p, o, m) SEQAN_PP_FOR_246_C(SEQAN_PP_BOOL(p(247, s)), s, p, o, m) +# define SEQAN_PP_FOR_247(s, p, o, m) SEQAN_PP_FOR_247_C(SEQAN_PP_BOOL(p(248, s)), s, p, o, m) +# define SEQAN_PP_FOR_248(s, p, o, m) SEQAN_PP_FOR_248_C(SEQAN_PP_BOOL(p(249, s)), s, p, o, m) +# define SEQAN_PP_FOR_249(s, p, o, m) SEQAN_PP_FOR_249_C(SEQAN_PP_BOOL(p(250, s)), s, p, o, m) +# define SEQAN_PP_FOR_250(s, p, o, m) SEQAN_PP_FOR_250_C(SEQAN_PP_BOOL(p(251, s)), s, p, o, m) +# define SEQAN_PP_FOR_251(s, p, o, m) SEQAN_PP_FOR_251_C(SEQAN_PP_BOOL(p(252, s)), s, p, o, m) +# define SEQAN_PP_FOR_252(s, p, o, m) SEQAN_PP_FOR_252_C(SEQAN_PP_BOOL(p(253, s)), s, p, o, m) +# define SEQAN_PP_FOR_253(s, p, o, m) SEQAN_PP_FOR_253_C(SEQAN_PP_BOOL(p(254, s)), s, p, o, m) +# define SEQAN_PP_FOR_254(s, p, o, m) SEQAN_PP_FOR_254_C(SEQAN_PP_BOOL(p(255, s)), s, p, o, m) +# define SEQAN_PP_FOR_255(s, p, o, m) SEQAN_PP_FOR_255_C(SEQAN_PP_BOOL(p(256, s)), s, p, o, m) +# define SEQAN_PP_FOR_256(s, p, o, m) SEQAN_PP_FOR_256_C(SEQAN_PP_BOOL(p(257, s)), s, p, o, m) +# +# define SEQAN_PP_FOR_1_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(2, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_2, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(2, s), p, o, m) +# define SEQAN_PP_FOR_2_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(3, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_3, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(3, s), p, o, m) +# define SEQAN_PP_FOR_3_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(4, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_4, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(4, s), p, o, m) +# define SEQAN_PP_FOR_4_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(5, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_5, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(5, s), p, o, m) +# define SEQAN_PP_FOR_5_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(6, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_6, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(6, s), p, o, m) +# define SEQAN_PP_FOR_6_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(7, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_7, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(7, s), p, o, m) +# define SEQAN_PP_FOR_7_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(8, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_8, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(8, s), p, o, m) +# define SEQAN_PP_FOR_8_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(9, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_9, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(9, s), p, o, m) +# define SEQAN_PP_FOR_9_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(10, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_10, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(10, s), p, o, m) +# define SEQAN_PP_FOR_10_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(11, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_11, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(11, s), p, o, m) +# define SEQAN_PP_FOR_11_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(12, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_12, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(12, s), p, o, m) +# define SEQAN_PP_FOR_12_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(13, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_13, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(13, s), p, o, m) +# define SEQAN_PP_FOR_13_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(14, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_14, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(14, s), p, o, m) +# define SEQAN_PP_FOR_14_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(15, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_15, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(15, s), p, o, m) +# define SEQAN_PP_FOR_15_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(16, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_16, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(16, s), p, o, m) +# define SEQAN_PP_FOR_16_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(17, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_17, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(17, s), p, o, m) +# define SEQAN_PP_FOR_17_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(18, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_18, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(18, s), p, o, m) +# define SEQAN_PP_FOR_18_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(19, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_19, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(19, s), p, o, m) +# define SEQAN_PP_FOR_19_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(20, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_20, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(20, s), p, o, m) +# define SEQAN_PP_FOR_20_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(21, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_21, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(21, s), p, o, m) +# define SEQAN_PP_FOR_21_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(22, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_22, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(22, s), p, o, m) +# define SEQAN_PP_FOR_22_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(23, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_23, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(23, s), p, o, m) +# define SEQAN_PP_FOR_23_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(24, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_24, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(24, s), p, o, m) +# define SEQAN_PP_FOR_24_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(25, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_25, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(25, s), p, o, m) +# define SEQAN_PP_FOR_25_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(26, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_26, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(26, s), p, o, m) +# define SEQAN_PP_FOR_26_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(27, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_27, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(27, s), p, o, m) +# define SEQAN_PP_FOR_27_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(28, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_28, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(28, s), p, o, m) +# define SEQAN_PP_FOR_28_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(29, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_29, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(29, s), p, o, m) +# define SEQAN_PP_FOR_29_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(30, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_30, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(30, s), p, o, m) +# define SEQAN_PP_FOR_30_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(31, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_31, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(31, s), p, o, m) +# define SEQAN_PP_FOR_31_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(32, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_32, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(32, s), p, o, m) +# define SEQAN_PP_FOR_32_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(33, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_33, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(33, s), p, o, m) +# define SEQAN_PP_FOR_33_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(34, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_34, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(34, s), p, o, m) +# define SEQAN_PP_FOR_34_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(35, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_35, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(35, s), p, o, m) +# define SEQAN_PP_FOR_35_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(36, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_36, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(36, s), p, o, m) +# define SEQAN_PP_FOR_36_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(37, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_37, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(37, s), p, o, m) +# define SEQAN_PP_FOR_37_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(38, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_38, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(38, s), p, o, m) +# define SEQAN_PP_FOR_38_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(39, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_39, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(39, s), p, o, m) +# define SEQAN_PP_FOR_39_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(40, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_40, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(40, s), p, o, m) +# define SEQAN_PP_FOR_40_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(41, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_41, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(41, s), p, o, m) +# define SEQAN_PP_FOR_41_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(42, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_42, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(42, s), p, o, m) +# define SEQAN_PP_FOR_42_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(43, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_43, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(43, s), p, o, m) +# define SEQAN_PP_FOR_43_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(44, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_44, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(44, s), p, o, m) +# define SEQAN_PP_FOR_44_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(45, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_45, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(45, s), p, o, m) +# define SEQAN_PP_FOR_45_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(46, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_46, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(46, s), p, o, m) +# define SEQAN_PP_FOR_46_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(47, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_47, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(47, s), p, o, m) +# define SEQAN_PP_FOR_47_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(48, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_48, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(48, s), p, o, m) +# define SEQAN_PP_FOR_48_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(49, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_49, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(49, s), p, o, m) +# define SEQAN_PP_FOR_49_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(50, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_50, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(50, s), p, o, m) +# define SEQAN_PP_FOR_50_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(51, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_51, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(51, s), p, o, m) +# define SEQAN_PP_FOR_51_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(52, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_52, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(52, s), p, o, m) +# define SEQAN_PP_FOR_52_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(53, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_53, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(53, s), p, o, m) +# define SEQAN_PP_FOR_53_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(54, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_54, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(54, s), p, o, m) +# define SEQAN_PP_FOR_54_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(55, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_55, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(55, s), p, o, m) +# define SEQAN_PP_FOR_55_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(56, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_56, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(56, s), p, o, m) +# define SEQAN_PP_FOR_56_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(57, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_57, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(57, s), p, o, m) +# define SEQAN_PP_FOR_57_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(58, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_58, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(58, s), p, o, m) +# define SEQAN_PP_FOR_58_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(59, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_59, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(59, s), p, o, m) +# define SEQAN_PP_FOR_59_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(60, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_60, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(60, s), p, o, m) +# define SEQAN_PP_FOR_60_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(61, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_61, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(61, s), p, o, m) +# define SEQAN_PP_FOR_61_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(62, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_62, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(62, s), p, o, m) +# define SEQAN_PP_FOR_62_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(63, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_63, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(63, s), p, o, m) +# define SEQAN_PP_FOR_63_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(64, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_64, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(64, s), p, o, m) +# define SEQAN_PP_FOR_64_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(65, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_65, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(65, s), p, o, m) +# define SEQAN_PP_FOR_65_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(66, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_66, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(66, s), p, o, m) +# define SEQAN_PP_FOR_66_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(67, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_67, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(67, s), p, o, m) +# define SEQAN_PP_FOR_67_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(68, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_68, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(68, s), p, o, m) +# define SEQAN_PP_FOR_68_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(69, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_69, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(69, s), p, o, m) +# define SEQAN_PP_FOR_69_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(70, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_70, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(70, s), p, o, m) +# define SEQAN_PP_FOR_70_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(71, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_71, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(71, s), p, o, m) +# define SEQAN_PP_FOR_71_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(72, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_72, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(72, s), p, o, m) +# define SEQAN_PP_FOR_72_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(73, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_73, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(73, s), p, o, m) +# define SEQAN_PP_FOR_73_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(74, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_74, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(74, s), p, o, m) +# define SEQAN_PP_FOR_74_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(75, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_75, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(75, s), p, o, m) +# define SEQAN_PP_FOR_75_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(76, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_76, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(76, s), p, o, m) +# define SEQAN_PP_FOR_76_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(77, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_77, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(77, s), p, o, m) +# define SEQAN_PP_FOR_77_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(78, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_78, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(78, s), p, o, m) +# define SEQAN_PP_FOR_78_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(79, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_79, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(79, s), p, o, m) +# define SEQAN_PP_FOR_79_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(80, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_80, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(80, s), p, o, m) +# define SEQAN_PP_FOR_80_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(81, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_81, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(81, s), p, o, m) +# define SEQAN_PP_FOR_81_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(82, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_82, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(82, s), p, o, m) +# define SEQAN_PP_FOR_82_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(83, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_83, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(83, s), p, o, m) +# define SEQAN_PP_FOR_83_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(84, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_84, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(84, s), p, o, m) +# define SEQAN_PP_FOR_84_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(85, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_85, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(85, s), p, o, m) +# define SEQAN_PP_FOR_85_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(86, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_86, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(86, s), p, o, m) +# define SEQAN_PP_FOR_86_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(87, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_87, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(87, s), p, o, m) +# define SEQAN_PP_FOR_87_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(88, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_88, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(88, s), p, o, m) +# define SEQAN_PP_FOR_88_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(89, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_89, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(89, s), p, o, m) +# define SEQAN_PP_FOR_89_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(90, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_90, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(90, s), p, o, m) +# define SEQAN_PP_FOR_90_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(91, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_91, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(91, s), p, o, m) +# define SEQAN_PP_FOR_91_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(92, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_92, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(92, s), p, o, m) +# define SEQAN_PP_FOR_92_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(93, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_93, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(93, s), p, o, m) +# define SEQAN_PP_FOR_93_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(94, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_94, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(94, s), p, o, m) +# define SEQAN_PP_FOR_94_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(95, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_95, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(95, s), p, o, m) +# define SEQAN_PP_FOR_95_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(96, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_96, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(96, s), p, o, m) +# define SEQAN_PP_FOR_96_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(97, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_97, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(97, s), p, o, m) +# define SEQAN_PP_FOR_97_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(98, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_98, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(98, s), p, o, m) +# define SEQAN_PP_FOR_98_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(99, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_99, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(99, s), p, o, m) +# define SEQAN_PP_FOR_99_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(100, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_100, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(100, s), p, o, m) +# define SEQAN_PP_FOR_100_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(101, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_101, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(101, s), p, o, m) +# define SEQAN_PP_FOR_101_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(102, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_102, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(102, s), p, o, m) +# define SEQAN_PP_FOR_102_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(103, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_103, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(103, s), p, o, m) +# define SEQAN_PP_FOR_103_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(104, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_104, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(104, s), p, o, m) +# define SEQAN_PP_FOR_104_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(105, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_105, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(105, s), p, o, m) +# define SEQAN_PP_FOR_105_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(106, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_106, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(106, s), p, o, m) +# define SEQAN_PP_FOR_106_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(107, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_107, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(107, s), p, o, m) +# define SEQAN_PP_FOR_107_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(108, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_108, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(108, s), p, o, m) +# define SEQAN_PP_FOR_108_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(109, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_109, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(109, s), p, o, m) +# define SEQAN_PP_FOR_109_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(110, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_110, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(110, s), p, o, m) +# define SEQAN_PP_FOR_110_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(111, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_111, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(111, s), p, o, m) +# define SEQAN_PP_FOR_111_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(112, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_112, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(112, s), p, o, m) +# define SEQAN_PP_FOR_112_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(113, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_113, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(113, s), p, o, m) +# define SEQAN_PP_FOR_113_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(114, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_114, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(114, s), p, o, m) +# define SEQAN_PP_FOR_114_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(115, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_115, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(115, s), p, o, m) +# define SEQAN_PP_FOR_115_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(116, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_116, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(116, s), p, o, m) +# define SEQAN_PP_FOR_116_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(117, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_117, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(117, s), p, o, m) +# define SEQAN_PP_FOR_117_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(118, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_118, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(118, s), p, o, m) +# define SEQAN_PP_FOR_118_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(119, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_119, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(119, s), p, o, m) +# define SEQAN_PP_FOR_119_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(120, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_120, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(120, s), p, o, m) +# define SEQAN_PP_FOR_120_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(121, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_121, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(121, s), p, o, m) +# define SEQAN_PP_FOR_121_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(122, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_122, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(122, s), p, o, m) +# define SEQAN_PP_FOR_122_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(123, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_123, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(123, s), p, o, m) +# define SEQAN_PP_FOR_123_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(124, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_124, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(124, s), p, o, m) +# define SEQAN_PP_FOR_124_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(125, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_125, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(125, s), p, o, m) +# define SEQAN_PP_FOR_125_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(126, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_126, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(126, s), p, o, m) +# define SEQAN_PP_FOR_126_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(127, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_127, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(127, s), p, o, m) +# define SEQAN_PP_FOR_127_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(128, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_128, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(128, s), p, o, m) +# define SEQAN_PP_FOR_128_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(129, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_129, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(129, s), p, o, m) +# define SEQAN_PP_FOR_129_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(130, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_130, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(130, s), p, o, m) +# define SEQAN_PP_FOR_130_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(131, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_131, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(131, s), p, o, m) +# define SEQAN_PP_FOR_131_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(132, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_132, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(132, s), p, o, m) +# define SEQAN_PP_FOR_132_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(133, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_133, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(133, s), p, o, m) +# define SEQAN_PP_FOR_133_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(134, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_134, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(134, s), p, o, m) +# define SEQAN_PP_FOR_134_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(135, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_135, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(135, s), p, o, m) +# define SEQAN_PP_FOR_135_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(136, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_136, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(136, s), p, o, m) +# define SEQAN_PP_FOR_136_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(137, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_137, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(137, s), p, o, m) +# define SEQAN_PP_FOR_137_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(138, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_138, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(138, s), p, o, m) +# define SEQAN_PP_FOR_138_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(139, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_139, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(139, s), p, o, m) +# define SEQAN_PP_FOR_139_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(140, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_140, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(140, s), p, o, m) +# define SEQAN_PP_FOR_140_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(141, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_141, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(141, s), p, o, m) +# define SEQAN_PP_FOR_141_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(142, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_142, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(142, s), p, o, m) +# define SEQAN_PP_FOR_142_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(143, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_143, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(143, s), p, o, m) +# define SEQAN_PP_FOR_143_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(144, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_144, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(144, s), p, o, m) +# define SEQAN_PP_FOR_144_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(145, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_145, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(145, s), p, o, m) +# define SEQAN_PP_FOR_145_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(146, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_146, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(146, s), p, o, m) +# define SEQAN_PP_FOR_146_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(147, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_147, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(147, s), p, o, m) +# define SEQAN_PP_FOR_147_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(148, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_148, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(148, s), p, o, m) +# define SEQAN_PP_FOR_148_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(149, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_149, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(149, s), p, o, m) +# define SEQAN_PP_FOR_149_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(150, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_150, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(150, s), p, o, m) +# define SEQAN_PP_FOR_150_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(151, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_151, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(151, s), p, o, m) +# define SEQAN_PP_FOR_151_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(152, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_152, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(152, s), p, o, m) +# define SEQAN_PP_FOR_152_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(153, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_153, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(153, s), p, o, m) +# define SEQAN_PP_FOR_153_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(154, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_154, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(154, s), p, o, m) +# define SEQAN_PP_FOR_154_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(155, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_155, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(155, s), p, o, m) +# define SEQAN_PP_FOR_155_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(156, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_156, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(156, s), p, o, m) +# define SEQAN_PP_FOR_156_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(157, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_157, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(157, s), p, o, m) +# define SEQAN_PP_FOR_157_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(158, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_158, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(158, s), p, o, m) +# define SEQAN_PP_FOR_158_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(159, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_159, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(159, s), p, o, m) +# define SEQAN_PP_FOR_159_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(160, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_160, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(160, s), p, o, m) +# define SEQAN_PP_FOR_160_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(161, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_161, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(161, s), p, o, m) +# define SEQAN_PP_FOR_161_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(162, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_162, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(162, s), p, o, m) +# define SEQAN_PP_FOR_162_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(163, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_163, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(163, s), p, o, m) +# define SEQAN_PP_FOR_163_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(164, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_164, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(164, s), p, o, m) +# define SEQAN_PP_FOR_164_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(165, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_165, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(165, s), p, o, m) +# define SEQAN_PP_FOR_165_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(166, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_166, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(166, s), p, o, m) +# define SEQAN_PP_FOR_166_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(167, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_167, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(167, s), p, o, m) +# define SEQAN_PP_FOR_167_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(168, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_168, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(168, s), p, o, m) +# define SEQAN_PP_FOR_168_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(169, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_169, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(169, s), p, o, m) +# define SEQAN_PP_FOR_169_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(170, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_170, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(170, s), p, o, m) +# define SEQAN_PP_FOR_170_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(171, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_171, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(171, s), p, o, m) +# define SEQAN_PP_FOR_171_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(172, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_172, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(172, s), p, o, m) +# define SEQAN_PP_FOR_172_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(173, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_173, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(173, s), p, o, m) +# define SEQAN_PP_FOR_173_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(174, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_174, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(174, s), p, o, m) +# define SEQAN_PP_FOR_174_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(175, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_175, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(175, s), p, o, m) +# define SEQAN_PP_FOR_175_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(176, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_176, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(176, s), p, o, m) +# define SEQAN_PP_FOR_176_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(177, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_177, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(177, s), p, o, m) +# define SEQAN_PP_FOR_177_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(178, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_178, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(178, s), p, o, m) +# define SEQAN_PP_FOR_178_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(179, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_179, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(179, s), p, o, m) +# define SEQAN_PP_FOR_179_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(180, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_180, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(180, s), p, o, m) +# define SEQAN_PP_FOR_180_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(181, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_181, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(181, s), p, o, m) +# define SEQAN_PP_FOR_181_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(182, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_182, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(182, s), p, o, m) +# define SEQAN_PP_FOR_182_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(183, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_183, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(183, s), p, o, m) +# define SEQAN_PP_FOR_183_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(184, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_184, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(184, s), p, o, m) +# define SEQAN_PP_FOR_184_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(185, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_185, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(185, s), p, o, m) +# define SEQAN_PP_FOR_185_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(186, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_186, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(186, s), p, o, m) +# define SEQAN_PP_FOR_186_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(187, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_187, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(187, s), p, o, m) +# define SEQAN_PP_FOR_187_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(188, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_188, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(188, s), p, o, m) +# define SEQAN_PP_FOR_188_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(189, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_189, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(189, s), p, o, m) +# define SEQAN_PP_FOR_189_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(190, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_190, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(190, s), p, o, m) +# define SEQAN_PP_FOR_190_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(191, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_191, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(191, s), p, o, m) +# define SEQAN_PP_FOR_191_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(192, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_192, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(192, s), p, o, m) +# define SEQAN_PP_FOR_192_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(193, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_193, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(193, s), p, o, m) +# define SEQAN_PP_FOR_193_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(194, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_194, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(194, s), p, o, m) +# define SEQAN_PP_FOR_194_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(195, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_195, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(195, s), p, o, m) +# define SEQAN_PP_FOR_195_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(196, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_196, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(196, s), p, o, m) +# define SEQAN_PP_FOR_196_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(197, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_197, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(197, s), p, o, m) +# define SEQAN_PP_FOR_197_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(198, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_198, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(198, s), p, o, m) +# define SEQAN_PP_FOR_198_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(199, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_199, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(199, s), p, o, m) +# define SEQAN_PP_FOR_199_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(200, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_200, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(200, s), p, o, m) +# define SEQAN_PP_FOR_200_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(201, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_201, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(201, s), p, o, m) +# define SEQAN_PP_FOR_201_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(202, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_202, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(202, s), p, o, m) +# define SEQAN_PP_FOR_202_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(203, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_203, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(203, s), p, o, m) +# define SEQAN_PP_FOR_203_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(204, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_204, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(204, s), p, o, m) +# define SEQAN_PP_FOR_204_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(205, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_205, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(205, s), p, o, m) +# define SEQAN_PP_FOR_205_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(206, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_206, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(206, s), p, o, m) +# define SEQAN_PP_FOR_206_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(207, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_207, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(207, s), p, o, m) +# define SEQAN_PP_FOR_207_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(208, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_208, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(208, s), p, o, m) +# define SEQAN_PP_FOR_208_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(209, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_209, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(209, s), p, o, m) +# define SEQAN_PP_FOR_209_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(210, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_210, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(210, s), p, o, m) +# define SEQAN_PP_FOR_210_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(211, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_211, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(211, s), p, o, m) +# define SEQAN_PP_FOR_211_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(212, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_212, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(212, s), p, o, m) +# define SEQAN_PP_FOR_212_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(213, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_213, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(213, s), p, o, m) +# define SEQAN_PP_FOR_213_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(214, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_214, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(214, s), p, o, m) +# define SEQAN_PP_FOR_214_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(215, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_215, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(215, s), p, o, m) +# define SEQAN_PP_FOR_215_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(216, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_216, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(216, s), p, o, m) +# define SEQAN_PP_FOR_216_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(217, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_217, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(217, s), p, o, m) +# define SEQAN_PP_FOR_217_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(218, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_218, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(218, s), p, o, m) +# define SEQAN_PP_FOR_218_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(219, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_219, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(219, s), p, o, m) +# define SEQAN_PP_FOR_219_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(220, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_220, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(220, s), p, o, m) +# define SEQAN_PP_FOR_220_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(221, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_221, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(221, s), p, o, m) +# define SEQAN_PP_FOR_221_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(222, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_222, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(222, s), p, o, m) +# define SEQAN_PP_FOR_222_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(223, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_223, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(223, s), p, o, m) +# define SEQAN_PP_FOR_223_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(224, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_224, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(224, s), p, o, m) +# define SEQAN_PP_FOR_224_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(225, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_225, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(225, s), p, o, m) +# define SEQAN_PP_FOR_225_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(226, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_226, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(226, s), p, o, m) +# define SEQAN_PP_FOR_226_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(227, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_227, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(227, s), p, o, m) +# define SEQAN_PP_FOR_227_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(228, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_228, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(228, s), p, o, m) +# define SEQAN_PP_FOR_228_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(229, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_229, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(229, s), p, o, m) +# define SEQAN_PP_FOR_229_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(230, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_230, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(230, s), p, o, m) +# define SEQAN_PP_FOR_230_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(231, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_231, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(231, s), p, o, m) +# define SEQAN_PP_FOR_231_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(232, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_232, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(232, s), p, o, m) +# define SEQAN_PP_FOR_232_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(233, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_233, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(233, s), p, o, m) +# define SEQAN_PP_FOR_233_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(234, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_234, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(234, s), p, o, m) +# define SEQAN_PP_FOR_234_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(235, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_235, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(235, s), p, o, m) +# define SEQAN_PP_FOR_235_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(236, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_236, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(236, s), p, o, m) +# define SEQAN_PP_FOR_236_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(237, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_237, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(237, s), p, o, m) +# define SEQAN_PP_FOR_237_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(238, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_238, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(238, s), p, o, m) +# define SEQAN_PP_FOR_238_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(239, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_239, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(239, s), p, o, m) +# define SEQAN_PP_FOR_239_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(240, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_240, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(240, s), p, o, m) +# define SEQAN_PP_FOR_240_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(241, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_241, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(241, s), p, o, m) +# define SEQAN_PP_FOR_241_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(242, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_242, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(242, s), p, o, m) +# define SEQAN_PP_FOR_242_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(243, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_243, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(243, s), p, o, m) +# define SEQAN_PP_FOR_243_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(244, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_244, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(244, s), p, o, m) +# define SEQAN_PP_FOR_244_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(245, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_245, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(245, s), p, o, m) +# define SEQAN_PP_FOR_245_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(246, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_246, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(246, s), p, o, m) +# define SEQAN_PP_FOR_246_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(247, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_247, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(247, s), p, o, m) +# define SEQAN_PP_FOR_247_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(248, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_248, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(248, s), p, o, m) +# define SEQAN_PP_FOR_248_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(249, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_249, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(249, s), p, o, m) +# define SEQAN_PP_FOR_249_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(250, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_250, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(250, s), p, o, m) +# define SEQAN_PP_FOR_250_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(251, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_251, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(251, s), p, o, m) +# define SEQAN_PP_FOR_251_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(252, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_252, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(252, s), p, o, m) +# define SEQAN_PP_FOR_252_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(253, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_253, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(253, s), p, o, m) +# define SEQAN_PP_FOR_253_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(254, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_254, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(254, s), p, o, m) +# define SEQAN_PP_FOR_254_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(255, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_255, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(255, s), p, o, m) +# define SEQAN_PP_FOR_255_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(256, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_256, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(256, s), p, o, m) +# define SEQAN_PP_FOR_256_C(c, s, p, o, m) SEQAN_PP_IIF(c, m, SEQAN_PP_TUPLE_EAT_2)(257, s) SEQAN_PP_IIF(c, SEQAN_PP_FOR_257, SEQAN_PP_TUPLE_EAT_4)(SEQAN_PP_EXPR_IIF(c, o)(257, s), p, o, m) + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/detail/auto_rec.hpp <== +// -------------------------------------------------------------------------- + +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # include +# +// # if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_DMC() +// # include +// # else +# +// # ifndef SEQAN_PREPROCESSOR_DETAIL_AUTO_REC_HPP +// # define SEQAN_PREPROCESSOR_DETAIL_AUTO_REC_HPP +# +// # include +# +# /* SEQAN_PP_AUTO_REC */ +# +# define SEQAN_PP_AUTO_REC(pred, n) SEQAN_PP_NODE_ENTRY_ ## n(pred) +# +# define SEQAN_PP_NODE_ENTRY_256(p) SEQAN_PP_NODE_128(p)(p)(p)(p)(p)(p)(p)(p) +# define SEQAN_PP_NODE_ENTRY_128(p) SEQAN_PP_NODE_64(p)(p)(p)(p)(p)(p)(p) +# define SEQAN_PP_NODE_ENTRY_64(p) SEQAN_PP_NODE_32(p)(p)(p)(p)(p)(p) +# define SEQAN_PP_NODE_ENTRY_32(p) SEQAN_PP_NODE_16(p)(p)(p)(p)(p) +# define SEQAN_PP_NODE_ENTRY_16(p) SEQAN_PP_NODE_8(p)(p)(p)(p) +# define SEQAN_PP_NODE_ENTRY_8(p) SEQAN_PP_NODE_4(p)(p)(p) +# define SEQAN_PP_NODE_ENTRY_4(p) SEQAN_PP_NODE_2(p)(p) +# define SEQAN_PP_NODE_ENTRY_2(p) SEQAN_PP_NODE_1(p) +# +# define SEQAN_PP_NODE_128(p) SEQAN_PP_IIF(p(128), SEQAN_PP_NODE_64, SEQAN_PP_NODE_192) +# define SEQAN_PP_NODE_64(p) SEQAN_PP_IIF(p(64), SEQAN_PP_NODE_32, SEQAN_PP_NODE_96) +# define SEQAN_PP_NODE_32(p) SEQAN_PP_IIF(p(32), SEQAN_PP_NODE_16, SEQAN_PP_NODE_48) +# define SEQAN_PP_NODE_16(p) SEQAN_PP_IIF(p(16), SEQAN_PP_NODE_8, SEQAN_PP_NODE_24) +# define SEQAN_PP_NODE_8(p) SEQAN_PP_IIF(p(8), SEQAN_PP_NODE_4, SEQAN_PP_NODE_12) +# define SEQAN_PP_NODE_4(p) SEQAN_PP_IIF(p(4), SEQAN_PP_NODE_2, SEQAN_PP_NODE_6) +# define SEQAN_PP_NODE_2(p) SEQAN_PP_IIF(p(2), SEQAN_PP_NODE_1, SEQAN_PP_NODE_3) +# define SEQAN_PP_NODE_1(p) SEQAN_PP_IIF(p(1), 1, 2) +# define SEQAN_PP_NODE_3(p) SEQAN_PP_IIF(p(3), 3, 4) +# define SEQAN_PP_NODE_6(p) SEQAN_PP_IIF(p(6), SEQAN_PP_NODE_5, SEQAN_PP_NODE_7) +# define SEQAN_PP_NODE_5(p) SEQAN_PP_IIF(p(5), 5, 6) +# define SEQAN_PP_NODE_7(p) SEQAN_PP_IIF(p(7), 7, 8) +# define SEQAN_PP_NODE_12(p) SEQAN_PP_IIF(p(12), SEQAN_PP_NODE_10, SEQAN_PP_NODE_14) +# define SEQAN_PP_NODE_10(p) SEQAN_PP_IIF(p(10), SEQAN_PP_NODE_9, SEQAN_PP_NODE_11) +# define SEQAN_PP_NODE_9(p) SEQAN_PP_IIF(p(9), 9, 10) +# define SEQAN_PP_NODE_11(p) SEQAN_PP_IIF(p(11), 11, 12) +# define SEQAN_PP_NODE_14(p) SEQAN_PP_IIF(p(14), SEQAN_PP_NODE_13, SEQAN_PP_NODE_15) +# define SEQAN_PP_NODE_13(p) SEQAN_PP_IIF(p(13), 13, 14) +# define SEQAN_PP_NODE_15(p) SEQAN_PP_IIF(p(15), 15, 16) +# define SEQAN_PP_NODE_24(p) SEQAN_PP_IIF(p(24), SEQAN_PP_NODE_20, SEQAN_PP_NODE_28) +# define SEQAN_PP_NODE_20(p) SEQAN_PP_IIF(p(20), SEQAN_PP_NODE_18, SEQAN_PP_NODE_22) +# define SEQAN_PP_NODE_18(p) SEQAN_PP_IIF(p(18), SEQAN_PP_NODE_17, SEQAN_PP_NODE_19) +# define SEQAN_PP_NODE_17(p) SEQAN_PP_IIF(p(17), 17, 18) +# define SEQAN_PP_NODE_19(p) SEQAN_PP_IIF(p(19), 19, 20) +# define SEQAN_PP_NODE_22(p) SEQAN_PP_IIF(p(22), SEQAN_PP_NODE_21, SEQAN_PP_NODE_23) +# define SEQAN_PP_NODE_21(p) SEQAN_PP_IIF(p(21), 21, 22) +# define SEQAN_PP_NODE_23(p) SEQAN_PP_IIF(p(23), 23, 24) +# define SEQAN_PP_NODE_28(p) SEQAN_PP_IIF(p(28), SEQAN_PP_NODE_26, SEQAN_PP_NODE_30) +# define SEQAN_PP_NODE_26(p) SEQAN_PP_IIF(p(26), SEQAN_PP_NODE_25, SEQAN_PP_NODE_27) +# define SEQAN_PP_NODE_25(p) SEQAN_PP_IIF(p(25), 25, 26) +# define SEQAN_PP_NODE_27(p) SEQAN_PP_IIF(p(27), 27, 28) +# define SEQAN_PP_NODE_30(p) SEQAN_PP_IIF(p(30), SEQAN_PP_NODE_29, SEQAN_PP_NODE_31) +# define SEQAN_PP_NODE_29(p) SEQAN_PP_IIF(p(29), 29, 30) +# define SEQAN_PP_NODE_31(p) SEQAN_PP_IIF(p(31), 31, 32) +# define SEQAN_PP_NODE_48(p) SEQAN_PP_IIF(p(48), SEQAN_PP_NODE_40, SEQAN_PP_NODE_56) +# define SEQAN_PP_NODE_40(p) SEQAN_PP_IIF(p(40), SEQAN_PP_NODE_36, SEQAN_PP_NODE_44) +# define SEQAN_PP_NODE_36(p) SEQAN_PP_IIF(p(36), SEQAN_PP_NODE_34, SEQAN_PP_NODE_38) +# define SEQAN_PP_NODE_34(p) SEQAN_PP_IIF(p(34), SEQAN_PP_NODE_33, SEQAN_PP_NODE_35) +# define SEQAN_PP_NODE_33(p) SEQAN_PP_IIF(p(33), 33, 34) +# define SEQAN_PP_NODE_35(p) SEQAN_PP_IIF(p(35), 35, 36) +# define SEQAN_PP_NODE_38(p) SEQAN_PP_IIF(p(38), SEQAN_PP_NODE_37, SEQAN_PP_NODE_39) +# define SEQAN_PP_NODE_37(p) SEQAN_PP_IIF(p(37), 37, 38) +# define SEQAN_PP_NODE_39(p) SEQAN_PP_IIF(p(39), 39, 40) +# define SEQAN_PP_NODE_44(p) SEQAN_PP_IIF(p(44), SEQAN_PP_NODE_42, SEQAN_PP_NODE_46) +# define SEQAN_PP_NODE_42(p) SEQAN_PP_IIF(p(42), SEQAN_PP_NODE_41, SEQAN_PP_NODE_43) +# define SEQAN_PP_NODE_41(p) SEQAN_PP_IIF(p(41), 41, 42) +# define SEQAN_PP_NODE_43(p) SEQAN_PP_IIF(p(43), 43, 44) +# define SEQAN_PP_NODE_46(p) SEQAN_PP_IIF(p(46), SEQAN_PP_NODE_45, SEQAN_PP_NODE_47) +# define SEQAN_PP_NODE_45(p) SEQAN_PP_IIF(p(45), 45, 46) +# define SEQAN_PP_NODE_47(p) SEQAN_PP_IIF(p(47), 47, 48) +# define SEQAN_PP_NODE_56(p) SEQAN_PP_IIF(p(56), SEQAN_PP_NODE_52, SEQAN_PP_NODE_60) +# define SEQAN_PP_NODE_52(p) SEQAN_PP_IIF(p(52), SEQAN_PP_NODE_50, SEQAN_PP_NODE_54) +# define SEQAN_PP_NODE_50(p) SEQAN_PP_IIF(p(50), SEQAN_PP_NODE_49, SEQAN_PP_NODE_51) +# define SEQAN_PP_NODE_49(p) SEQAN_PP_IIF(p(49), 49, 50) +# define SEQAN_PP_NODE_51(p) SEQAN_PP_IIF(p(51), 51, 52) +# define SEQAN_PP_NODE_54(p) SEQAN_PP_IIF(p(54), SEQAN_PP_NODE_53, SEQAN_PP_NODE_55) +# define SEQAN_PP_NODE_53(p) SEQAN_PP_IIF(p(53), 53, 54) +# define SEQAN_PP_NODE_55(p) SEQAN_PP_IIF(p(55), 55, 56) +# define SEQAN_PP_NODE_60(p) SEQAN_PP_IIF(p(60), SEQAN_PP_NODE_58, SEQAN_PP_NODE_62) +# define SEQAN_PP_NODE_58(p) SEQAN_PP_IIF(p(58), SEQAN_PP_NODE_57, SEQAN_PP_NODE_59) +# define SEQAN_PP_NODE_57(p) SEQAN_PP_IIF(p(57), 57, 58) +# define SEQAN_PP_NODE_59(p) SEQAN_PP_IIF(p(59), 59, 60) +# define SEQAN_PP_NODE_62(p) SEQAN_PP_IIF(p(62), SEQAN_PP_NODE_61, SEQAN_PP_NODE_63) +# define SEQAN_PP_NODE_61(p) SEQAN_PP_IIF(p(61), 61, 62) +# define SEQAN_PP_NODE_63(p) SEQAN_PP_IIF(p(63), 63, 64) +# define SEQAN_PP_NODE_96(p) SEQAN_PP_IIF(p(96), SEQAN_PP_NODE_80, SEQAN_PP_NODE_112) +# define SEQAN_PP_NODE_80(p) SEQAN_PP_IIF(p(80), SEQAN_PP_NODE_72, SEQAN_PP_NODE_88) +# define SEQAN_PP_NODE_72(p) SEQAN_PP_IIF(p(72), SEQAN_PP_NODE_68, SEQAN_PP_NODE_76) +# define SEQAN_PP_NODE_68(p) SEQAN_PP_IIF(p(68), SEQAN_PP_NODE_66, SEQAN_PP_NODE_70) +# define SEQAN_PP_NODE_66(p) SEQAN_PP_IIF(p(66), SEQAN_PP_NODE_65, SEQAN_PP_NODE_67) +# define SEQAN_PP_NODE_65(p) SEQAN_PP_IIF(p(65), 65, 66) +# define SEQAN_PP_NODE_67(p) SEQAN_PP_IIF(p(67), 67, 68) +# define SEQAN_PP_NODE_70(p) SEQAN_PP_IIF(p(70), SEQAN_PP_NODE_69, SEQAN_PP_NODE_71) +# define SEQAN_PP_NODE_69(p) SEQAN_PP_IIF(p(69), 69, 70) +# define SEQAN_PP_NODE_71(p) SEQAN_PP_IIF(p(71), 71, 72) +# define SEQAN_PP_NODE_76(p) SEQAN_PP_IIF(p(76), SEQAN_PP_NODE_74, SEQAN_PP_NODE_78) +# define SEQAN_PP_NODE_74(p) SEQAN_PP_IIF(p(74), SEQAN_PP_NODE_73, SEQAN_PP_NODE_75) +# define SEQAN_PP_NODE_73(p) SEQAN_PP_IIF(p(73), 73, 74) +# define SEQAN_PP_NODE_75(p) SEQAN_PP_IIF(p(75), 75, 76) +# define SEQAN_PP_NODE_78(p) SEQAN_PP_IIF(p(78), SEQAN_PP_NODE_77, SEQAN_PP_NODE_79) +# define SEQAN_PP_NODE_77(p) SEQAN_PP_IIF(p(77), 77, 78) +# define SEQAN_PP_NODE_79(p) SEQAN_PP_IIF(p(79), 79, 80) +# define SEQAN_PP_NODE_88(p) SEQAN_PP_IIF(p(88), SEQAN_PP_NODE_84, SEQAN_PP_NODE_92) +# define SEQAN_PP_NODE_84(p) SEQAN_PP_IIF(p(84), SEQAN_PP_NODE_82, SEQAN_PP_NODE_86) +# define SEQAN_PP_NODE_82(p) SEQAN_PP_IIF(p(82), SEQAN_PP_NODE_81, SEQAN_PP_NODE_83) +# define SEQAN_PP_NODE_81(p) SEQAN_PP_IIF(p(81), 81, 82) +# define SEQAN_PP_NODE_83(p) SEQAN_PP_IIF(p(83), 83, 84) +# define SEQAN_PP_NODE_86(p) SEQAN_PP_IIF(p(86), SEQAN_PP_NODE_85, SEQAN_PP_NODE_87) +# define SEQAN_PP_NODE_85(p) SEQAN_PP_IIF(p(85), 85, 86) +# define SEQAN_PP_NODE_87(p) SEQAN_PP_IIF(p(87), 87, 88) +# define SEQAN_PP_NODE_92(p) SEQAN_PP_IIF(p(92), SEQAN_PP_NODE_90, SEQAN_PP_NODE_94) +# define SEQAN_PP_NODE_90(p) SEQAN_PP_IIF(p(90), SEQAN_PP_NODE_89, SEQAN_PP_NODE_91) +# define SEQAN_PP_NODE_89(p) SEQAN_PP_IIF(p(89), 89, 90) +# define SEQAN_PP_NODE_91(p) SEQAN_PP_IIF(p(91), 91, 92) +# define SEQAN_PP_NODE_94(p) SEQAN_PP_IIF(p(94), SEQAN_PP_NODE_93, SEQAN_PP_NODE_95) +# define SEQAN_PP_NODE_93(p) SEQAN_PP_IIF(p(93), 93, 94) +# define SEQAN_PP_NODE_95(p) SEQAN_PP_IIF(p(95), 95, 96) +# define SEQAN_PP_NODE_112(p) SEQAN_PP_IIF(p(112), SEQAN_PP_NODE_104, SEQAN_PP_NODE_120) +# define SEQAN_PP_NODE_104(p) SEQAN_PP_IIF(p(104), SEQAN_PP_NODE_100, SEQAN_PP_NODE_108) +# define SEQAN_PP_NODE_100(p) SEQAN_PP_IIF(p(100), SEQAN_PP_NODE_98, SEQAN_PP_NODE_102) +# define SEQAN_PP_NODE_98(p) SEQAN_PP_IIF(p(98), SEQAN_PP_NODE_97, SEQAN_PP_NODE_99) +# define SEQAN_PP_NODE_97(p) SEQAN_PP_IIF(p(97), 97, 98) +# define SEQAN_PP_NODE_99(p) SEQAN_PP_IIF(p(99), 99, 100) +# define SEQAN_PP_NODE_102(p) SEQAN_PP_IIF(p(102), SEQAN_PP_NODE_101, SEQAN_PP_NODE_103) +# define SEQAN_PP_NODE_101(p) SEQAN_PP_IIF(p(101), 101, 102) +# define SEQAN_PP_NODE_103(p) SEQAN_PP_IIF(p(103), 103, 104) +# define SEQAN_PP_NODE_108(p) SEQAN_PP_IIF(p(108), SEQAN_PP_NODE_106, SEQAN_PP_NODE_110) +# define SEQAN_PP_NODE_106(p) SEQAN_PP_IIF(p(106), SEQAN_PP_NODE_105, SEQAN_PP_NODE_107) +# define SEQAN_PP_NODE_105(p) SEQAN_PP_IIF(p(105), 105, 106) +# define SEQAN_PP_NODE_107(p) SEQAN_PP_IIF(p(107), 107, 108) +# define SEQAN_PP_NODE_110(p) SEQAN_PP_IIF(p(110), SEQAN_PP_NODE_109, SEQAN_PP_NODE_111) +# define SEQAN_PP_NODE_109(p) SEQAN_PP_IIF(p(109), 109, 110) +# define SEQAN_PP_NODE_111(p) SEQAN_PP_IIF(p(111), 111, 112) +# define SEQAN_PP_NODE_120(p) SEQAN_PP_IIF(p(120), SEQAN_PP_NODE_116, SEQAN_PP_NODE_124) +# define SEQAN_PP_NODE_116(p) SEQAN_PP_IIF(p(116), SEQAN_PP_NODE_114, SEQAN_PP_NODE_118) +# define SEQAN_PP_NODE_114(p) SEQAN_PP_IIF(p(114), SEQAN_PP_NODE_113, SEQAN_PP_NODE_115) +# define SEQAN_PP_NODE_113(p) SEQAN_PP_IIF(p(113), 113, 114) +# define SEQAN_PP_NODE_115(p) SEQAN_PP_IIF(p(115), 115, 116) +# define SEQAN_PP_NODE_118(p) SEQAN_PP_IIF(p(118), SEQAN_PP_NODE_117, SEQAN_PP_NODE_119) +# define SEQAN_PP_NODE_117(p) SEQAN_PP_IIF(p(117), 117, 118) +# define SEQAN_PP_NODE_119(p) SEQAN_PP_IIF(p(119), 119, 120) +# define SEQAN_PP_NODE_124(p) SEQAN_PP_IIF(p(124), SEQAN_PP_NODE_122, SEQAN_PP_NODE_126) +# define SEQAN_PP_NODE_122(p) SEQAN_PP_IIF(p(122), SEQAN_PP_NODE_121, SEQAN_PP_NODE_123) +# define SEQAN_PP_NODE_121(p) SEQAN_PP_IIF(p(121), 121, 122) +# define SEQAN_PP_NODE_123(p) SEQAN_PP_IIF(p(123), 123, 124) +# define SEQAN_PP_NODE_126(p) SEQAN_PP_IIF(p(126), SEQAN_PP_NODE_125, SEQAN_PP_NODE_127) +# define SEQAN_PP_NODE_125(p) SEQAN_PP_IIF(p(125), 125, 126) +# define SEQAN_PP_NODE_127(p) SEQAN_PP_IIF(p(127), 127, 128) +# define SEQAN_PP_NODE_192(p) SEQAN_PP_IIF(p(192), SEQAN_PP_NODE_160, SEQAN_PP_NODE_224) +# define SEQAN_PP_NODE_160(p) SEQAN_PP_IIF(p(160), SEQAN_PP_NODE_144, SEQAN_PP_NODE_176) +# define SEQAN_PP_NODE_144(p) SEQAN_PP_IIF(p(144), SEQAN_PP_NODE_136, SEQAN_PP_NODE_152) +# define SEQAN_PP_NODE_136(p) SEQAN_PP_IIF(p(136), SEQAN_PP_NODE_132, SEQAN_PP_NODE_140) +# define SEQAN_PP_NODE_132(p) SEQAN_PP_IIF(p(132), SEQAN_PP_NODE_130, SEQAN_PP_NODE_134) +# define SEQAN_PP_NODE_130(p) SEQAN_PP_IIF(p(130), SEQAN_PP_NODE_129, SEQAN_PP_NODE_131) +# define SEQAN_PP_NODE_129(p) SEQAN_PP_IIF(p(129), 129, 130) +# define SEQAN_PP_NODE_131(p) SEQAN_PP_IIF(p(131), 131, 132) +# define SEQAN_PP_NODE_134(p) SEQAN_PP_IIF(p(134), SEQAN_PP_NODE_133, SEQAN_PP_NODE_135) +# define SEQAN_PP_NODE_133(p) SEQAN_PP_IIF(p(133), 133, 134) +# define SEQAN_PP_NODE_135(p) SEQAN_PP_IIF(p(135), 135, 136) +# define SEQAN_PP_NODE_140(p) SEQAN_PP_IIF(p(140), SEQAN_PP_NODE_138, SEQAN_PP_NODE_142) +# define SEQAN_PP_NODE_138(p) SEQAN_PP_IIF(p(138), SEQAN_PP_NODE_137, SEQAN_PP_NODE_139) +# define SEQAN_PP_NODE_137(p) SEQAN_PP_IIF(p(137), 137, 138) +# define SEQAN_PP_NODE_139(p) SEQAN_PP_IIF(p(139), 139, 140) +# define SEQAN_PP_NODE_142(p) SEQAN_PP_IIF(p(142), SEQAN_PP_NODE_141, SEQAN_PP_NODE_143) +# define SEQAN_PP_NODE_141(p) SEQAN_PP_IIF(p(141), 141, 142) +# define SEQAN_PP_NODE_143(p) SEQAN_PP_IIF(p(143), 143, 144) +# define SEQAN_PP_NODE_152(p) SEQAN_PP_IIF(p(152), SEQAN_PP_NODE_148, SEQAN_PP_NODE_156) +# define SEQAN_PP_NODE_148(p) SEQAN_PP_IIF(p(148), SEQAN_PP_NODE_146, SEQAN_PP_NODE_150) +# define SEQAN_PP_NODE_146(p) SEQAN_PP_IIF(p(146), SEQAN_PP_NODE_145, SEQAN_PP_NODE_147) +# define SEQAN_PP_NODE_145(p) SEQAN_PP_IIF(p(145), 145, 146) +# define SEQAN_PP_NODE_147(p) SEQAN_PP_IIF(p(147), 147, 148) +# define SEQAN_PP_NODE_150(p) SEQAN_PP_IIF(p(150), SEQAN_PP_NODE_149, SEQAN_PP_NODE_151) +# define SEQAN_PP_NODE_149(p) SEQAN_PP_IIF(p(149), 149, 150) +# define SEQAN_PP_NODE_151(p) SEQAN_PP_IIF(p(151), 151, 152) +# define SEQAN_PP_NODE_156(p) SEQAN_PP_IIF(p(156), SEQAN_PP_NODE_154, SEQAN_PP_NODE_158) +# define SEQAN_PP_NODE_154(p) SEQAN_PP_IIF(p(154), SEQAN_PP_NODE_153, SEQAN_PP_NODE_155) +# define SEQAN_PP_NODE_153(p) SEQAN_PP_IIF(p(153), 153, 154) +# define SEQAN_PP_NODE_155(p) SEQAN_PP_IIF(p(155), 155, 156) +# define SEQAN_PP_NODE_158(p) SEQAN_PP_IIF(p(158), SEQAN_PP_NODE_157, SEQAN_PP_NODE_159) +# define SEQAN_PP_NODE_157(p) SEQAN_PP_IIF(p(157), 157, 158) +# define SEQAN_PP_NODE_159(p) SEQAN_PP_IIF(p(159), 159, 160) +# define SEQAN_PP_NODE_176(p) SEQAN_PP_IIF(p(176), SEQAN_PP_NODE_168, SEQAN_PP_NODE_184) +# define SEQAN_PP_NODE_168(p) SEQAN_PP_IIF(p(168), SEQAN_PP_NODE_164, SEQAN_PP_NODE_172) +# define SEQAN_PP_NODE_164(p) SEQAN_PP_IIF(p(164), SEQAN_PP_NODE_162, SEQAN_PP_NODE_166) +# define SEQAN_PP_NODE_162(p) SEQAN_PP_IIF(p(162), SEQAN_PP_NODE_161, SEQAN_PP_NODE_163) +# define SEQAN_PP_NODE_161(p) SEQAN_PP_IIF(p(161), 161, 162) +# define SEQAN_PP_NODE_163(p) SEQAN_PP_IIF(p(163), 163, 164) +# define SEQAN_PP_NODE_166(p) SEQAN_PP_IIF(p(166), SEQAN_PP_NODE_165, SEQAN_PP_NODE_167) +# define SEQAN_PP_NODE_165(p) SEQAN_PP_IIF(p(165), 165, 166) +# define SEQAN_PP_NODE_167(p) SEQAN_PP_IIF(p(167), 167, 168) +# define SEQAN_PP_NODE_172(p) SEQAN_PP_IIF(p(172), SEQAN_PP_NODE_170, SEQAN_PP_NODE_174) +# define SEQAN_PP_NODE_170(p) SEQAN_PP_IIF(p(170), SEQAN_PP_NODE_169, SEQAN_PP_NODE_171) +# define SEQAN_PP_NODE_169(p) SEQAN_PP_IIF(p(169), 169, 170) +# define SEQAN_PP_NODE_171(p) SEQAN_PP_IIF(p(171), 171, 172) +# define SEQAN_PP_NODE_174(p) SEQAN_PP_IIF(p(174), SEQAN_PP_NODE_173, SEQAN_PP_NODE_175) +# define SEQAN_PP_NODE_173(p) SEQAN_PP_IIF(p(173), 173, 174) +# define SEQAN_PP_NODE_175(p) SEQAN_PP_IIF(p(175), 175, 176) +# define SEQAN_PP_NODE_184(p) SEQAN_PP_IIF(p(184), SEQAN_PP_NODE_180, SEQAN_PP_NODE_188) +# define SEQAN_PP_NODE_180(p) SEQAN_PP_IIF(p(180), SEQAN_PP_NODE_178, SEQAN_PP_NODE_182) +# define SEQAN_PP_NODE_178(p) SEQAN_PP_IIF(p(178), SEQAN_PP_NODE_177, SEQAN_PP_NODE_179) +# define SEQAN_PP_NODE_177(p) SEQAN_PP_IIF(p(177), 177, 178) +# define SEQAN_PP_NODE_179(p) SEQAN_PP_IIF(p(179), 179, 180) +# define SEQAN_PP_NODE_182(p) SEQAN_PP_IIF(p(182), SEQAN_PP_NODE_181, SEQAN_PP_NODE_183) +# define SEQAN_PP_NODE_181(p) SEQAN_PP_IIF(p(181), 181, 182) +# define SEQAN_PP_NODE_183(p) SEQAN_PP_IIF(p(183), 183, 184) +# define SEQAN_PP_NODE_188(p) SEQAN_PP_IIF(p(188), SEQAN_PP_NODE_186, SEQAN_PP_NODE_190) +# define SEQAN_PP_NODE_186(p) SEQAN_PP_IIF(p(186), SEQAN_PP_NODE_185, SEQAN_PP_NODE_187) +# define SEQAN_PP_NODE_185(p) SEQAN_PP_IIF(p(185), 185, 186) +# define SEQAN_PP_NODE_187(p) SEQAN_PP_IIF(p(187), 187, 188) +# define SEQAN_PP_NODE_190(p) SEQAN_PP_IIF(p(190), SEQAN_PP_NODE_189, SEQAN_PP_NODE_191) +# define SEQAN_PP_NODE_189(p) SEQAN_PP_IIF(p(189), 189, 190) +# define SEQAN_PP_NODE_191(p) SEQAN_PP_IIF(p(191), 191, 192) +# define SEQAN_PP_NODE_224(p) SEQAN_PP_IIF(p(224), SEQAN_PP_NODE_208, SEQAN_PP_NODE_240) +# define SEQAN_PP_NODE_208(p) SEQAN_PP_IIF(p(208), SEQAN_PP_NODE_200, SEQAN_PP_NODE_216) +# define SEQAN_PP_NODE_200(p) SEQAN_PP_IIF(p(200), SEQAN_PP_NODE_196, SEQAN_PP_NODE_204) +# define SEQAN_PP_NODE_196(p) SEQAN_PP_IIF(p(196), SEQAN_PP_NODE_194, SEQAN_PP_NODE_198) +# define SEQAN_PP_NODE_194(p) SEQAN_PP_IIF(p(194), SEQAN_PP_NODE_193, SEQAN_PP_NODE_195) +# define SEQAN_PP_NODE_193(p) SEQAN_PP_IIF(p(193), 193, 194) +# define SEQAN_PP_NODE_195(p) SEQAN_PP_IIF(p(195), 195, 196) +# define SEQAN_PP_NODE_198(p) SEQAN_PP_IIF(p(198), SEQAN_PP_NODE_197, SEQAN_PP_NODE_199) +# define SEQAN_PP_NODE_197(p) SEQAN_PP_IIF(p(197), 197, 198) +# define SEQAN_PP_NODE_199(p) SEQAN_PP_IIF(p(199), 199, 200) +# define SEQAN_PP_NODE_204(p) SEQAN_PP_IIF(p(204), SEQAN_PP_NODE_202, SEQAN_PP_NODE_206) +# define SEQAN_PP_NODE_202(p) SEQAN_PP_IIF(p(202), SEQAN_PP_NODE_201, SEQAN_PP_NODE_203) +# define SEQAN_PP_NODE_201(p) SEQAN_PP_IIF(p(201), 201, 202) +# define SEQAN_PP_NODE_203(p) SEQAN_PP_IIF(p(203), 203, 204) +# define SEQAN_PP_NODE_206(p) SEQAN_PP_IIF(p(206), SEQAN_PP_NODE_205, SEQAN_PP_NODE_207) +# define SEQAN_PP_NODE_205(p) SEQAN_PP_IIF(p(205), 205, 206) +# define SEQAN_PP_NODE_207(p) SEQAN_PP_IIF(p(207), 207, 208) +# define SEQAN_PP_NODE_216(p) SEQAN_PP_IIF(p(216), SEQAN_PP_NODE_212, SEQAN_PP_NODE_220) +# define SEQAN_PP_NODE_212(p) SEQAN_PP_IIF(p(212), SEQAN_PP_NODE_210, SEQAN_PP_NODE_214) +# define SEQAN_PP_NODE_210(p) SEQAN_PP_IIF(p(210), SEQAN_PP_NODE_209, SEQAN_PP_NODE_211) +# define SEQAN_PP_NODE_209(p) SEQAN_PP_IIF(p(209), 209, 210) +# define SEQAN_PP_NODE_211(p) SEQAN_PP_IIF(p(211), 211, 212) +# define SEQAN_PP_NODE_214(p) SEQAN_PP_IIF(p(214), SEQAN_PP_NODE_213, SEQAN_PP_NODE_215) +# define SEQAN_PP_NODE_213(p) SEQAN_PP_IIF(p(213), 213, 214) +# define SEQAN_PP_NODE_215(p) SEQAN_PP_IIF(p(215), 215, 216) +# define SEQAN_PP_NODE_220(p) SEQAN_PP_IIF(p(220), SEQAN_PP_NODE_218, SEQAN_PP_NODE_222) +# define SEQAN_PP_NODE_218(p) SEQAN_PP_IIF(p(218), SEQAN_PP_NODE_217, SEQAN_PP_NODE_219) +# define SEQAN_PP_NODE_217(p) SEQAN_PP_IIF(p(217), 217, 218) +# define SEQAN_PP_NODE_219(p) SEQAN_PP_IIF(p(219), 219, 220) +# define SEQAN_PP_NODE_222(p) SEQAN_PP_IIF(p(222), SEQAN_PP_NODE_221, SEQAN_PP_NODE_223) +# define SEQAN_PP_NODE_221(p) SEQAN_PP_IIF(p(221), 221, 222) +# define SEQAN_PP_NODE_223(p) SEQAN_PP_IIF(p(223), 223, 224) +# define SEQAN_PP_NODE_240(p) SEQAN_PP_IIF(p(240), SEQAN_PP_NODE_232, SEQAN_PP_NODE_248) +# define SEQAN_PP_NODE_232(p) SEQAN_PP_IIF(p(232), SEQAN_PP_NODE_228, SEQAN_PP_NODE_236) +# define SEQAN_PP_NODE_228(p) SEQAN_PP_IIF(p(228), SEQAN_PP_NODE_226, SEQAN_PP_NODE_230) +# define SEQAN_PP_NODE_226(p) SEQAN_PP_IIF(p(226), SEQAN_PP_NODE_225, SEQAN_PP_NODE_227) +# define SEQAN_PP_NODE_225(p) SEQAN_PP_IIF(p(225), 225, 226) +# define SEQAN_PP_NODE_227(p) SEQAN_PP_IIF(p(227), 227, 228) +# define SEQAN_PP_NODE_230(p) SEQAN_PP_IIF(p(230), SEQAN_PP_NODE_229, SEQAN_PP_NODE_231) +# define SEQAN_PP_NODE_229(p) SEQAN_PP_IIF(p(229), 229, 230) +# define SEQAN_PP_NODE_231(p) SEQAN_PP_IIF(p(231), 231, 232) +# define SEQAN_PP_NODE_236(p) SEQAN_PP_IIF(p(236), SEQAN_PP_NODE_234, SEQAN_PP_NODE_238) +# define SEQAN_PP_NODE_234(p) SEQAN_PP_IIF(p(234), SEQAN_PP_NODE_233, SEQAN_PP_NODE_235) +# define SEQAN_PP_NODE_233(p) SEQAN_PP_IIF(p(233), 233, 234) +# define SEQAN_PP_NODE_235(p) SEQAN_PP_IIF(p(235), 235, 236) +# define SEQAN_PP_NODE_238(p) SEQAN_PP_IIF(p(238), SEQAN_PP_NODE_237, SEQAN_PP_NODE_239) +# define SEQAN_PP_NODE_237(p) SEQAN_PP_IIF(p(237), 237, 238) +# define SEQAN_PP_NODE_239(p) SEQAN_PP_IIF(p(239), 239, 240) +# define SEQAN_PP_NODE_248(p) SEQAN_PP_IIF(p(248), SEQAN_PP_NODE_244, SEQAN_PP_NODE_252) +# define SEQAN_PP_NODE_244(p) SEQAN_PP_IIF(p(244), SEQAN_PP_NODE_242, SEQAN_PP_NODE_246) +# define SEQAN_PP_NODE_242(p) SEQAN_PP_IIF(p(242), SEQAN_PP_NODE_241, SEQAN_PP_NODE_243) +# define SEQAN_PP_NODE_241(p) SEQAN_PP_IIF(p(241), 241, 242) +# define SEQAN_PP_NODE_243(p) SEQAN_PP_IIF(p(243), 243, 244) +# define SEQAN_PP_NODE_246(p) SEQAN_PP_IIF(p(246), SEQAN_PP_NODE_245, SEQAN_PP_NODE_247) +# define SEQAN_PP_NODE_245(p) SEQAN_PP_IIF(p(245), 245, 246) +# define SEQAN_PP_NODE_247(p) SEQAN_PP_IIF(p(247), 247, 248) +# define SEQAN_PP_NODE_252(p) SEQAN_PP_IIF(p(252), SEQAN_PP_NODE_250, SEQAN_PP_NODE_254) +# define SEQAN_PP_NODE_250(p) SEQAN_PP_IIF(p(250), SEQAN_PP_NODE_249, SEQAN_PP_NODE_251) +# define SEQAN_PP_NODE_249(p) SEQAN_PP_IIF(p(249), 249, 250) +# define SEQAN_PP_NODE_251(p) SEQAN_PP_IIF(p(251), 251, 252) +# define SEQAN_PP_NODE_254(p) SEQAN_PP_IIF(p(254), SEQAN_PP_NODE_253, SEQAN_PP_NODE_255) +# define SEQAN_PP_NODE_253(p) SEQAN_PP_IIF(p(253), 253, 254) +# define SEQAN_PP_NODE_255(p) SEQAN_PP_IIF(p(255), 255, 256) + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/logical/bool.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_LOGICAL_BOOL_HPP +// # define SEQAN_PREPROCESSOR_LOGICAL_BOOL_HPP +# +// # include +# +# /* SEQAN_PP_BOOL */ +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_BOOL(x) SEQAN_PP_BOOL_I(x) +// # else +// # define SEQAN_PP_BOOL(x) SEQAN_PP_BOOL_OO((x)) +// # define SEQAN_PP_BOOL_OO(par) SEQAN_PP_BOOL_I ## par +// # endif +# +# define SEQAN_PP_BOOL_I(x) SEQAN_PP_BOOL_ ## x +# +# define SEQAN_PP_BOOL_0 0 +# define SEQAN_PP_BOOL_1 1 +# define SEQAN_PP_BOOL_2 1 +# define SEQAN_PP_BOOL_3 1 +# define SEQAN_PP_BOOL_4 1 +# define SEQAN_PP_BOOL_5 1 +# define SEQAN_PP_BOOL_6 1 +# define SEQAN_PP_BOOL_7 1 +# define SEQAN_PP_BOOL_8 1 +# define SEQAN_PP_BOOL_9 1 +# define SEQAN_PP_BOOL_10 1 +# define SEQAN_PP_BOOL_11 1 +# define SEQAN_PP_BOOL_12 1 +# define SEQAN_PP_BOOL_13 1 +# define SEQAN_PP_BOOL_14 1 +# define SEQAN_PP_BOOL_15 1 +# define SEQAN_PP_BOOL_16 1 +# define SEQAN_PP_BOOL_17 1 +# define SEQAN_PP_BOOL_18 1 +# define SEQAN_PP_BOOL_19 1 +# define SEQAN_PP_BOOL_20 1 +# define SEQAN_PP_BOOL_21 1 +# define SEQAN_PP_BOOL_22 1 +# define SEQAN_PP_BOOL_23 1 +# define SEQAN_PP_BOOL_24 1 +# define SEQAN_PP_BOOL_25 1 +# define SEQAN_PP_BOOL_26 1 +# define SEQAN_PP_BOOL_27 1 +# define SEQAN_PP_BOOL_28 1 +# define SEQAN_PP_BOOL_29 1 +# define SEQAN_PP_BOOL_30 1 +# define SEQAN_PP_BOOL_31 1 +# define SEQAN_PP_BOOL_32 1 +# define SEQAN_PP_BOOL_33 1 +# define SEQAN_PP_BOOL_34 1 +# define SEQAN_PP_BOOL_35 1 +# define SEQAN_PP_BOOL_36 1 +# define SEQAN_PP_BOOL_37 1 +# define SEQAN_PP_BOOL_38 1 +# define SEQAN_PP_BOOL_39 1 +# define SEQAN_PP_BOOL_40 1 +# define SEQAN_PP_BOOL_41 1 +# define SEQAN_PP_BOOL_42 1 +# define SEQAN_PP_BOOL_43 1 +# define SEQAN_PP_BOOL_44 1 +# define SEQAN_PP_BOOL_45 1 +# define SEQAN_PP_BOOL_46 1 +# define SEQAN_PP_BOOL_47 1 +# define SEQAN_PP_BOOL_48 1 +# define SEQAN_PP_BOOL_49 1 +# define SEQAN_PP_BOOL_50 1 +# define SEQAN_PP_BOOL_51 1 +# define SEQAN_PP_BOOL_52 1 +# define SEQAN_PP_BOOL_53 1 +# define SEQAN_PP_BOOL_54 1 +# define SEQAN_PP_BOOL_55 1 +# define SEQAN_PP_BOOL_56 1 +# define SEQAN_PP_BOOL_57 1 +# define SEQAN_PP_BOOL_58 1 +# define SEQAN_PP_BOOL_59 1 +# define SEQAN_PP_BOOL_60 1 +# define SEQAN_PP_BOOL_61 1 +# define SEQAN_PP_BOOL_62 1 +# define SEQAN_PP_BOOL_63 1 +# define SEQAN_PP_BOOL_64 1 +# define SEQAN_PP_BOOL_65 1 +# define SEQAN_PP_BOOL_66 1 +# define SEQAN_PP_BOOL_67 1 +# define SEQAN_PP_BOOL_68 1 +# define SEQAN_PP_BOOL_69 1 +# define SEQAN_PP_BOOL_70 1 +# define SEQAN_PP_BOOL_71 1 +# define SEQAN_PP_BOOL_72 1 +# define SEQAN_PP_BOOL_73 1 +# define SEQAN_PP_BOOL_74 1 +# define SEQAN_PP_BOOL_75 1 +# define SEQAN_PP_BOOL_76 1 +# define SEQAN_PP_BOOL_77 1 +# define SEQAN_PP_BOOL_78 1 +# define SEQAN_PP_BOOL_79 1 +# define SEQAN_PP_BOOL_80 1 +# define SEQAN_PP_BOOL_81 1 +# define SEQAN_PP_BOOL_82 1 +# define SEQAN_PP_BOOL_83 1 +# define SEQAN_PP_BOOL_84 1 +# define SEQAN_PP_BOOL_85 1 +# define SEQAN_PP_BOOL_86 1 +# define SEQAN_PP_BOOL_87 1 +# define SEQAN_PP_BOOL_88 1 +# define SEQAN_PP_BOOL_89 1 +# define SEQAN_PP_BOOL_90 1 +# define SEQAN_PP_BOOL_91 1 +# define SEQAN_PP_BOOL_92 1 +# define SEQAN_PP_BOOL_93 1 +# define SEQAN_PP_BOOL_94 1 +# define SEQAN_PP_BOOL_95 1 +# define SEQAN_PP_BOOL_96 1 +# define SEQAN_PP_BOOL_97 1 +# define SEQAN_PP_BOOL_98 1 +# define SEQAN_PP_BOOL_99 1 +# define SEQAN_PP_BOOL_100 1 +# define SEQAN_PP_BOOL_101 1 +# define SEQAN_PP_BOOL_102 1 +# define SEQAN_PP_BOOL_103 1 +# define SEQAN_PP_BOOL_104 1 +# define SEQAN_PP_BOOL_105 1 +# define SEQAN_PP_BOOL_106 1 +# define SEQAN_PP_BOOL_107 1 +# define SEQAN_PP_BOOL_108 1 +# define SEQAN_PP_BOOL_109 1 +# define SEQAN_PP_BOOL_110 1 +# define SEQAN_PP_BOOL_111 1 +# define SEQAN_PP_BOOL_112 1 +# define SEQAN_PP_BOOL_113 1 +# define SEQAN_PP_BOOL_114 1 +# define SEQAN_PP_BOOL_115 1 +# define SEQAN_PP_BOOL_116 1 +# define SEQAN_PP_BOOL_117 1 +# define SEQAN_PP_BOOL_118 1 +# define SEQAN_PP_BOOL_119 1 +# define SEQAN_PP_BOOL_120 1 +# define SEQAN_PP_BOOL_121 1 +# define SEQAN_PP_BOOL_122 1 +# define SEQAN_PP_BOOL_123 1 +# define SEQAN_PP_BOOL_124 1 +# define SEQAN_PP_BOOL_125 1 +# define SEQAN_PP_BOOL_126 1 +# define SEQAN_PP_BOOL_127 1 +# define SEQAN_PP_BOOL_128 1 +# define SEQAN_PP_BOOL_129 1 +# define SEQAN_PP_BOOL_130 1 +# define SEQAN_PP_BOOL_131 1 +# define SEQAN_PP_BOOL_132 1 +# define SEQAN_PP_BOOL_133 1 +# define SEQAN_PP_BOOL_134 1 +# define SEQAN_PP_BOOL_135 1 +# define SEQAN_PP_BOOL_136 1 +# define SEQAN_PP_BOOL_137 1 +# define SEQAN_PP_BOOL_138 1 +# define SEQAN_PP_BOOL_139 1 +# define SEQAN_PP_BOOL_140 1 +# define SEQAN_PP_BOOL_141 1 +# define SEQAN_PP_BOOL_142 1 +# define SEQAN_PP_BOOL_143 1 +# define SEQAN_PP_BOOL_144 1 +# define SEQAN_PP_BOOL_145 1 +# define SEQAN_PP_BOOL_146 1 +# define SEQAN_PP_BOOL_147 1 +# define SEQAN_PP_BOOL_148 1 +# define SEQAN_PP_BOOL_149 1 +# define SEQAN_PP_BOOL_150 1 +# define SEQAN_PP_BOOL_151 1 +# define SEQAN_PP_BOOL_152 1 +# define SEQAN_PP_BOOL_153 1 +# define SEQAN_PP_BOOL_154 1 +# define SEQAN_PP_BOOL_155 1 +# define SEQAN_PP_BOOL_156 1 +# define SEQAN_PP_BOOL_157 1 +# define SEQAN_PP_BOOL_158 1 +# define SEQAN_PP_BOOL_159 1 +# define SEQAN_PP_BOOL_160 1 +# define SEQAN_PP_BOOL_161 1 +# define SEQAN_PP_BOOL_162 1 +# define SEQAN_PP_BOOL_163 1 +# define SEQAN_PP_BOOL_164 1 +# define SEQAN_PP_BOOL_165 1 +# define SEQAN_PP_BOOL_166 1 +# define SEQAN_PP_BOOL_167 1 +# define SEQAN_PP_BOOL_168 1 +# define SEQAN_PP_BOOL_169 1 +# define SEQAN_PP_BOOL_170 1 +# define SEQAN_PP_BOOL_171 1 +# define SEQAN_PP_BOOL_172 1 +# define SEQAN_PP_BOOL_173 1 +# define SEQAN_PP_BOOL_174 1 +# define SEQAN_PP_BOOL_175 1 +# define SEQAN_PP_BOOL_176 1 +# define SEQAN_PP_BOOL_177 1 +# define SEQAN_PP_BOOL_178 1 +# define SEQAN_PP_BOOL_179 1 +# define SEQAN_PP_BOOL_180 1 +# define SEQAN_PP_BOOL_181 1 +# define SEQAN_PP_BOOL_182 1 +# define SEQAN_PP_BOOL_183 1 +# define SEQAN_PP_BOOL_184 1 +# define SEQAN_PP_BOOL_185 1 +# define SEQAN_PP_BOOL_186 1 +# define SEQAN_PP_BOOL_187 1 +# define SEQAN_PP_BOOL_188 1 +# define SEQAN_PP_BOOL_189 1 +# define SEQAN_PP_BOOL_190 1 +# define SEQAN_PP_BOOL_191 1 +# define SEQAN_PP_BOOL_192 1 +# define SEQAN_PP_BOOL_193 1 +# define SEQAN_PP_BOOL_194 1 +# define SEQAN_PP_BOOL_195 1 +# define SEQAN_PP_BOOL_196 1 +# define SEQAN_PP_BOOL_197 1 +# define SEQAN_PP_BOOL_198 1 +# define SEQAN_PP_BOOL_199 1 +# define SEQAN_PP_BOOL_200 1 +# define SEQAN_PP_BOOL_201 1 +# define SEQAN_PP_BOOL_202 1 +# define SEQAN_PP_BOOL_203 1 +# define SEQAN_PP_BOOL_204 1 +# define SEQAN_PP_BOOL_205 1 +# define SEQAN_PP_BOOL_206 1 +# define SEQAN_PP_BOOL_207 1 +# define SEQAN_PP_BOOL_208 1 +# define SEQAN_PP_BOOL_209 1 +# define SEQAN_PP_BOOL_210 1 +# define SEQAN_PP_BOOL_211 1 +# define SEQAN_PP_BOOL_212 1 +# define SEQAN_PP_BOOL_213 1 +# define SEQAN_PP_BOOL_214 1 +# define SEQAN_PP_BOOL_215 1 +# define SEQAN_PP_BOOL_216 1 +# define SEQAN_PP_BOOL_217 1 +# define SEQAN_PP_BOOL_218 1 +# define SEQAN_PP_BOOL_219 1 +# define SEQAN_PP_BOOL_220 1 +# define SEQAN_PP_BOOL_221 1 +# define SEQAN_PP_BOOL_222 1 +# define SEQAN_PP_BOOL_223 1 +# define SEQAN_PP_BOOL_224 1 +# define SEQAN_PP_BOOL_225 1 +# define SEQAN_PP_BOOL_226 1 +# define SEQAN_PP_BOOL_227 1 +# define SEQAN_PP_BOOL_228 1 +# define SEQAN_PP_BOOL_229 1 +# define SEQAN_PP_BOOL_230 1 +# define SEQAN_PP_BOOL_231 1 +# define SEQAN_PP_BOOL_232 1 +# define SEQAN_PP_BOOL_233 1 +# define SEQAN_PP_BOOL_234 1 +# define SEQAN_PP_BOOL_235 1 +# define SEQAN_PP_BOOL_236 1 +# define SEQAN_PP_BOOL_237 1 +# define SEQAN_PP_BOOL_238 1 +# define SEQAN_PP_BOOL_239 1 +# define SEQAN_PP_BOOL_240 1 +# define SEQAN_PP_BOOL_241 1 +# define SEQAN_PP_BOOL_242 1 +# define SEQAN_PP_BOOL_243 1 +# define SEQAN_PP_BOOL_244 1 +# define SEQAN_PP_BOOL_245 1 +# define SEQAN_PP_BOOL_246 1 +# define SEQAN_PP_BOOL_247 1 +# define SEQAN_PP_BOOL_248 1 +# define SEQAN_PP_BOOL_249 1 +# define SEQAN_PP_BOOL_250 1 +# define SEQAN_PP_BOOL_251 1 +# define SEQAN_PP_BOOL_252 1 +# define SEQAN_PP_BOOL_253 1 +# define SEQAN_PP_BOOL_254 1 +# define SEQAN_PP_BOOL_255 1 +# define SEQAN_PP_BOOL_256 1 + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/control/expr_iif.hpp <== +// -------------------------------------------------------------------------- + +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_CONTROL_EXPR_IIF_HPP +// # define SEQAN_PREPROCESSOR_CONTROL_EXPR_IIF_HPP +# +// # include +# +# /* SEQAN_PP_EXPR_IIF */ +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_EXPR_IIF(bit, expr) SEQAN_PP_EXPR_IIF_I(bit, expr) +// # else +// # define SEQAN_PP_EXPR_IIF(bit, expr) SEQAN_PP_EXPR_IIF_OO((bit, expr)) +// # define SEQAN_PP_EXPR_IIF_OO(par) SEQAN_PP_EXPR_IIF_I ## par +// # endif +# +# define SEQAN_PP_EXPR_IIF_I(bit, expr) SEQAN_PP_EXPR_IIF_ ## bit(expr) +# +# define SEQAN_PP_EXPR_IIF_0(expr) +# define SEQAN_PP_EXPR_IIF_1(expr) expr +# +// # endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/control/iif.hpp <== +// -------------------------------------------------------------------------- + +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_CONTROL_IIF_HPP +// # define SEQAN_PREPROCESSOR_CONTROL_IIF_HPP +# +// # include +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_IIF(bit, t, f) SEQAN_PP_IIF_I(bit, t, f) +// # else +// # define SEQAN_PP_IIF(bit, t, f) SEQAN_PP_IIF_OO((bit, t, f)) +// # define SEQAN_PP_IIF_OO(par) SEQAN_PP_IIF_I ## par +// # endif +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MSVC() +#ifndef STDLIB_VS +# define SEQAN_PP_IIF_I(bit, t, f) SEQAN_PP_IIF_ ## bit(t, f) +# else // #ifndef STDLIB_VS +# define SEQAN_PP_IIF_I(bit, t, f) SEQAN_PP_IIF_II(SEQAN_PP_IIF_ ## bit(t, f)) +# define SEQAN_PP_IIF_II(id) id +# endif // #ifndef STDLIB_VS +# +# define SEQAN_PP_IIF_0(t, f) f +# define SEQAN_PP_IIF_1(t, f) t +# +// # endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/control/if.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +//# ifndef SEQAN_PREPROCESSOR_CONTROL_IF_HPP +//# define SEQAN_PREPROCESSOR_CONTROL_IF_HPP +# +//# include +//# include +//# include +# +# /* SEQAN_PP_IF */ +# +//# if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() +# define SEQAN_PP_IF(cond, t, f) SEQAN_PP_IIF(SEQAN_PP_BOOL(cond), t, f) +//# else +//# define SEQAN_PP_IF(cond, t, f) SEQAN_PP_IF_I(cond, t, f) +//# define SEQAN_PP_IF_I(cond, t, f) SEQAN_PP_IIF(SEQAN_PP_BOOL(cond), t, f) +//# endif +# +//# endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/facilities/empty.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +//# ifndef SEQAN_PREPROCESSOR_FACILITIES_EMPTY_HPP +//# define SEQAN_PREPROCESSOR_FACILITIES_EMPTY_HPP +# +# /* SEQAN_PP_EMPTY */ +# +# define SEQAN_PP_EMPTY() +# +//# endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/punctuation/comma.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +//# ifndef SEQAN_PREPROCESSOR_PUNCTUATION_COMMA_HPP +//# define SEQAN_PREPROCESSOR_PUNCTUATION_COMMA_HPP +# +# /* SEQAN_PP_COMMA */ +# +# define SEQAN_PP_COMMA() , +# +//# endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/punctuation/comma_if.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +//# ifndef SEQAN_PREPROCESSOR_PUNCTUATION_COMMA_IF_HPP +//# define SEQAN_PREPROCESSOR_PUNCTUATION_COMMA_IF_HPP +# +//# include +//# include +//# include +//# include +# +# /* SEQAN_PP_COMMA_IF */ +# +//# if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() +# define SEQAN_PP_COMMA_IF(cond) SEQAN_PP_IF(cond, SEQAN_PP_COMMA, SEQAN_PP_EMPTY)() +//# else +//# define SEQAN_PP_COMMA_IF(cond) SEQAN_PP_COMMA_IF_I(cond) +//# define SEQAN_PP_COMMA_IF_I(cond) SEQAN_PP_IF(cond, SEQAN_PP_COMMA, SEQAN_PP_EMPTY)() +//# endif +# +//# endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/repetition/repeat.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +//# ifndef SEQAN_PREPROCESSOR_REPETITION_REPEAT_HPP +//# define SEQAN_PREPROCESSOR_REPETITION_REPEAT_HPP +# +//# include +//# include +//# include +//# include +//# include +# +# /* SEQAN_PP_REPEAT */ +# +# if 0 +# define SEQAN_PP_REPEAT(count, macro, data) +# endif +# +# define SEQAN_PP_REPEAT SEQAN_PP_CAT(SEQAN_PP_REPEAT_, SEQAN_PP_AUTO_REC(SEQAN_PP_REPEAT_P, 4)) +# +# define SEQAN_PP_REPEAT_P(n) SEQAN_PP_CAT(SEQAN_PP_REPEAT_CHECK_, SEQAN_PP_REPEAT_ ## n(1, SEQAN_PP_NIL SEQAN_PP_TUPLE_EAT_3, SEQAN_PP_NIL)) +# +# define SEQAN_PP_REPEAT_CHECK_SEQAN_PP_NIL 1 +# define SEQAN_PP_REPEAT_CHECK_SEQAN_PP_REPEAT_1(c, m, d) 0 +# define SEQAN_PP_REPEAT_CHECK_SEQAN_PP_REPEAT_2(c, m, d) 0 +# define SEQAN_PP_REPEAT_CHECK_SEQAN_PP_REPEAT_3(c, m, d) 0 +# +# define SEQAN_PP_REPEAT_1(c, m, d) SEQAN_PP_REPEAT_1_I(c, m, d) +# define SEQAN_PP_REPEAT_2(c, m, d) SEQAN_PP_REPEAT_2_I(c, m, d) +# define SEQAN_PP_REPEAT_3(c, m, d) SEQAN_PP_REPEAT_3_I(c, m, d) +# define SEQAN_PP_REPEAT_4(c, m, d) SEQAN_PP_ERROR(0x0003) +# +# define SEQAN_PP_REPEAT_1_I(c, m, d) SEQAN_PP_REPEAT_1_ ## c(m, d) +# define SEQAN_PP_REPEAT_2_I(c, m, d) SEQAN_PP_REPEAT_2_ ## c(m, d) +# define SEQAN_PP_REPEAT_3_I(c, m, d) SEQAN_PP_REPEAT_3_ ## c(m, d) +# +# define SEQAN_PP_REPEAT_1ST SEQAN_PP_REPEAT_1 +# define SEQAN_PP_REPEAT_2ND SEQAN_PP_REPEAT_2 +# define SEQAN_PP_REPEAT_3RD SEQAN_PP_REPEAT_3 +# +# define SEQAN_PP_REPEAT_1_0(m, d) +# define SEQAN_PP_REPEAT_1_1(m, d) m(2, 0, d) +# define SEQAN_PP_REPEAT_1_2(m, d) SEQAN_PP_REPEAT_1_1(m, d) m(2, 1, d) +# define SEQAN_PP_REPEAT_1_3(m, d) SEQAN_PP_REPEAT_1_2(m, d) m(2, 2, d) +# define SEQAN_PP_REPEAT_1_4(m, d) SEQAN_PP_REPEAT_1_3(m, d) m(2, 3, d) +# define SEQAN_PP_REPEAT_1_5(m, d) SEQAN_PP_REPEAT_1_4(m, d) m(2, 4, d) +# define SEQAN_PP_REPEAT_1_6(m, d) SEQAN_PP_REPEAT_1_5(m, d) m(2, 5, d) +# define SEQAN_PP_REPEAT_1_7(m, d) SEQAN_PP_REPEAT_1_6(m, d) m(2, 6, d) +# define SEQAN_PP_REPEAT_1_8(m, d) SEQAN_PP_REPEAT_1_7(m, d) m(2, 7, d) +# define SEQAN_PP_REPEAT_1_9(m, d) SEQAN_PP_REPEAT_1_8(m, d) m(2, 8, d) +# define SEQAN_PP_REPEAT_1_10(m, d) SEQAN_PP_REPEAT_1_9(m, d) m(2, 9, d) +# define SEQAN_PP_REPEAT_1_11(m, d) SEQAN_PP_REPEAT_1_10(m, d) m(2, 10, d) +# define SEQAN_PP_REPEAT_1_12(m, d) SEQAN_PP_REPEAT_1_11(m, d) m(2, 11, d) +# define SEQAN_PP_REPEAT_1_13(m, d) SEQAN_PP_REPEAT_1_12(m, d) m(2, 12, d) +# define SEQAN_PP_REPEAT_1_14(m, d) SEQAN_PP_REPEAT_1_13(m, d) m(2, 13, d) +# define SEQAN_PP_REPEAT_1_15(m, d) SEQAN_PP_REPEAT_1_14(m, d) m(2, 14, d) +# define SEQAN_PP_REPEAT_1_16(m, d) SEQAN_PP_REPEAT_1_15(m, d) m(2, 15, d) +# define SEQAN_PP_REPEAT_1_17(m, d) SEQAN_PP_REPEAT_1_16(m, d) m(2, 16, d) +# define SEQAN_PP_REPEAT_1_18(m, d) SEQAN_PP_REPEAT_1_17(m, d) m(2, 17, d) +# define SEQAN_PP_REPEAT_1_19(m, d) SEQAN_PP_REPEAT_1_18(m, d) m(2, 18, d) +# define SEQAN_PP_REPEAT_1_20(m, d) SEQAN_PP_REPEAT_1_19(m, d) m(2, 19, d) +# define SEQAN_PP_REPEAT_1_21(m, d) SEQAN_PP_REPEAT_1_20(m, d) m(2, 20, d) +# define SEQAN_PP_REPEAT_1_22(m, d) SEQAN_PP_REPEAT_1_21(m, d) m(2, 21, d) +# define SEQAN_PP_REPEAT_1_23(m, d) SEQAN_PP_REPEAT_1_22(m, d) m(2, 22, d) +# define SEQAN_PP_REPEAT_1_24(m, d) SEQAN_PP_REPEAT_1_23(m, d) m(2, 23, d) +# define SEQAN_PP_REPEAT_1_25(m, d) SEQAN_PP_REPEAT_1_24(m, d) m(2, 24, d) +# define SEQAN_PP_REPEAT_1_26(m, d) SEQAN_PP_REPEAT_1_25(m, d) m(2, 25, d) +# define SEQAN_PP_REPEAT_1_27(m, d) SEQAN_PP_REPEAT_1_26(m, d) m(2, 26, d) +# define SEQAN_PP_REPEAT_1_28(m, d) SEQAN_PP_REPEAT_1_27(m, d) m(2, 27, d) +# define SEQAN_PP_REPEAT_1_29(m, d) SEQAN_PP_REPEAT_1_28(m, d) m(2, 28, d) +# define SEQAN_PP_REPEAT_1_30(m, d) SEQAN_PP_REPEAT_1_29(m, d) m(2, 29, d) +# define SEQAN_PP_REPEAT_1_31(m, d) SEQAN_PP_REPEAT_1_30(m, d) m(2, 30, d) +# define SEQAN_PP_REPEAT_1_32(m, d) SEQAN_PP_REPEAT_1_31(m, d) m(2, 31, d) +# define SEQAN_PP_REPEAT_1_33(m, d) SEQAN_PP_REPEAT_1_32(m, d) m(2, 32, d) +# define SEQAN_PP_REPEAT_1_34(m, d) SEQAN_PP_REPEAT_1_33(m, d) m(2, 33, d) +# define SEQAN_PP_REPEAT_1_35(m, d) SEQAN_PP_REPEAT_1_34(m, d) m(2, 34, d) +# define SEQAN_PP_REPEAT_1_36(m, d) SEQAN_PP_REPEAT_1_35(m, d) m(2, 35, d) +# define SEQAN_PP_REPEAT_1_37(m, d) SEQAN_PP_REPEAT_1_36(m, d) m(2, 36, d) +# define SEQAN_PP_REPEAT_1_38(m, d) SEQAN_PP_REPEAT_1_37(m, d) m(2, 37, d) +# define SEQAN_PP_REPEAT_1_39(m, d) SEQAN_PP_REPEAT_1_38(m, d) m(2, 38, d) +# define SEQAN_PP_REPEAT_1_40(m, d) SEQAN_PP_REPEAT_1_39(m, d) m(2, 39, d) +# define SEQAN_PP_REPEAT_1_41(m, d) SEQAN_PP_REPEAT_1_40(m, d) m(2, 40, d) +# define SEQAN_PP_REPEAT_1_42(m, d) SEQAN_PP_REPEAT_1_41(m, d) m(2, 41, d) +# define SEQAN_PP_REPEAT_1_43(m, d) SEQAN_PP_REPEAT_1_42(m, d) m(2, 42, d) +# define SEQAN_PP_REPEAT_1_44(m, d) SEQAN_PP_REPEAT_1_43(m, d) m(2, 43, d) +# define SEQAN_PP_REPEAT_1_45(m, d) SEQAN_PP_REPEAT_1_44(m, d) m(2, 44, d) +# define SEQAN_PP_REPEAT_1_46(m, d) SEQAN_PP_REPEAT_1_45(m, d) m(2, 45, d) +# define SEQAN_PP_REPEAT_1_47(m, d) SEQAN_PP_REPEAT_1_46(m, d) m(2, 46, d) +# define SEQAN_PP_REPEAT_1_48(m, d) SEQAN_PP_REPEAT_1_47(m, d) m(2, 47, d) +# define SEQAN_PP_REPEAT_1_49(m, d) SEQAN_PP_REPEAT_1_48(m, d) m(2, 48, d) +# define SEQAN_PP_REPEAT_1_50(m, d) SEQAN_PP_REPEAT_1_49(m, d) m(2, 49, d) +# define SEQAN_PP_REPEAT_1_51(m, d) SEQAN_PP_REPEAT_1_50(m, d) m(2, 50, d) +# define SEQAN_PP_REPEAT_1_52(m, d) SEQAN_PP_REPEAT_1_51(m, d) m(2, 51, d) +# define SEQAN_PP_REPEAT_1_53(m, d) SEQAN_PP_REPEAT_1_52(m, d) m(2, 52, d) +# define SEQAN_PP_REPEAT_1_54(m, d) SEQAN_PP_REPEAT_1_53(m, d) m(2, 53, d) +# define SEQAN_PP_REPEAT_1_55(m, d) SEQAN_PP_REPEAT_1_54(m, d) m(2, 54, d) +# define SEQAN_PP_REPEAT_1_56(m, d) SEQAN_PP_REPEAT_1_55(m, d) m(2, 55, d) +# define SEQAN_PP_REPEAT_1_57(m, d) SEQAN_PP_REPEAT_1_56(m, d) m(2, 56, d) +# define SEQAN_PP_REPEAT_1_58(m, d) SEQAN_PP_REPEAT_1_57(m, d) m(2, 57, d) +# define SEQAN_PP_REPEAT_1_59(m, d) SEQAN_PP_REPEAT_1_58(m, d) m(2, 58, d) +# define SEQAN_PP_REPEAT_1_60(m, d) SEQAN_PP_REPEAT_1_59(m, d) m(2, 59, d) +# define SEQAN_PP_REPEAT_1_61(m, d) SEQAN_PP_REPEAT_1_60(m, d) m(2, 60, d) +# define SEQAN_PP_REPEAT_1_62(m, d) SEQAN_PP_REPEAT_1_61(m, d) m(2, 61, d) +# define SEQAN_PP_REPEAT_1_63(m, d) SEQAN_PP_REPEAT_1_62(m, d) m(2, 62, d) +# define SEQAN_PP_REPEAT_1_64(m, d) SEQAN_PP_REPEAT_1_63(m, d) m(2, 63, d) +# define SEQAN_PP_REPEAT_1_65(m, d) SEQAN_PP_REPEAT_1_64(m, d) m(2, 64, d) +# define SEQAN_PP_REPEAT_1_66(m, d) SEQAN_PP_REPEAT_1_65(m, d) m(2, 65, d) +# define SEQAN_PP_REPEAT_1_67(m, d) SEQAN_PP_REPEAT_1_66(m, d) m(2, 66, d) +# define SEQAN_PP_REPEAT_1_68(m, d) SEQAN_PP_REPEAT_1_67(m, d) m(2, 67, d) +# define SEQAN_PP_REPEAT_1_69(m, d) SEQAN_PP_REPEAT_1_68(m, d) m(2, 68, d) +# define SEQAN_PP_REPEAT_1_70(m, d) SEQAN_PP_REPEAT_1_69(m, d) m(2, 69, d) +# define SEQAN_PP_REPEAT_1_71(m, d) SEQAN_PP_REPEAT_1_70(m, d) m(2, 70, d) +# define SEQAN_PP_REPEAT_1_72(m, d) SEQAN_PP_REPEAT_1_71(m, d) m(2, 71, d) +# define SEQAN_PP_REPEAT_1_73(m, d) SEQAN_PP_REPEAT_1_72(m, d) m(2, 72, d) +# define SEQAN_PP_REPEAT_1_74(m, d) SEQAN_PP_REPEAT_1_73(m, d) m(2, 73, d) +# define SEQAN_PP_REPEAT_1_75(m, d) SEQAN_PP_REPEAT_1_74(m, d) m(2, 74, d) +# define SEQAN_PP_REPEAT_1_76(m, d) SEQAN_PP_REPEAT_1_75(m, d) m(2, 75, d) +# define SEQAN_PP_REPEAT_1_77(m, d) SEQAN_PP_REPEAT_1_76(m, d) m(2, 76, d) +# define SEQAN_PP_REPEAT_1_78(m, d) SEQAN_PP_REPEAT_1_77(m, d) m(2, 77, d) +# define SEQAN_PP_REPEAT_1_79(m, d) SEQAN_PP_REPEAT_1_78(m, d) m(2, 78, d) +# define SEQAN_PP_REPEAT_1_80(m, d) SEQAN_PP_REPEAT_1_79(m, d) m(2, 79, d) +# define SEQAN_PP_REPEAT_1_81(m, d) SEQAN_PP_REPEAT_1_80(m, d) m(2, 80, d) +# define SEQAN_PP_REPEAT_1_82(m, d) SEQAN_PP_REPEAT_1_81(m, d) m(2, 81, d) +# define SEQAN_PP_REPEAT_1_83(m, d) SEQAN_PP_REPEAT_1_82(m, d) m(2, 82, d) +# define SEQAN_PP_REPEAT_1_84(m, d) SEQAN_PP_REPEAT_1_83(m, d) m(2, 83, d) +# define SEQAN_PP_REPEAT_1_85(m, d) SEQAN_PP_REPEAT_1_84(m, d) m(2, 84, d) +# define SEQAN_PP_REPEAT_1_86(m, d) SEQAN_PP_REPEAT_1_85(m, d) m(2, 85, d) +# define SEQAN_PP_REPEAT_1_87(m, d) SEQAN_PP_REPEAT_1_86(m, d) m(2, 86, d) +# define SEQAN_PP_REPEAT_1_88(m, d) SEQAN_PP_REPEAT_1_87(m, d) m(2, 87, d) +# define SEQAN_PP_REPEAT_1_89(m, d) SEQAN_PP_REPEAT_1_88(m, d) m(2, 88, d) +# define SEQAN_PP_REPEAT_1_90(m, d) SEQAN_PP_REPEAT_1_89(m, d) m(2, 89, d) +# define SEQAN_PP_REPEAT_1_91(m, d) SEQAN_PP_REPEAT_1_90(m, d) m(2, 90, d) +# define SEQAN_PP_REPEAT_1_92(m, d) SEQAN_PP_REPEAT_1_91(m, d) m(2, 91, d) +# define SEQAN_PP_REPEAT_1_93(m, d) SEQAN_PP_REPEAT_1_92(m, d) m(2, 92, d) +# define SEQAN_PP_REPEAT_1_94(m, d) SEQAN_PP_REPEAT_1_93(m, d) m(2, 93, d) +# define SEQAN_PP_REPEAT_1_95(m, d) SEQAN_PP_REPEAT_1_94(m, d) m(2, 94, d) +# define SEQAN_PP_REPEAT_1_96(m, d) SEQAN_PP_REPEAT_1_95(m, d) m(2, 95, d) +# define SEQAN_PP_REPEAT_1_97(m, d) SEQAN_PP_REPEAT_1_96(m, d) m(2, 96, d) +# define SEQAN_PP_REPEAT_1_98(m, d) SEQAN_PP_REPEAT_1_97(m, d) m(2, 97, d) +# define SEQAN_PP_REPEAT_1_99(m, d) SEQAN_PP_REPEAT_1_98(m, d) m(2, 98, d) +# define SEQAN_PP_REPEAT_1_100(m, d) SEQAN_PP_REPEAT_1_99(m, d) m(2, 99, d) +# define SEQAN_PP_REPEAT_1_101(m, d) SEQAN_PP_REPEAT_1_100(m, d) m(2, 100, d) +# define SEQAN_PP_REPEAT_1_102(m, d) SEQAN_PP_REPEAT_1_101(m, d) m(2, 101, d) +# define SEQAN_PP_REPEAT_1_103(m, d) SEQAN_PP_REPEAT_1_102(m, d) m(2, 102, d) +# define SEQAN_PP_REPEAT_1_104(m, d) SEQAN_PP_REPEAT_1_103(m, d) m(2, 103, d) +# define SEQAN_PP_REPEAT_1_105(m, d) SEQAN_PP_REPEAT_1_104(m, d) m(2, 104, d) +# define SEQAN_PP_REPEAT_1_106(m, d) SEQAN_PP_REPEAT_1_105(m, d) m(2, 105, d) +# define SEQAN_PP_REPEAT_1_107(m, d) SEQAN_PP_REPEAT_1_106(m, d) m(2, 106, d) +# define SEQAN_PP_REPEAT_1_108(m, d) SEQAN_PP_REPEAT_1_107(m, d) m(2, 107, d) +# define SEQAN_PP_REPEAT_1_109(m, d) SEQAN_PP_REPEAT_1_108(m, d) m(2, 108, d) +# define SEQAN_PP_REPEAT_1_110(m, d) SEQAN_PP_REPEAT_1_109(m, d) m(2, 109, d) +# define SEQAN_PP_REPEAT_1_111(m, d) SEQAN_PP_REPEAT_1_110(m, d) m(2, 110, d) +# define SEQAN_PP_REPEAT_1_112(m, d) SEQAN_PP_REPEAT_1_111(m, d) m(2, 111, d) +# define SEQAN_PP_REPEAT_1_113(m, d) SEQAN_PP_REPEAT_1_112(m, d) m(2, 112, d) +# define SEQAN_PP_REPEAT_1_114(m, d) SEQAN_PP_REPEAT_1_113(m, d) m(2, 113, d) +# define SEQAN_PP_REPEAT_1_115(m, d) SEQAN_PP_REPEAT_1_114(m, d) m(2, 114, d) +# define SEQAN_PP_REPEAT_1_116(m, d) SEQAN_PP_REPEAT_1_115(m, d) m(2, 115, d) +# define SEQAN_PP_REPEAT_1_117(m, d) SEQAN_PP_REPEAT_1_116(m, d) m(2, 116, d) +# define SEQAN_PP_REPEAT_1_118(m, d) SEQAN_PP_REPEAT_1_117(m, d) m(2, 117, d) +# define SEQAN_PP_REPEAT_1_119(m, d) SEQAN_PP_REPEAT_1_118(m, d) m(2, 118, d) +# define SEQAN_PP_REPEAT_1_120(m, d) SEQAN_PP_REPEAT_1_119(m, d) m(2, 119, d) +# define SEQAN_PP_REPEAT_1_121(m, d) SEQAN_PP_REPEAT_1_120(m, d) m(2, 120, d) +# define SEQAN_PP_REPEAT_1_122(m, d) SEQAN_PP_REPEAT_1_121(m, d) m(2, 121, d) +# define SEQAN_PP_REPEAT_1_123(m, d) SEQAN_PP_REPEAT_1_122(m, d) m(2, 122, d) +# define SEQAN_PP_REPEAT_1_124(m, d) SEQAN_PP_REPEAT_1_123(m, d) m(2, 123, d) +# define SEQAN_PP_REPEAT_1_125(m, d) SEQAN_PP_REPEAT_1_124(m, d) m(2, 124, d) +# define SEQAN_PP_REPEAT_1_126(m, d) SEQAN_PP_REPEAT_1_125(m, d) m(2, 125, d) +# define SEQAN_PP_REPEAT_1_127(m, d) SEQAN_PP_REPEAT_1_126(m, d) m(2, 126, d) +# define SEQAN_PP_REPEAT_1_128(m, d) SEQAN_PP_REPEAT_1_127(m, d) m(2, 127, d) +# define SEQAN_PP_REPEAT_1_129(m, d) SEQAN_PP_REPEAT_1_128(m, d) m(2, 128, d) +# define SEQAN_PP_REPEAT_1_130(m, d) SEQAN_PP_REPEAT_1_129(m, d) m(2, 129, d) +# define SEQAN_PP_REPEAT_1_131(m, d) SEQAN_PP_REPEAT_1_130(m, d) m(2, 130, d) +# define SEQAN_PP_REPEAT_1_132(m, d) SEQAN_PP_REPEAT_1_131(m, d) m(2, 131, d) +# define SEQAN_PP_REPEAT_1_133(m, d) SEQAN_PP_REPEAT_1_132(m, d) m(2, 132, d) +# define SEQAN_PP_REPEAT_1_134(m, d) SEQAN_PP_REPEAT_1_133(m, d) m(2, 133, d) +# define SEQAN_PP_REPEAT_1_135(m, d) SEQAN_PP_REPEAT_1_134(m, d) m(2, 134, d) +# define SEQAN_PP_REPEAT_1_136(m, d) SEQAN_PP_REPEAT_1_135(m, d) m(2, 135, d) +# define SEQAN_PP_REPEAT_1_137(m, d) SEQAN_PP_REPEAT_1_136(m, d) m(2, 136, d) +# define SEQAN_PP_REPEAT_1_138(m, d) SEQAN_PP_REPEAT_1_137(m, d) m(2, 137, d) +# define SEQAN_PP_REPEAT_1_139(m, d) SEQAN_PP_REPEAT_1_138(m, d) m(2, 138, d) +# define SEQAN_PP_REPEAT_1_140(m, d) SEQAN_PP_REPEAT_1_139(m, d) m(2, 139, d) +# define SEQAN_PP_REPEAT_1_141(m, d) SEQAN_PP_REPEAT_1_140(m, d) m(2, 140, d) +# define SEQAN_PP_REPEAT_1_142(m, d) SEQAN_PP_REPEAT_1_141(m, d) m(2, 141, d) +# define SEQAN_PP_REPEAT_1_143(m, d) SEQAN_PP_REPEAT_1_142(m, d) m(2, 142, d) +# define SEQAN_PP_REPEAT_1_144(m, d) SEQAN_PP_REPEAT_1_143(m, d) m(2, 143, d) +# define SEQAN_PP_REPEAT_1_145(m, d) SEQAN_PP_REPEAT_1_144(m, d) m(2, 144, d) +# define SEQAN_PP_REPEAT_1_146(m, d) SEQAN_PP_REPEAT_1_145(m, d) m(2, 145, d) +# define SEQAN_PP_REPEAT_1_147(m, d) SEQAN_PP_REPEAT_1_146(m, d) m(2, 146, d) +# define SEQAN_PP_REPEAT_1_148(m, d) SEQAN_PP_REPEAT_1_147(m, d) m(2, 147, d) +# define SEQAN_PP_REPEAT_1_149(m, d) SEQAN_PP_REPEAT_1_148(m, d) m(2, 148, d) +# define SEQAN_PP_REPEAT_1_150(m, d) SEQAN_PP_REPEAT_1_149(m, d) m(2, 149, d) +# define SEQAN_PP_REPEAT_1_151(m, d) SEQAN_PP_REPEAT_1_150(m, d) m(2, 150, d) +# define SEQAN_PP_REPEAT_1_152(m, d) SEQAN_PP_REPEAT_1_151(m, d) m(2, 151, d) +# define SEQAN_PP_REPEAT_1_153(m, d) SEQAN_PP_REPEAT_1_152(m, d) m(2, 152, d) +# define SEQAN_PP_REPEAT_1_154(m, d) SEQAN_PP_REPEAT_1_153(m, d) m(2, 153, d) +# define SEQAN_PP_REPEAT_1_155(m, d) SEQAN_PP_REPEAT_1_154(m, d) m(2, 154, d) +# define SEQAN_PP_REPEAT_1_156(m, d) SEQAN_PP_REPEAT_1_155(m, d) m(2, 155, d) +# define SEQAN_PP_REPEAT_1_157(m, d) SEQAN_PP_REPEAT_1_156(m, d) m(2, 156, d) +# define SEQAN_PP_REPEAT_1_158(m, d) SEQAN_PP_REPEAT_1_157(m, d) m(2, 157, d) +# define SEQAN_PP_REPEAT_1_159(m, d) SEQAN_PP_REPEAT_1_158(m, d) m(2, 158, d) +# define SEQAN_PP_REPEAT_1_160(m, d) SEQAN_PP_REPEAT_1_159(m, d) m(2, 159, d) +# define SEQAN_PP_REPEAT_1_161(m, d) SEQAN_PP_REPEAT_1_160(m, d) m(2, 160, d) +# define SEQAN_PP_REPEAT_1_162(m, d) SEQAN_PP_REPEAT_1_161(m, d) m(2, 161, d) +# define SEQAN_PP_REPEAT_1_163(m, d) SEQAN_PP_REPEAT_1_162(m, d) m(2, 162, d) +# define SEQAN_PP_REPEAT_1_164(m, d) SEQAN_PP_REPEAT_1_163(m, d) m(2, 163, d) +# define SEQAN_PP_REPEAT_1_165(m, d) SEQAN_PP_REPEAT_1_164(m, d) m(2, 164, d) +# define SEQAN_PP_REPEAT_1_166(m, d) SEQAN_PP_REPEAT_1_165(m, d) m(2, 165, d) +# define SEQAN_PP_REPEAT_1_167(m, d) SEQAN_PP_REPEAT_1_166(m, d) m(2, 166, d) +# define SEQAN_PP_REPEAT_1_168(m, d) SEQAN_PP_REPEAT_1_167(m, d) m(2, 167, d) +# define SEQAN_PP_REPEAT_1_169(m, d) SEQAN_PP_REPEAT_1_168(m, d) m(2, 168, d) +# define SEQAN_PP_REPEAT_1_170(m, d) SEQAN_PP_REPEAT_1_169(m, d) m(2, 169, d) +# define SEQAN_PP_REPEAT_1_171(m, d) SEQAN_PP_REPEAT_1_170(m, d) m(2, 170, d) +# define SEQAN_PP_REPEAT_1_172(m, d) SEQAN_PP_REPEAT_1_171(m, d) m(2, 171, d) +# define SEQAN_PP_REPEAT_1_173(m, d) SEQAN_PP_REPEAT_1_172(m, d) m(2, 172, d) +# define SEQAN_PP_REPEAT_1_174(m, d) SEQAN_PP_REPEAT_1_173(m, d) m(2, 173, d) +# define SEQAN_PP_REPEAT_1_175(m, d) SEQAN_PP_REPEAT_1_174(m, d) m(2, 174, d) +# define SEQAN_PP_REPEAT_1_176(m, d) SEQAN_PP_REPEAT_1_175(m, d) m(2, 175, d) +# define SEQAN_PP_REPEAT_1_177(m, d) SEQAN_PP_REPEAT_1_176(m, d) m(2, 176, d) +# define SEQAN_PP_REPEAT_1_178(m, d) SEQAN_PP_REPEAT_1_177(m, d) m(2, 177, d) +# define SEQAN_PP_REPEAT_1_179(m, d) SEQAN_PP_REPEAT_1_178(m, d) m(2, 178, d) +# define SEQAN_PP_REPEAT_1_180(m, d) SEQAN_PP_REPEAT_1_179(m, d) m(2, 179, d) +# define SEQAN_PP_REPEAT_1_181(m, d) SEQAN_PP_REPEAT_1_180(m, d) m(2, 180, d) +# define SEQAN_PP_REPEAT_1_182(m, d) SEQAN_PP_REPEAT_1_181(m, d) m(2, 181, d) +# define SEQAN_PP_REPEAT_1_183(m, d) SEQAN_PP_REPEAT_1_182(m, d) m(2, 182, d) +# define SEQAN_PP_REPEAT_1_184(m, d) SEQAN_PP_REPEAT_1_183(m, d) m(2, 183, d) +# define SEQAN_PP_REPEAT_1_185(m, d) SEQAN_PP_REPEAT_1_184(m, d) m(2, 184, d) +# define SEQAN_PP_REPEAT_1_186(m, d) SEQAN_PP_REPEAT_1_185(m, d) m(2, 185, d) +# define SEQAN_PP_REPEAT_1_187(m, d) SEQAN_PP_REPEAT_1_186(m, d) m(2, 186, d) +# define SEQAN_PP_REPEAT_1_188(m, d) SEQAN_PP_REPEAT_1_187(m, d) m(2, 187, d) +# define SEQAN_PP_REPEAT_1_189(m, d) SEQAN_PP_REPEAT_1_188(m, d) m(2, 188, d) +# define SEQAN_PP_REPEAT_1_190(m, d) SEQAN_PP_REPEAT_1_189(m, d) m(2, 189, d) +# define SEQAN_PP_REPEAT_1_191(m, d) SEQAN_PP_REPEAT_1_190(m, d) m(2, 190, d) +# define SEQAN_PP_REPEAT_1_192(m, d) SEQAN_PP_REPEAT_1_191(m, d) m(2, 191, d) +# define SEQAN_PP_REPEAT_1_193(m, d) SEQAN_PP_REPEAT_1_192(m, d) m(2, 192, d) +# define SEQAN_PP_REPEAT_1_194(m, d) SEQAN_PP_REPEAT_1_193(m, d) m(2, 193, d) +# define SEQAN_PP_REPEAT_1_195(m, d) SEQAN_PP_REPEAT_1_194(m, d) m(2, 194, d) +# define SEQAN_PP_REPEAT_1_196(m, d) SEQAN_PP_REPEAT_1_195(m, d) m(2, 195, d) +# define SEQAN_PP_REPEAT_1_197(m, d) SEQAN_PP_REPEAT_1_196(m, d) m(2, 196, d) +# define SEQAN_PP_REPEAT_1_198(m, d) SEQAN_PP_REPEAT_1_197(m, d) m(2, 197, d) +# define SEQAN_PP_REPEAT_1_199(m, d) SEQAN_PP_REPEAT_1_198(m, d) m(2, 198, d) +# define SEQAN_PP_REPEAT_1_200(m, d) SEQAN_PP_REPEAT_1_199(m, d) m(2, 199, d) +# define SEQAN_PP_REPEAT_1_201(m, d) SEQAN_PP_REPEAT_1_200(m, d) m(2, 200, d) +# define SEQAN_PP_REPEAT_1_202(m, d) SEQAN_PP_REPEAT_1_201(m, d) m(2, 201, d) +# define SEQAN_PP_REPEAT_1_203(m, d) SEQAN_PP_REPEAT_1_202(m, d) m(2, 202, d) +# define SEQAN_PP_REPEAT_1_204(m, d) SEQAN_PP_REPEAT_1_203(m, d) m(2, 203, d) +# define SEQAN_PP_REPEAT_1_205(m, d) SEQAN_PP_REPEAT_1_204(m, d) m(2, 204, d) +# define SEQAN_PP_REPEAT_1_206(m, d) SEQAN_PP_REPEAT_1_205(m, d) m(2, 205, d) +# define SEQAN_PP_REPEAT_1_207(m, d) SEQAN_PP_REPEAT_1_206(m, d) m(2, 206, d) +# define SEQAN_PP_REPEAT_1_208(m, d) SEQAN_PP_REPEAT_1_207(m, d) m(2, 207, d) +# define SEQAN_PP_REPEAT_1_209(m, d) SEQAN_PP_REPEAT_1_208(m, d) m(2, 208, d) +# define SEQAN_PP_REPEAT_1_210(m, d) SEQAN_PP_REPEAT_1_209(m, d) m(2, 209, d) +# define SEQAN_PP_REPEAT_1_211(m, d) SEQAN_PP_REPEAT_1_210(m, d) m(2, 210, d) +# define SEQAN_PP_REPEAT_1_212(m, d) SEQAN_PP_REPEAT_1_211(m, d) m(2, 211, d) +# define SEQAN_PP_REPEAT_1_213(m, d) SEQAN_PP_REPEAT_1_212(m, d) m(2, 212, d) +# define SEQAN_PP_REPEAT_1_214(m, d) SEQAN_PP_REPEAT_1_213(m, d) m(2, 213, d) +# define SEQAN_PP_REPEAT_1_215(m, d) SEQAN_PP_REPEAT_1_214(m, d) m(2, 214, d) +# define SEQAN_PP_REPEAT_1_216(m, d) SEQAN_PP_REPEAT_1_215(m, d) m(2, 215, d) +# define SEQAN_PP_REPEAT_1_217(m, d) SEQAN_PP_REPEAT_1_216(m, d) m(2, 216, d) +# define SEQAN_PP_REPEAT_1_218(m, d) SEQAN_PP_REPEAT_1_217(m, d) m(2, 217, d) +# define SEQAN_PP_REPEAT_1_219(m, d) SEQAN_PP_REPEAT_1_218(m, d) m(2, 218, d) +# define SEQAN_PP_REPEAT_1_220(m, d) SEQAN_PP_REPEAT_1_219(m, d) m(2, 219, d) +# define SEQAN_PP_REPEAT_1_221(m, d) SEQAN_PP_REPEAT_1_220(m, d) m(2, 220, d) +# define SEQAN_PP_REPEAT_1_222(m, d) SEQAN_PP_REPEAT_1_221(m, d) m(2, 221, d) +# define SEQAN_PP_REPEAT_1_223(m, d) SEQAN_PP_REPEAT_1_222(m, d) m(2, 222, d) +# define SEQAN_PP_REPEAT_1_224(m, d) SEQAN_PP_REPEAT_1_223(m, d) m(2, 223, d) +# define SEQAN_PP_REPEAT_1_225(m, d) SEQAN_PP_REPEAT_1_224(m, d) m(2, 224, d) +# define SEQAN_PP_REPEAT_1_226(m, d) SEQAN_PP_REPEAT_1_225(m, d) m(2, 225, d) +# define SEQAN_PP_REPEAT_1_227(m, d) SEQAN_PP_REPEAT_1_226(m, d) m(2, 226, d) +# define SEQAN_PP_REPEAT_1_228(m, d) SEQAN_PP_REPEAT_1_227(m, d) m(2, 227, d) +# define SEQAN_PP_REPEAT_1_229(m, d) SEQAN_PP_REPEAT_1_228(m, d) m(2, 228, d) +# define SEQAN_PP_REPEAT_1_230(m, d) SEQAN_PP_REPEAT_1_229(m, d) m(2, 229, d) +# define SEQAN_PP_REPEAT_1_231(m, d) SEQAN_PP_REPEAT_1_230(m, d) m(2, 230, d) +# define SEQAN_PP_REPEAT_1_232(m, d) SEQAN_PP_REPEAT_1_231(m, d) m(2, 231, d) +# define SEQAN_PP_REPEAT_1_233(m, d) SEQAN_PP_REPEAT_1_232(m, d) m(2, 232, d) +# define SEQAN_PP_REPEAT_1_234(m, d) SEQAN_PP_REPEAT_1_233(m, d) m(2, 233, d) +# define SEQAN_PP_REPEAT_1_235(m, d) SEQAN_PP_REPEAT_1_234(m, d) m(2, 234, d) +# define SEQAN_PP_REPEAT_1_236(m, d) SEQAN_PP_REPEAT_1_235(m, d) m(2, 235, d) +# define SEQAN_PP_REPEAT_1_237(m, d) SEQAN_PP_REPEAT_1_236(m, d) m(2, 236, d) +# define SEQAN_PP_REPEAT_1_238(m, d) SEQAN_PP_REPEAT_1_237(m, d) m(2, 237, d) +# define SEQAN_PP_REPEAT_1_239(m, d) SEQAN_PP_REPEAT_1_238(m, d) m(2, 238, d) +# define SEQAN_PP_REPEAT_1_240(m, d) SEQAN_PP_REPEAT_1_239(m, d) m(2, 239, d) +# define SEQAN_PP_REPEAT_1_241(m, d) SEQAN_PP_REPEAT_1_240(m, d) m(2, 240, d) +# define SEQAN_PP_REPEAT_1_242(m, d) SEQAN_PP_REPEAT_1_241(m, d) m(2, 241, d) +# define SEQAN_PP_REPEAT_1_243(m, d) SEQAN_PP_REPEAT_1_242(m, d) m(2, 242, d) +# define SEQAN_PP_REPEAT_1_244(m, d) SEQAN_PP_REPEAT_1_243(m, d) m(2, 243, d) +# define SEQAN_PP_REPEAT_1_245(m, d) SEQAN_PP_REPEAT_1_244(m, d) m(2, 244, d) +# define SEQAN_PP_REPEAT_1_246(m, d) SEQAN_PP_REPEAT_1_245(m, d) m(2, 245, d) +# define SEQAN_PP_REPEAT_1_247(m, d) SEQAN_PP_REPEAT_1_246(m, d) m(2, 246, d) +# define SEQAN_PP_REPEAT_1_248(m, d) SEQAN_PP_REPEAT_1_247(m, d) m(2, 247, d) +# define SEQAN_PP_REPEAT_1_249(m, d) SEQAN_PP_REPEAT_1_248(m, d) m(2, 248, d) +# define SEQAN_PP_REPEAT_1_250(m, d) SEQAN_PP_REPEAT_1_249(m, d) m(2, 249, d) +# define SEQAN_PP_REPEAT_1_251(m, d) SEQAN_PP_REPEAT_1_250(m, d) m(2, 250, d) +# define SEQAN_PP_REPEAT_1_252(m, d) SEQAN_PP_REPEAT_1_251(m, d) m(2, 251, d) +# define SEQAN_PP_REPEAT_1_253(m, d) SEQAN_PP_REPEAT_1_252(m, d) m(2, 252, d) +# define SEQAN_PP_REPEAT_1_254(m, d) SEQAN_PP_REPEAT_1_253(m, d) m(2, 253, d) +# define SEQAN_PP_REPEAT_1_255(m, d) SEQAN_PP_REPEAT_1_254(m, d) m(2, 254, d) +# define SEQAN_PP_REPEAT_1_256(m, d) SEQAN_PP_REPEAT_1_255(m, d) m(2, 255, d) +# +# define SEQAN_PP_REPEAT_2_0(m, d) +# define SEQAN_PP_REPEAT_2_1(m, d) m(3, 0, d) +# define SEQAN_PP_REPEAT_2_2(m, d) SEQAN_PP_REPEAT_2_1(m, d) m(3, 1, d) +# define SEQAN_PP_REPEAT_2_3(m, d) SEQAN_PP_REPEAT_2_2(m, d) m(3, 2, d) +# define SEQAN_PP_REPEAT_2_4(m, d) SEQAN_PP_REPEAT_2_3(m, d) m(3, 3, d) +# define SEQAN_PP_REPEAT_2_5(m, d) SEQAN_PP_REPEAT_2_4(m, d) m(3, 4, d) +# define SEQAN_PP_REPEAT_2_6(m, d) SEQAN_PP_REPEAT_2_5(m, d) m(3, 5, d) +# define SEQAN_PP_REPEAT_2_7(m, d) SEQAN_PP_REPEAT_2_6(m, d) m(3, 6, d) +# define SEQAN_PP_REPEAT_2_8(m, d) SEQAN_PP_REPEAT_2_7(m, d) m(3, 7, d) +# define SEQAN_PP_REPEAT_2_9(m, d) SEQAN_PP_REPEAT_2_8(m, d) m(3, 8, d) +# define SEQAN_PP_REPEAT_2_10(m, d) SEQAN_PP_REPEAT_2_9(m, d) m(3, 9, d) +# define SEQAN_PP_REPEAT_2_11(m, d) SEQAN_PP_REPEAT_2_10(m, d) m(3, 10, d) +# define SEQAN_PP_REPEAT_2_12(m, d) SEQAN_PP_REPEAT_2_11(m, d) m(3, 11, d) +# define SEQAN_PP_REPEAT_2_13(m, d) SEQAN_PP_REPEAT_2_12(m, d) m(3, 12, d) +# define SEQAN_PP_REPEAT_2_14(m, d) SEQAN_PP_REPEAT_2_13(m, d) m(3, 13, d) +# define SEQAN_PP_REPEAT_2_15(m, d) SEQAN_PP_REPEAT_2_14(m, d) m(3, 14, d) +# define SEQAN_PP_REPEAT_2_16(m, d) SEQAN_PP_REPEAT_2_15(m, d) m(3, 15, d) +# define SEQAN_PP_REPEAT_2_17(m, d) SEQAN_PP_REPEAT_2_16(m, d) m(3, 16, d) +# define SEQAN_PP_REPEAT_2_18(m, d) SEQAN_PP_REPEAT_2_17(m, d) m(3, 17, d) +# define SEQAN_PP_REPEAT_2_19(m, d) SEQAN_PP_REPEAT_2_18(m, d) m(3, 18, d) +# define SEQAN_PP_REPEAT_2_20(m, d) SEQAN_PP_REPEAT_2_19(m, d) m(3, 19, d) +# define SEQAN_PP_REPEAT_2_21(m, d) SEQAN_PP_REPEAT_2_20(m, d) m(3, 20, d) +# define SEQAN_PP_REPEAT_2_22(m, d) SEQAN_PP_REPEAT_2_21(m, d) m(3, 21, d) +# define SEQAN_PP_REPEAT_2_23(m, d) SEQAN_PP_REPEAT_2_22(m, d) m(3, 22, d) +# define SEQAN_PP_REPEAT_2_24(m, d) SEQAN_PP_REPEAT_2_23(m, d) m(3, 23, d) +# define SEQAN_PP_REPEAT_2_25(m, d) SEQAN_PP_REPEAT_2_24(m, d) m(3, 24, d) +# define SEQAN_PP_REPEAT_2_26(m, d) SEQAN_PP_REPEAT_2_25(m, d) m(3, 25, d) +# define SEQAN_PP_REPEAT_2_27(m, d) SEQAN_PP_REPEAT_2_26(m, d) m(3, 26, d) +# define SEQAN_PP_REPEAT_2_28(m, d) SEQAN_PP_REPEAT_2_27(m, d) m(3, 27, d) +# define SEQAN_PP_REPEAT_2_29(m, d) SEQAN_PP_REPEAT_2_28(m, d) m(3, 28, d) +# define SEQAN_PP_REPEAT_2_30(m, d) SEQAN_PP_REPEAT_2_29(m, d) m(3, 29, d) +# define SEQAN_PP_REPEAT_2_31(m, d) SEQAN_PP_REPEAT_2_30(m, d) m(3, 30, d) +# define SEQAN_PP_REPEAT_2_32(m, d) SEQAN_PP_REPEAT_2_31(m, d) m(3, 31, d) +# define SEQAN_PP_REPEAT_2_33(m, d) SEQAN_PP_REPEAT_2_32(m, d) m(3, 32, d) +# define SEQAN_PP_REPEAT_2_34(m, d) SEQAN_PP_REPEAT_2_33(m, d) m(3, 33, d) +# define SEQAN_PP_REPEAT_2_35(m, d) SEQAN_PP_REPEAT_2_34(m, d) m(3, 34, d) +# define SEQAN_PP_REPEAT_2_36(m, d) SEQAN_PP_REPEAT_2_35(m, d) m(3, 35, d) +# define SEQAN_PP_REPEAT_2_37(m, d) SEQAN_PP_REPEAT_2_36(m, d) m(3, 36, d) +# define SEQAN_PP_REPEAT_2_38(m, d) SEQAN_PP_REPEAT_2_37(m, d) m(3, 37, d) +# define SEQAN_PP_REPEAT_2_39(m, d) SEQAN_PP_REPEAT_2_38(m, d) m(3, 38, d) +# define SEQAN_PP_REPEAT_2_40(m, d) SEQAN_PP_REPEAT_2_39(m, d) m(3, 39, d) +# define SEQAN_PP_REPEAT_2_41(m, d) SEQAN_PP_REPEAT_2_40(m, d) m(3, 40, d) +# define SEQAN_PP_REPEAT_2_42(m, d) SEQAN_PP_REPEAT_2_41(m, d) m(3, 41, d) +# define SEQAN_PP_REPEAT_2_43(m, d) SEQAN_PP_REPEAT_2_42(m, d) m(3, 42, d) +# define SEQAN_PP_REPEAT_2_44(m, d) SEQAN_PP_REPEAT_2_43(m, d) m(3, 43, d) +# define SEQAN_PP_REPEAT_2_45(m, d) SEQAN_PP_REPEAT_2_44(m, d) m(3, 44, d) +# define SEQAN_PP_REPEAT_2_46(m, d) SEQAN_PP_REPEAT_2_45(m, d) m(3, 45, d) +# define SEQAN_PP_REPEAT_2_47(m, d) SEQAN_PP_REPEAT_2_46(m, d) m(3, 46, d) +# define SEQAN_PP_REPEAT_2_48(m, d) SEQAN_PP_REPEAT_2_47(m, d) m(3, 47, d) +# define SEQAN_PP_REPEAT_2_49(m, d) SEQAN_PP_REPEAT_2_48(m, d) m(3, 48, d) +# define SEQAN_PP_REPEAT_2_50(m, d) SEQAN_PP_REPEAT_2_49(m, d) m(3, 49, d) +# define SEQAN_PP_REPEAT_2_51(m, d) SEQAN_PP_REPEAT_2_50(m, d) m(3, 50, d) +# define SEQAN_PP_REPEAT_2_52(m, d) SEQAN_PP_REPEAT_2_51(m, d) m(3, 51, d) +# define SEQAN_PP_REPEAT_2_53(m, d) SEQAN_PP_REPEAT_2_52(m, d) m(3, 52, d) +# define SEQAN_PP_REPEAT_2_54(m, d) SEQAN_PP_REPEAT_2_53(m, d) m(3, 53, d) +# define SEQAN_PP_REPEAT_2_55(m, d) SEQAN_PP_REPEAT_2_54(m, d) m(3, 54, d) +# define SEQAN_PP_REPEAT_2_56(m, d) SEQAN_PP_REPEAT_2_55(m, d) m(3, 55, d) +# define SEQAN_PP_REPEAT_2_57(m, d) SEQAN_PP_REPEAT_2_56(m, d) m(3, 56, d) +# define SEQAN_PP_REPEAT_2_58(m, d) SEQAN_PP_REPEAT_2_57(m, d) m(3, 57, d) +# define SEQAN_PP_REPEAT_2_59(m, d) SEQAN_PP_REPEAT_2_58(m, d) m(3, 58, d) +# define SEQAN_PP_REPEAT_2_60(m, d) SEQAN_PP_REPEAT_2_59(m, d) m(3, 59, d) +# define SEQAN_PP_REPEAT_2_61(m, d) SEQAN_PP_REPEAT_2_60(m, d) m(3, 60, d) +# define SEQAN_PP_REPEAT_2_62(m, d) SEQAN_PP_REPEAT_2_61(m, d) m(3, 61, d) +# define SEQAN_PP_REPEAT_2_63(m, d) SEQAN_PP_REPEAT_2_62(m, d) m(3, 62, d) +# define SEQAN_PP_REPEAT_2_64(m, d) SEQAN_PP_REPEAT_2_63(m, d) m(3, 63, d) +# define SEQAN_PP_REPEAT_2_65(m, d) SEQAN_PP_REPEAT_2_64(m, d) m(3, 64, d) +# define SEQAN_PP_REPEAT_2_66(m, d) SEQAN_PP_REPEAT_2_65(m, d) m(3, 65, d) +# define SEQAN_PP_REPEAT_2_67(m, d) SEQAN_PP_REPEAT_2_66(m, d) m(3, 66, d) +# define SEQAN_PP_REPEAT_2_68(m, d) SEQAN_PP_REPEAT_2_67(m, d) m(3, 67, d) +# define SEQAN_PP_REPEAT_2_69(m, d) SEQAN_PP_REPEAT_2_68(m, d) m(3, 68, d) +# define SEQAN_PP_REPEAT_2_70(m, d) SEQAN_PP_REPEAT_2_69(m, d) m(3, 69, d) +# define SEQAN_PP_REPEAT_2_71(m, d) SEQAN_PP_REPEAT_2_70(m, d) m(3, 70, d) +# define SEQAN_PP_REPEAT_2_72(m, d) SEQAN_PP_REPEAT_2_71(m, d) m(3, 71, d) +# define SEQAN_PP_REPEAT_2_73(m, d) SEQAN_PP_REPEAT_2_72(m, d) m(3, 72, d) +# define SEQAN_PP_REPEAT_2_74(m, d) SEQAN_PP_REPEAT_2_73(m, d) m(3, 73, d) +# define SEQAN_PP_REPEAT_2_75(m, d) SEQAN_PP_REPEAT_2_74(m, d) m(3, 74, d) +# define SEQAN_PP_REPEAT_2_76(m, d) SEQAN_PP_REPEAT_2_75(m, d) m(3, 75, d) +# define SEQAN_PP_REPEAT_2_77(m, d) SEQAN_PP_REPEAT_2_76(m, d) m(3, 76, d) +# define SEQAN_PP_REPEAT_2_78(m, d) SEQAN_PP_REPEAT_2_77(m, d) m(3, 77, d) +# define SEQAN_PP_REPEAT_2_79(m, d) SEQAN_PP_REPEAT_2_78(m, d) m(3, 78, d) +# define SEQAN_PP_REPEAT_2_80(m, d) SEQAN_PP_REPEAT_2_79(m, d) m(3, 79, d) +# define SEQAN_PP_REPEAT_2_81(m, d) SEQAN_PP_REPEAT_2_80(m, d) m(3, 80, d) +# define SEQAN_PP_REPEAT_2_82(m, d) SEQAN_PP_REPEAT_2_81(m, d) m(3, 81, d) +# define SEQAN_PP_REPEAT_2_83(m, d) SEQAN_PP_REPEAT_2_82(m, d) m(3, 82, d) +# define SEQAN_PP_REPEAT_2_84(m, d) SEQAN_PP_REPEAT_2_83(m, d) m(3, 83, d) +# define SEQAN_PP_REPEAT_2_85(m, d) SEQAN_PP_REPEAT_2_84(m, d) m(3, 84, d) +# define SEQAN_PP_REPEAT_2_86(m, d) SEQAN_PP_REPEAT_2_85(m, d) m(3, 85, d) +# define SEQAN_PP_REPEAT_2_87(m, d) SEQAN_PP_REPEAT_2_86(m, d) m(3, 86, d) +# define SEQAN_PP_REPEAT_2_88(m, d) SEQAN_PP_REPEAT_2_87(m, d) m(3, 87, d) +# define SEQAN_PP_REPEAT_2_89(m, d) SEQAN_PP_REPEAT_2_88(m, d) m(3, 88, d) +# define SEQAN_PP_REPEAT_2_90(m, d) SEQAN_PP_REPEAT_2_89(m, d) m(3, 89, d) +# define SEQAN_PP_REPEAT_2_91(m, d) SEQAN_PP_REPEAT_2_90(m, d) m(3, 90, d) +# define SEQAN_PP_REPEAT_2_92(m, d) SEQAN_PP_REPEAT_2_91(m, d) m(3, 91, d) +# define SEQAN_PP_REPEAT_2_93(m, d) SEQAN_PP_REPEAT_2_92(m, d) m(3, 92, d) +# define SEQAN_PP_REPEAT_2_94(m, d) SEQAN_PP_REPEAT_2_93(m, d) m(3, 93, d) +# define SEQAN_PP_REPEAT_2_95(m, d) SEQAN_PP_REPEAT_2_94(m, d) m(3, 94, d) +# define SEQAN_PP_REPEAT_2_96(m, d) SEQAN_PP_REPEAT_2_95(m, d) m(3, 95, d) +# define SEQAN_PP_REPEAT_2_97(m, d) SEQAN_PP_REPEAT_2_96(m, d) m(3, 96, d) +# define SEQAN_PP_REPEAT_2_98(m, d) SEQAN_PP_REPEAT_2_97(m, d) m(3, 97, d) +# define SEQAN_PP_REPEAT_2_99(m, d) SEQAN_PP_REPEAT_2_98(m, d) m(3, 98, d) +# define SEQAN_PP_REPEAT_2_100(m, d) SEQAN_PP_REPEAT_2_99(m, d) m(3, 99, d) +# define SEQAN_PP_REPEAT_2_101(m, d) SEQAN_PP_REPEAT_2_100(m, d) m(3, 100, d) +# define SEQAN_PP_REPEAT_2_102(m, d) SEQAN_PP_REPEAT_2_101(m, d) m(3, 101, d) +# define SEQAN_PP_REPEAT_2_103(m, d) SEQAN_PP_REPEAT_2_102(m, d) m(3, 102, d) +# define SEQAN_PP_REPEAT_2_104(m, d) SEQAN_PP_REPEAT_2_103(m, d) m(3, 103, d) +# define SEQAN_PP_REPEAT_2_105(m, d) SEQAN_PP_REPEAT_2_104(m, d) m(3, 104, d) +# define SEQAN_PP_REPEAT_2_106(m, d) SEQAN_PP_REPEAT_2_105(m, d) m(3, 105, d) +# define SEQAN_PP_REPEAT_2_107(m, d) SEQAN_PP_REPEAT_2_106(m, d) m(3, 106, d) +# define SEQAN_PP_REPEAT_2_108(m, d) SEQAN_PP_REPEAT_2_107(m, d) m(3, 107, d) +# define SEQAN_PP_REPEAT_2_109(m, d) SEQAN_PP_REPEAT_2_108(m, d) m(3, 108, d) +# define SEQAN_PP_REPEAT_2_110(m, d) SEQAN_PP_REPEAT_2_109(m, d) m(3, 109, d) +# define SEQAN_PP_REPEAT_2_111(m, d) SEQAN_PP_REPEAT_2_110(m, d) m(3, 110, d) +# define SEQAN_PP_REPEAT_2_112(m, d) SEQAN_PP_REPEAT_2_111(m, d) m(3, 111, d) +# define SEQAN_PP_REPEAT_2_113(m, d) SEQAN_PP_REPEAT_2_112(m, d) m(3, 112, d) +# define SEQAN_PP_REPEAT_2_114(m, d) SEQAN_PP_REPEAT_2_113(m, d) m(3, 113, d) +# define SEQAN_PP_REPEAT_2_115(m, d) SEQAN_PP_REPEAT_2_114(m, d) m(3, 114, d) +# define SEQAN_PP_REPEAT_2_116(m, d) SEQAN_PP_REPEAT_2_115(m, d) m(3, 115, d) +# define SEQAN_PP_REPEAT_2_117(m, d) SEQAN_PP_REPEAT_2_116(m, d) m(3, 116, d) +# define SEQAN_PP_REPEAT_2_118(m, d) SEQAN_PP_REPEAT_2_117(m, d) m(3, 117, d) +# define SEQAN_PP_REPEAT_2_119(m, d) SEQAN_PP_REPEAT_2_118(m, d) m(3, 118, d) +# define SEQAN_PP_REPEAT_2_120(m, d) SEQAN_PP_REPEAT_2_119(m, d) m(3, 119, d) +# define SEQAN_PP_REPEAT_2_121(m, d) SEQAN_PP_REPEAT_2_120(m, d) m(3, 120, d) +# define SEQAN_PP_REPEAT_2_122(m, d) SEQAN_PP_REPEAT_2_121(m, d) m(3, 121, d) +# define SEQAN_PP_REPEAT_2_123(m, d) SEQAN_PP_REPEAT_2_122(m, d) m(3, 122, d) +# define SEQAN_PP_REPEAT_2_124(m, d) SEQAN_PP_REPEAT_2_123(m, d) m(3, 123, d) +# define SEQAN_PP_REPEAT_2_125(m, d) SEQAN_PP_REPEAT_2_124(m, d) m(3, 124, d) +# define SEQAN_PP_REPEAT_2_126(m, d) SEQAN_PP_REPEAT_2_125(m, d) m(3, 125, d) +# define SEQAN_PP_REPEAT_2_127(m, d) SEQAN_PP_REPEAT_2_126(m, d) m(3, 126, d) +# define SEQAN_PP_REPEAT_2_128(m, d) SEQAN_PP_REPEAT_2_127(m, d) m(3, 127, d) +# define SEQAN_PP_REPEAT_2_129(m, d) SEQAN_PP_REPEAT_2_128(m, d) m(3, 128, d) +# define SEQAN_PP_REPEAT_2_130(m, d) SEQAN_PP_REPEAT_2_129(m, d) m(3, 129, d) +# define SEQAN_PP_REPEAT_2_131(m, d) SEQAN_PP_REPEAT_2_130(m, d) m(3, 130, d) +# define SEQAN_PP_REPEAT_2_132(m, d) SEQAN_PP_REPEAT_2_131(m, d) m(3, 131, d) +# define SEQAN_PP_REPEAT_2_133(m, d) SEQAN_PP_REPEAT_2_132(m, d) m(3, 132, d) +# define SEQAN_PP_REPEAT_2_134(m, d) SEQAN_PP_REPEAT_2_133(m, d) m(3, 133, d) +# define SEQAN_PP_REPEAT_2_135(m, d) SEQAN_PP_REPEAT_2_134(m, d) m(3, 134, d) +# define SEQAN_PP_REPEAT_2_136(m, d) SEQAN_PP_REPEAT_2_135(m, d) m(3, 135, d) +# define SEQAN_PP_REPEAT_2_137(m, d) SEQAN_PP_REPEAT_2_136(m, d) m(3, 136, d) +# define SEQAN_PP_REPEAT_2_138(m, d) SEQAN_PP_REPEAT_2_137(m, d) m(3, 137, d) +# define SEQAN_PP_REPEAT_2_139(m, d) SEQAN_PP_REPEAT_2_138(m, d) m(3, 138, d) +# define SEQAN_PP_REPEAT_2_140(m, d) SEQAN_PP_REPEAT_2_139(m, d) m(3, 139, d) +# define SEQAN_PP_REPEAT_2_141(m, d) SEQAN_PP_REPEAT_2_140(m, d) m(3, 140, d) +# define SEQAN_PP_REPEAT_2_142(m, d) SEQAN_PP_REPEAT_2_141(m, d) m(3, 141, d) +# define SEQAN_PP_REPEAT_2_143(m, d) SEQAN_PP_REPEAT_2_142(m, d) m(3, 142, d) +# define SEQAN_PP_REPEAT_2_144(m, d) SEQAN_PP_REPEAT_2_143(m, d) m(3, 143, d) +# define SEQAN_PP_REPEAT_2_145(m, d) SEQAN_PP_REPEAT_2_144(m, d) m(3, 144, d) +# define SEQAN_PP_REPEAT_2_146(m, d) SEQAN_PP_REPEAT_2_145(m, d) m(3, 145, d) +# define SEQAN_PP_REPEAT_2_147(m, d) SEQAN_PP_REPEAT_2_146(m, d) m(3, 146, d) +# define SEQAN_PP_REPEAT_2_148(m, d) SEQAN_PP_REPEAT_2_147(m, d) m(3, 147, d) +# define SEQAN_PP_REPEAT_2_149(m, d) SEQAN_PP_REPEAT_2_148(m, d) m(3, 148, d) +# define SEQAN_PP_REPEAT_2_150(m, d) SEQAN_PP_REPEAT_2_149(m, d) m(3, 149, d) +# define SEQAN_PP_REPEAT_2_151(m, d) SEQAN_PP_REPEAT_2_150(m, d) m(3, 150, d) +# define SEQAN_PP_REPEAT_2_152(m, d) SEQAN_PP_REPEAT_2_151(m, d) m(3, 151, d) +# define SEQAN_PP_REPEAT_2_153(m, d) SEQAN_PP_REPEAT_2_152(m, d) m(3, 152, d) +# define SEQAN_PP_REPEAT_2_154(m, d) SEQAN_PP_REPEAT_2_153(m, d) m(3, 153, d) +# define SEQAN_PP_REPEAT_2_155(m, d) SEQAN_PP_REPEAT_2_154(m, d) m(3, 154, d) +# define SEQAN_PP_REPEAT_2_156(m, d) SEQAN_PP_REPEAT_2_155(m, d) m(3, 155, d) +# define SEQAN_PP_REPEAT_2_157(m, d) SEQAN_PP_REPEAT_2_156(m, d) m(3, 156, d) +# define SEQAN_PP_REPEAT_2_158(m, d) SEQAN_PP_REPEAT_2_157(m, d) m(3, 157, d) +# define SEQAN_PP_REPEAT_2_159(m, d) SEQAN_PP_REPEAT_2_158(m, d) m(3, 158, d) +# define SEQAN_PP_REPEAT_2_160(m, d) SEQAN_PP_REPEAT_2_159(m, d) m(3, 159, d) +# define SEQAN_PP_REPEAT_2_161(m, d) SEQAN_PP_REPEAT_2_160(m, d) m(3, 160, d) +# define SEQAN_PP_REPEAT_2_162(m, d) SEQAN_PP_REPEAT_2_161(m, d) m(3, 161, d) +# define SEQAN_PP_REPEAT_2_163(m, d) SEQAN_PP_REPEAT_2_162(m, d) m(3, 162, d) +# define SEQAN_PP_REPEAT_2_164(m, d) SEQAN_PP_REPEAT_2_163(m, d) m(3, 163, d) +# define SEQAN_PP_REPEAT_2_165(m, d) SEQAN_PP_REPEAT_2_164(m, d) m(3, 164, d) +# define SEQAN_PP_REPEAT_2_166(m, d) SEQAN_PP_REPEAT_2_165(m, d) m(3, 165, d) +# define SEQAN_PP_REPEAT_2_167(m, d) SEQAN_PP_REPEAT_2_166(m, d) m(3, 166, d) +# define SEQAN_PP_REPEAT_2_168(m, d) SEQAN_PP_REPEAT_2_167(m, d) m(3, 167, d) +# define SEQAN_PP_REPEAT_2_169(m, d) SEQAN_PP_REPEAT_2_168(m, d) m(3, 168, d) +# define SEQAN_PP_REPEAT_2_170(m, d) SEQAN_PP_REPEAT_2_169(m, d) m(3, 169, d) +# define SEQAN_PP_REPEAT_2_171(m, d) SEQAN_PP_REPEAT_2_170(m, d) m(3, 170, d) +# define SEQAN_PP_REPEAT_2_172(m, d) SEQAN_PP_REPEAT_2_171(m, d) m(3, 171, d) +# define SEQAN_PP_REPEAT_2_173(m, d) SEQAN_PP_REPEAT_2_172(m, d) m(3, 172, d) +# define SEQAN_PP_REPEAT_2_174(m, d) SEQAN_PP_REPEAT_2_173(m, d) m(3, 173, d) +# define SEQAN_PP_REPEAT_2_175(m, d) SEQAN_PP_REPEAT_2_174(m, d) m(3, 174, d) +# define SEQAN_PP_REPEAT_2_176(m, d) SEQAN_PP_REPEAT_2_175(m, d) m(3, 175, d) +# define SEQAN_PP_REPEAT_2_177(m, d) SEQAN_PP_REPEAT_2_176(m, d) m(3, 176, d) +# define SEQAN_PP_REPEAT_2_178(m, d) SEQAN_PP_REPEAT_2_177(m, d) m(3, 177, d) +# define SEQAN_PP_REPEAT_2_179(m, d) SEQAN_PP_REPEAT_2_178(m, d) m(3, 178, d) +# define SEQAN_PP_REPEAT_2_180(m, d) SEQAN_PP_REPEAT_2_179(m, d) m(3, 179, d) +# define SEQAN_PP_REPEAT_2_181(m, d) SEQAN_PP_REPEAT_2_180(m, d) m(3, 180, d) +# define SEQAN_PP_REPEAT_2_182(m, d) SEQAN_PP_REPEAT_2_181(m, d) m(3, 181, d) +# define SEQAN_PP_REPEAT_2_183(m, d) SEQAN_PP_REPEAT_2_182(m, d) m(3, 182, d) +# define SEQAN_PP_REPEAT_2_184(m, d) SEQAN_PP_REPEAT_2_183(m, d) m(3, 183, d) +# define SEQAN_PP_REPEAT_2_185(m, d) SEQAN_PP_REPEAT_2_184(m, d) m(3, 184, d) +# define SEQAN_PP_REPEAT_2_186(m, d) SEQAN_PP_REPEAT_2_185(m, d) m(3, 185, d) +# define SEQAN_PP_REPEAT_2_187(m, d) SEQAN_PP_REPEAT_2_186(m, d) m(3, 186, d) +# define SEQAN_PP_REPEAT_2_188(m, d) SEQAN_PP_REPEAT_2_187(m, d) m(3, 187, d) +# define SEQAN_PP_REPEAT_2_189(m, d) SEQAN_PP_REPEAT_2_188(m, d) m(3, 188, d) +# define SEQAN_PP_REPEAT_2_190(m, d) SEQAN_PP_REPEAT_2_189(m, d) m(3, 189, d) +# define SEQAN_PP_REPEAT_2_191(m, d) SEQAN_PP_REPEAT_2_190(m, d) m(3, 190, d) +# define SEQAN_PP_REPEAT_2_192(m, d) SEQAN_PP_REPEAT_2_191(m, d) m(3, 191, d) +# define SEQAN_PP_REPEAT_2_193(m, d) SEQAN_PP_REPEAT_2_192(m, d) m(3, 192, d) +# define SEQAN_PP_REPEAT_2_194(m, d) SEQAN_PP_REPEAT_2_193(m, d) m(3, 193, d) +# define SEQAN_PP_REPEAT_2_195(m, d) SEQAN_PP_REPEAT_2_194(m, d) m(3, 194, d) +# define SEQAN_PP_REPEAT_2_196(m, d) SEQAN_PP_REPEAT_2_195(m, d) m(3, 195, d) +# define SEQAN_PP_REPEAT_2_197(m, d) SEQAN_PP_REPEAT_2_196(m, d) m(3, 196, d) +# define SEQAN_PP_REPEAT_2_198(m, d) SEQAN_PP_REPEAT_2_197(m, d) m(3, 197, d) +# define SEQAN_PP_REPEAT_2_199(m, d) SEQAN_PP_REPEAT_2_198(m, d) m(3, 198, d) +# define SEQAN_PP_REPEAT_2_200(m, d) SEQAN_PP_REPEAT_2_199(m, d) m(3, 199, d) +# define SEQAN_PP_REPEAT_2_201(m, d) SEQAN_PP_REPEAT_2_200(m, d) m(3, 200, d) +# define SEQAN_PP_REPEAT_2_202(m, d) SEQAN_PP_REPEAT_2_201(m, d) m(3, 201, d) +# define SEQAN_PP_REPEAT_2_203(m, d) SEQAN_PP_REPEAT_2_202(m, d) m(3, 202, d) +# define SEQAN_PP_REPEAT_2_204(m, d) SEQAN_PP_REPEAT_2_203(m, d) m(3, 203, d) +# define SEQAN_PP_REPEAT_2_205(m, d) SEQAN_PP_REPEAT_2_204(m, d) m(3, 204, d) +# define SEQAN_PP_REPEAT_2_206(m, d) SEQAN_PP_REPEAT_2_205(m, d) m(3, 205, d) +# define SEQAN_PP_REPEAT_2_207(m, d) SEQAN_PP_REPEAT_2_206(m, d) m(3, 206, d) +# define SEQAN_PP_REPEAT_2_208(m, d) SEQAN_PP_REPEAT_2_207(m, d) m(3, 207, d) +# define SEQAN_PP_REPEAT_2_209(m, d) SEQAN_PP_REPEAT_2_208(m, d) m(3, 208, d) +# define SEQAN_PP_REPEAT_2_210(m, d) SEQAN_PP_REPEAT_2_209(m, d) m(3, 209, d) +# define SEQAN_PP_REPEAT_2_211(m, d) SEQAN_PP_REPEAT_2_210(m, d) m(3, 210, d) +# define SEQAN_PP_REPEAT_2_212(m, d) SEQAN_PP_REPEAT_2_211(m, d) m(3, 211, d) +# define SEQAN_PP_REPEAT_2_213(m, d) SEQAN_PP_REPEAT_2_212(m, d) m(3, 212, d) +# define SEQAN_PP_REPEAT_2_214(m, d) SEQAN_PP_REPEAT_2_213(m, d) m(3, 213, d) +# define SEQAN_PP_REPEAT_2_215(m, d) SEQAN_PP_REPEAT_2_214(m, d) m(3, 214, d) +# define SEQAN_PP_REPEAT_2_216(m, d) SEQAN_PP_REPEAT_2_215(m, d) m(3, 215, d) +# define SEQAN_PP_REPEAT_2_217(m, d) SEQAN_PP_REPEAT_2_216(m, d) m(3, 216, d) +# define SEQAN_PP_REPEAT_2_218(m, d) SEQAN_PP_REPEAT_2_217(m, d) m(3, 217, d) +# define SEQAN_PP_REPEAT_2_219(m, d) SEQAN_PP_REPEAT_2_218(m, d) m(3, 218, d) +# define SEQAN_PP_REPEAT_2_220(m, d) SEQAN_PP_REPEAT_2_219(m, d) m(3, 219, d) +# define SEQAN_PP_REPEAT_2_221(m, d) SEQAN_PP_REPEAT_2_220(m, d) m(3, 220, d) +# define SEQAN_PP_REPEAT_2_222(m, d) SEQAN_PP_REPEAT_2_221(m, d) m(3, 221, d) +# define SEQAN_PP_REPEAT_2_223(m, d) SEQAN_PP_REPEAT_2_222(m, d) m(3, 222, d) +# define SEQAN_PP_REPEAT_2_224(m, d) SEQAN_PP_REPEAT_2_223(m, d) m(3, 223, d) +# define SEQAN_PP_REPEAT_2_225(m, d) SEQAN_PP_REPEAT_2_224(m, d) m(3, 224, d) +# define SEQAN_PP_REPEAT_2_226(m, d) SEQAN_PP_REPEAT_2_225(m, d) m(3, 225, d) +# define SEQAN_PP_REPEAT_2_227(m, d) SEQAN_PP_REPEAT_2_226(m, d) m(3, 226, d) +# define SEQAN_PP_REPEAT_2_228(m, d) SEQAN_PP_REPEAT_2_227(m, d) m(3, 227, d) +# define SEQAN_PP_REPEAT_2_229(m, d) SEQAN_PP_REPEAT_2_228(m, d) m(3, 228, d) +# define SEQAN_PP_REPEAT_2_230(m, d) SEQAN_PP_REPEAT_2_229(m, d) m(3, 229, d) +# define SEQAN_PP_REPEAT_2_231(m, d) SEQAN_PP_REPEAT_2_230(m, d) m(3, 230, d) +# define SEQAN_PP_REPEAT_2_232(m, d) SEQAN_PP_REPEAT_2_231(m, d) m(3, 231, d) +# define SEQAN_PP_REPEAT_2_233(m, d) SEQAN_PP_REPEAT_2_232(m, d) m(3, 232, d) +# define SEQAN_PP_REPEAT_2_234(m, d) SEQAN_PP_REPEAT_2_233(m, d) m(3, 233, d) +# define SEQAN_PP_REPEAT_2_235(m, d) SEQAN_PP_REPEAT_2_234(m, d) m(3, 234, d) +# define SEQAN_PP_REPEAT_2_236(m, d) SEQAN_PP_REPEAT_2_235(m, d) m(3, 235, d) +# define SEQAN_PP_REPEAT_2_237(m, d) SEQAN_PP_REPEAT_2_236(m, d) m(3, 236, d) +# define SEQAN_PP_REPEAT_2_238(m, d) SEQAN_PP_REPEAT_2_237(m, d) m(3, 237, d) +# define SEQAN_PP_REPEAT_2_239(m, d) SEQAN_PP_REPEAT_2_238(m, d) m(3, 238, d) +# define SEQAN_PP_REPEAT_2_240(m, d) SEQAN_PP_REPEAT_2_239(m, d) m(3, 239, d) +# define SEQAN_PP_REPEAT_2_241(m, d) SEQAN_PP_REPEAT_2_240(m, d) m(3, 240, d) +# define SEQAN_PP_REPEAT_2_242(m, d) SEQAN_PP_REPEAT_2_241(m, d) m(3, 241, d) +# define SEQAN_PP_REPEAT_2_243(m, d) SEQAN_PP_REPEAT_2_242(m, d) m(3, 242, d) +# define SEQAN_PP_REPEAT_2_244(m, d) SEQAN_PP_REPEAT_2_243(m, d) m(3, 243, d) +# define SEQAN_PP_REPEAT_2_245(m, d) SEQAN_PP_REPEAT_2_244(m, d) m(3, 244, d) +# define SEQAN_PP_REPEAT_2_246(m, d) SEQAN_PP_REPEAT_2_245(m, d) m(3, 245, d) +# define SEQAN_PP_REPEAT_2_247(m, d) SEQAN_PP_REPEAT_2_246(m, d) m(3, 246, d) +# define SEQAN_PP_REPEAT_2_248(m, d) SEQAN_PP_REPEAT_2_247(m, d) m(3, 247, d) +# define SEQAN_PP_REPEAT_2_249(m, d) SEQAN_PP_REPEAT_2_248(m, d) m(3, 248, d) +# define SEQAN_PP_REPEAT_2_250(m, d) SEQAN_PP_REPEAT_2_249(m, d) m(3, 249, d) +# define SEQAN_PP_REPEAT_2_251(m, d) SEQAN_PP_REPEAT_2_250(m, d) m(3, 250, d) +# define SEQAN_PP_REPEAT_2_252(m, d) SEQAN_PP_REPEAT_2_251(m, d) m(3, 251, d) +# define SEQAN_PP_REPEAT_2_253(m, d) SEQAN_PP_REPEAT_2_252(m, d) m(3, 252, d) +# define SEQAN_PP_REPEAT_2_254(m, d) SEQAN_PP_REPEAT_2_253(m, d) m(3, 253, d) +# define SEQAN_PP_REPEAT_2_255(m, d) SEQAN_PP_REPEAT_2_254(m, d) m(3, 254, d) +# define SEQAN_PP_REPEAT_2_256(m, d) SEQAN_PP_REPEAT_2_255(m, d) m(3, 255, d) +# +# define SEQAN_PP_REPEAT_3_0(m, d) +# define SEQAN_PP_REPEAT_3_1(m, d) m(4, 0, d) +# define SEQAN_PP_REPEAT_3_2(m, d) SEQAN_PP_REPEAT_3_1(m, d) m(4, 1, d) +# define SEQAN_PP_REPEAT_3_3(m, d) SEQAN_PP_REPEAT_3_2(m, d) m(4, 2, d) +# define SEQAN_PP_REPEAT_3_4(m, d) SEQAN_PP_REPEAT_3_3(m, d) m(4, 3, d) +# define SEQAN_PP_REPEAT_3_5(m, d) SEQAN_PP_REPEAT_3_4(m, d) m(4, 4, d) +# define SEQAN_PP_REPEAT_3_6(m, d) SEQAN_PP_REPEAT_3_5(m, d) m(4, 5, d) +# define SEQAN_PP_REPEAT_3_7(m, d) SEQAN_PP_REPEAT_3_6(m, d) m(4, 6, d) +# define SEQAN_PP_REPEAT_3_8(m, d) SEQAN_PP_REPEAT_3_7(m, d) m(4, 7, d) +# define SEQAN_PP_REPEAT_3_9(m, d) SEQAN_PP_REPEAT_3_8(m, d) m(4, 8, d) +# define SEQAN_PP_REPEAT_3_10(m, d) SEQAN_PP_REPEAT_3_9(m, d) m(4, 9, d) +# define SEQAN_PP_REPEAT_3_11(m, d) SEQAN_PP_REPEAT_3_10(m, d) m(4, 10, d) +# define SEQAN_PP_REPEAT_3_12(m, d) SEQAN_PP_REPEAT_3_11(m, d) m(4, 11, d) +# define SEQAN_PP_REPEAT_3_13(m, d) SEQAN_PP_REPEAT_3_12(m, d) m(4, 12, d) +# define SEQAN_PP_REPEAT_3_14(m, d) SEQAN_PP_REPEAT_3_13(m, d) m(4, 13, d) +# define SEQAN_PP_REPEAT_3_15(m, d) SEQAN_PP_REPEAT_3_14(m, d) m(4, 14, d) +# define SEQAN_PP_REPEAT_3_16(m, d) SEQAN_PP_REPEAT_3_15(m, d) m(4, 15, d) +# define SEQAN_PP_REPEAT_3_17(m, d) SEQAN_PP_REPEAT_3_16(m, d) m(4, 16, d) +# define SEQAN_PP_REPEAT_3_18(m, d) SEQAN_PP_REPEAT_3_17(m, d) m(4, 17, d) +# define SEQAN_PP_REPEAT_3_19(m, d) SEQAN_PP_REPEAT_3_18(m, d) m(4, 18, d) +# define SEQAN_PP_REPEAT_3_20(m, d) SEQAN_PP_REPEAT_3_19(m, d) m(4, 19, d) +# define SEQAN_PP_REPEAT_3_21(m, d) SEQAN_PP_REPEAT_3_20(m, d) m(4, 20, d) +# define SEQAN_PP_REPEAT_3_22(m, d) SEQAN_PP_REPEAT_3_21(m, d) m(4, 21, d) +# define SEQAN_PP_REPEAT_3_23(m, d) SEQAN_PP_REPEAT_3_22(m, d) m(4, 22, d) +# define SEQAN_PP_REPEAT_3_24(m, d) SEQAN_PP_REPEAT_3_23(m, d) m(4, 23, d) +# define SEQAN_PP_REPEAT_3_25(m, d) SEQAN_PP_REPEAT_3_24(m, d) m(4, 24, d) +# define SEQAN_PP_REPEAT_3_26(m, d) SEQAN_PP_REPEAT_3_25(m, d) m(4, 25, d) +# define SEQAN_PP_REPEAT_3_27(m, d) SEQAN_PP_REPEAT_3_26(m, d) m(4, 26, d) +# define SEQAN_PP_REPEAT_3_28(m, d) SEQAN_PP_REPEAT_3_27(m, d) m(4, 27, d) +# define SEQAN_PP_REPEAT_3_29(m, d) SEQAN_PP_REPEAT_3_28(m, d) m(4, 28, d) +# define SEQAN_PP_REPEAT_3_30(m, d) SEQAN_PP_REPEAT_3_29(m, d) m(4, 29, d) +# define SEQAN_PP_REPEAT_3_31(m, d) SEQAN_PP_REPEAT_3_30(m, d) m(4, 30, d) +# define SEQAN_PP_REPEAT_3_32(m, d) SEQAN_PP_REPEAT_3_31(m, d) m(4, 31, d) +# define SEQAN_PP_REPEAT_3_33(m, d) SEQAN_PP_REPEAT_3_32(m, d) m(4, 32, d) +# define SEQAN_PP_REPEAT_3_34(m, d) SEQAN_PP_REPEAT_3_33(m, d) m(4, 33, d) +# define SEQAN_PP_REPEAT_3_35(m, d) SEQAN_PP_REPEAT_3_34(m, d) m(4, 34, d) +# define SEQAN_PP_REPEAT_3_36(m, d) SEQAN_PP_REPEAT_3_35(m, d) m(4, 35, d) +# define SEQAN_PP_REPEAT_3_37(m, d) SEQAN_PP_REPEAT_3_36(m, d) m(4, 36, d) +# define SEQAN_PP_REPEAT_3_38(m, d) SEQAN_PP_REPEAT_3_37(m, d) m(4, 37, d) +# define SEQAN_PP_REPEAT_3_39(m, d) SEQAN_PP_REPEAT_3_38(m, d) m(4, 38, d) +# define SEQAN_PP_REPEAT_3_40(m, d) SEQAN_PP_REPEAT_3_39(m, d) m(4, 39, d) +# define SEQAN_PP_REPEAT_3_41(m, d) SEQAN_PP_REPEAT_3_40(m, d) m(4, 40, d) +# define SEQAN_PP_REPEAT_3_42(m, d) SEQAN_PP_REPEAT_3_41(m, d) m(4, 41, d) +# define SEQAN_PP_REPEAT_3_43(m, d) SEQAN_PP_REPEAT_3_42(m, d) m(4, 42, d) +# define SEQAN_PP_REPEAT_3_44(m, d) SEQAN_PP_REPEAT_3_43(m, d) m(4, 43, d) +# define SEQAN_PP_REPEAT_3_45(m, d) SEQAN_PP_REPEAT_3_44(m, d) m(4, 44, d) +# define SEQAN_PP_REPEAT_3_46(m, d) SEQAN_PP_REPEAT_3_45(m, d) m(4, 45, d) +# define SEQAN_PP_REPEAT_3_47(m, d) SEQAN_PP_REPEAT_3_46(m, d) m(4, 46, d) +# define SEQAN_PP_REPEAT_3_48(m, d) SEQAN_PP_REPEAT_3_47(m, d) m(4, 47, d) +# define SEQAN_PP_REPEAT_3_49(m, d) SEQAN_PP_REPEAT_3_48(m, d) m(4, 48, d) +# define SEQAN_PP_REPEAT_3_50(m, d) SEQAN_PP_REPEAT_3_49(m, d) m(4, 49, d) +# define SEQAN_PP_REPEAT_3_51(m, d) SEQAN_PP_REPEAT_3_50(m, d) m(4, 50, d) +# define SEQAN_PP_REPEAT_3_52(m, d) SEQAN_PP_REPEAT_3_51(m, d) m(4, 51, d) +# define SEQAN_PP_REPEAT_3_53(m, d) SEQAN_PP_REPEAT_3_52(m, d) m(4, 52, d) +# define SEQAN_PP_REPEAT_3_54(m, d) SEQAN_PP_REPEAT_3_53(m, d) m(4, 53, d) +# define SEQAN_PP_REPEAT_3_55(m, d) SEQAN_PP_REPEAT_3_54(m, d) m(4, 54, d) +# define SEQAN_PP_REPEAT_3_56(m, d) SEQAN_PP_REPEAT_3_55(m, d) m(4, 55, d) +# define SEQAN_PP_REPEAT_3_57(m, d) SEQAN_PP_REPEAT_3_56(m, d) m(4, 56, d) +# define SEQAN_PP_REPEAT_3_58(m, d) SEQAN_PP_REPEAT_3_57(m, d) m(4, 57, d) +# define SEQAN_PP_REPEAT_3_59(m, d) SEQAN_PP_REPEAT_3_58(m, d) m(4, 58, d) +# define SEQAN_PP_REPEAT_3_60(m, d) SEQAN_PP_REPEAT_3_59(m, d) m(4, 59, d) +# define SEQAN_PP_REPEAT_3_61(m, d) SEQAN_PP_REPEAT_3_60(m, d) m(4, 60, d) +# define SEQAN_PP_REPEAT_3_62(m, d) SEQAN_PP_REPEAT_3_61(m, d) m(4, 61, d) +# define SEQAN_PP_REPEAT_3_63(m, d) SEQAN_PP_REPEAT_3_62(m, d) m(4, 62, d) +# define SEQAN_PP_REPEAT_3_64(m, d) SEQAN_PP_REPEAT_3_63(m, d) m(4, 63, d) +# define SEQAN_PP_REPEAT_3_65(m, d) SEQAN_PP_REPEAT_3_64(m, d) m(4, 64, d) +# define SEQAN_PP_REPEAT_3_66(m, d) SEQAN_PP_REPEAT_3_65(m, d) m(4, 65, d) +# define SEQAN_PP_REPEAT_3_67(m, d) SEQAN_PP_REPEAT_3_66(m, d) m(4, 66, d) +# define SEQAN_PP_REPEAT_3_68(m, d) SEQAN_PP_REPEAT_3_67(m, d) m(4, 67, d) +# define SEQAN_PP_REPEAT_3_69(m, d) SEQAN_PP_REPEAT_3_68(m, d) m(4, 68, d) +# define SEQAN_PP_REPEAT_3_70(m, d) SEQAN_PP_REPEAT_3_69(m, d) m(4, 69, d) +# define SEQAN_PP_REPEAT_3_71(m, d) SEQAN_PP_REPEAT_3_70(m, d) m(4, 70, d) +# define SEQAN_PP_REPEAT_3_72(m, d) SEQAN_PP_REPEAT_3_71(m, d) m(4, 71, d) +# define SEQAN_PP_REPEAT_3_73(m, d) SEQAN_PP_REPEAT_3_72(m, d) m(4, 72, d) +# define SEQAN_PP_REPEAT_3_74(m, d) SEQAN_PP_REPEAT_3_73(m, d) m(4, 73, d) +# define SEQAN_PP_REPEAT_3_75(m, d) SEQAN_PP_REPEAT_3_74(m, d) m(4, 74, d) +# define SEQAN_PP_REPEAT_3_76(m, d) SEQAN_PP_REPEAT_3_75(m, d) m(4, 75, d) +# define SEQAN_PP_REPEAT_3_77(m, d) SEQAN_PP_REPEAT_3_76(m, d) m(4, 76, d) +# define SEQAN_PP_REPEAT_3_78(m, d) SEQAN_PP_REPEAT_3_77(m, d) m(4, 77, d) +# define SEQAN_PP_REPEAT_3_79(m, d) SEQAN_PP_REPEAT_3_78(m, d) m(4, 78, d) +# define SEQAN_PP_REPEAT_3_80(m, d) SEQAN_PP_REPEAT_3_79(m, d) m(4, 79, d) +# define SEQAN_PP_REPEAT_3_81(m, d) SEQAN_PP_REPEAT_3_80(m, d) m(4, 80, d) +# define SEQAN_PP_REPEAT_3_82(m, d) SEQAN_PP_REPEAT_3_81(m, d) m(4, 81, d) +# define SEQAN_PP_REPEAT_3_83(m, d) SEQAN_PP_REPEAT_3_82(m, d) m(4, 82, d) +# define SEQAN_PP_REPEAT_3_84(m, d) SEQAN_PP_REPEAT_3_83(m, d) m(4, 83, d) +# define SEQAN_PP_REPEAT_3_85(m, d) SEQAN_PP_REPEAT_3_84(m, d) m(4, 84, d) +# define SEQAN_PP_REPEAT_3_86(m, d) SEQAN_PP_REPEAT_3_85(m, d) m(4, 85, d) +# define SEQAN_PP_REPEAT_3_87(m, d) SEQAN_PP_REPEAT_3_86(m, d) m(4, 86, d) +# define SEQAN_PP_REPEAT_3_88(m, d) SEQAN_PP_REPEAT_3_87(m, d) m(4, 87, d) +# define SEQAN_PP_REPEAT_3_89(m, d) SEQAN_PP_REPEAT_3_88(m, d) m(4, 88, d) +# define SEQAN_PP_REPEAT_3_90(m, d) SEQAN_PP_REPEAT_3_89(m, d) m(4, 89, d) +# define SEQAN_PP_REPEAT_3_91(m, d) SEQAN_PP_REPEAT_3_90(m, d) m(4, 90, d) +# define SEQAN_PP_REPEAT_3_92(m, d) SEQAN_PP_REPEAT_3_91(m, d) m(4, 91, d) +# define SEQAN_PP_REPEAT_3_93(m, d) SEQAN_PP_REPEAT_3_92(m, d) m(4, 92, d) +# define SEQAN_PP_REPEAT_3_94(m, d) SEQAN_PP_REPEAT_3_93(m, d) m(4, 93, d) +# define SEQAN_PP_REPEAT_3_95(m, d) SEQAN_PP_REPEAT_3_94(m, d) m(4, 94, d) +# define SEQAN_PP_REPEAT_3_96(m, d) SEQAN_PP_REPEAT_3_95(m, d) m(4, 95, d) +# define SEQAN_PP_REPEAT_3_97(m, d) SEQAN_PP_REPEAT_3_96(m, d) m(4, 96, d) +# define SEQAN_PP_REPEAT_3_98(m, d) SEQAN_PP_REPEAT_3_97(m, d) m(4, 97, d) +# define SEQAN_PP_REPEAT_3_99(m, d) SEQAN_PP_REPEAT_3_98(m, d) m(4, 98, d) +# define SEQAN_PP_REPEAT_3_100(m, d) SEQAN_PP_REPEAT_3_99(m, d) m(4, 99, d) +# define SEQAN_PP_REPEAT_3_101(m, d) SEQAN_PP_REPEAT_3_100(m, d) m(4, 100, d) +# define SEQAN_PP_REPEAT_3_102(m, d) SEQAN_PP_REPEAT_3_101(m, d) m(4, 101, d) +# define SEQAN_PP_REPEAT_3_103(m, d) SEQAN_PP_REPEAT_3_102(m, d) m(4, 102, d) +# define SEQAN_PP_REPEAT_3_104(m, d) SEQAN_PP_REPEAT_3_103(m, d) m(4, 103, d) +# define SEQAN_PP_REPEAT_3_105(m, d) SEQAN_PP_REPEAT_3_104(m, d) m(4, 104, d) +# define SEQAN_PP_REPEAT_3_106(m, d) SEQAN_PP_REPEAT_3_105(m, d) m(4, 105, d) +# define SEQAN_PP_REPEAT_3_107(m, d) SEQAN_PP_REPEAT_3_106(m, d) m(4, 106, d) +# define SEQAN_PP_REPEAT_3_108(m, d) SEQAN_PP_REPEAT_3_107(m, d) m(4, 107, d) +# define SEQAN_PP_REPEAT_3_109(m, d) SEQAN_PP_REPEAT_3_108(m, d) m(4, 108, d) +# define SEQAN_PP_REPEAT_3_110(m, d) SEQAN_PP_REPEAT_3_109(m, d) m(4, 109, d) +# define SEQAN_PP_REPEAT_3_111(m, d) SEQAN_PP_REPEAT_3_110(m, d) m(4, 110, d) +# define SEQAN_PP_REPEAT_3_112(m, d) SEQAN_PP_REPEAT_3_111(m, d) m(4, 111, d) +# define SEQAN_PP_REPEAT_3_113(m, d) SEQAN_PP_REPEAT_3_112(m, d) m(4, 112, d) +# define SEQAN_PP_REPEAT_3_114(m, d) SEQAN_PP_REPEAT_3_113(m, d) m(4, 113, d) +# define SEQAN_PP_REPEAT_3_115(m, d) SEQAN_PP_REPEAT_3_114(m, d) m(4, 114, d) +# define SEQAN_PP_REPEAT_3_116(m, d) SEQAN_PP_REPEAT_3_115(m, d) m(4, 115, d) +# define SEQAN_PP_REPEAT_3_117(m, d) SEQAN_PP_REPEAT_3_116(m, d) m(4, 116, d) +# define SEQAN_PP_REPEAT_3_118(m, d) SEQAN_PP_REPEAT_3_117(m, d) m(4, 117, d) +# define SEQAN_PP_REPEAT_3_119(m, d) SEQAN_PP_REPEAT_3_118(m, d) m(4, 118, d) +# define SEQAN_PP_REPEAT_3_120(m, d) SEQAN_PP_REPEAT_3_119(m, d) m(4, 119, d) +# define SEQAN_PP_REPEAT_3_121(m, d) SEQAN_PP_REPEAT_3_120(m, d) m(4, 120, d) +# define SEQAN_PP_REPEAT_3_122(m, d) SEQAN_PP_REPEAT_3_121(m, d) m(4, 121, d) +# define SEQAN_PP_REPEAT_3_123(m, d) SEQAN_PP_REPEAT_3_122(m, d) m(4, 122, d) +# define SEQAN_PP_REPEAT_3_124(m, d) SEQAN_PP_REPEAT_3_123(m, d) m(4, 123, d) +# define SEQAN_PP_REPEAT_3_125(m, d) SEQAN_PP_REPEAT_3_124(m, d) m(4, 124, d) +# define SEQAN_PP_REPEAT_3_126(m, d) SEQAN_PP_REPEAT_3_125(m, d) m(4, 125, d) +# define SEQAN_PP_REPEAT_3_127(m, d) SEQAN_PP_REPEAT_3_126(m, d) m(4, 126, d) +# define SEQAN_PP_REPEAT_3_128(m, d) SEQAN_PP_REPEAT_3_127(m, d) m(4, 127, d) +# define SEQAN_PP_REPEAT_3_129(m, d) SEQAN_PP_REPEAT_3_128(m, d) m(4, 128, d) +# define SEQAN_PP_REPEAT_3_130(m, d) SEQAN_PP_REPEAT_3_129(m, d) m(4, 129, d) +# define SEQAN_PP_REPEAT_3_131(m, d) SEQAN_PP_REPEAT_3_130(m, d) m(4, 130, d) +# define SEQAN_PP_REPEAT_3_132(m, d) SEQAN_PP_REPEAT_3_131(m, d) m(4, 131, d) +# define SEQAN_PP_REPEAT_3_133(m, d) SEQAN_PP_REPEAT_3_132(m, d) m(4, 132, d) +# define SEQAN_PP_REPEAT_3_134(m, d) SEQAN_PP_REPEAT_3_133(m, d) m(4, 133, d) +# define SEQAN_PP_REPEAT_3_135(m, d) SEQAN_PP_REPEAT_3_134(m, d) m(4, 134, d) +# define SEQAN_PP_REPEAT_3_136(m, d) SEQAN_PP_REPEAT_3_135(m, d) m(4, 135, d) +# define SEQAN_PP_REPEAT_3_137(m, d) SEQAN_PP_REPEAT_3_136(m, d) m(4, 136, d) +# define SEQAN_PP_REPEAT_3_138(m, d) SEQAN_PP_REPEAT_3_137(m, d) m(4, 137, d) +# define SEQAN_PP_REPEAT_3_139(m, d) SEQAN_PP_REPEAT_3_138(m, d) m(4, 138, d) +# define SEQAN_PP_REPEAT_3_140(m, d) SEQAN_PP_REPEAT_3_139(m, d) m(4, 139, d) +# define SEQAN_PP_REPEAT_3_141(m, d) SEQAN_PP_REPEAT_3_140(m, d) m(4, 140, d) +# define SEQAN_PP_REPEAT_3_142(m, d) SEQAN_PP_REPEAT_3_141(m, d) m(4, 141, d) +# define SEQAN_PP_REPEAT_3_143(m, d) SEQAN_PP_REPEAT_3_142(m, d) m(4, 142, d) +# define SEQAN_PP_REPEAT_3_144(m, d) SEQAN_PP_REPEAT_3_143(m, d) m(4, 143, d) +# define SEQAN_PP_REPEAT_3_145(m, d) SEQAN_PP_REPEAT_3_144(m, d) m(4, 144, d) +# define SEQAN_PP_REPEAT_3_146(m, d) SEQAN_PP_REPEAT_3_145(m, d) m(4, 145, d) +# define SEQAN_PP_REPEAT_3_147(m, d) SEQAN_PP_REPEAT_3_146(m, d) m(4, 146, d) +# define SEQAN_PP_REPEAT_3_148(m, d) SEQAN_PP_REPEAT_3_147(m, d) m(4, 147, d) +# define SEQAN_PP_REPEAT_3_149(m, d) SEQAN_PP_REPEAT_3_148(m, d) m(4, 148, d) +# define SEQAN_PP_REPEAT_3_150(m, d) SEQAN_PP_REPEAT_3_149(m, d) m(4, 149, d) +# define SEQAN_PP_REPEAT_3_151(m, d) SEQAN_PP_REPEAT_3_150(m, d) m(4, 150, d) +# define SEQAN_PP_REPEAT_3_152(m, d) SEQAN_PP_REPEAT_3_151(m, d) m(4, 151, d) +# define SEQAN_PP_REPEAT_3_153(m, d) SEQAN_PP_REPEAT_3_152(m, d) m(4, 152, d) +# define SEQAN_PP_REPEAT_3_154(m, d) SEQAN_PP_REPEAT_3_153(m, d) m(4, 153, d) +# define SEQAN_PP_REPEAT_3_155(m, d) SEQAN_PP_REPEAT_3_154(m, d) m(4, 154, d) +# define SEQAN_PP_REPEAT_3_156(m, d) SEQAN_PP_REPEAT_3_155(m, d) m(4, 155, d) +# define SEQAN_PP_REPEAT_3_157(m, d) SEQAN_PP_REPEAT_3_156(m, d) m(4, 156, d) +# define SEQAN_PP_REPEAT_3_158(m, d) SEQAN_PP_REPEAT_3_157(m, d) m(4, 157, d) +# define SEQAN_PP_REPEAT_3_159(m, d) SEQAN_PP_REPEAT_3_158(m, d) m(4, 158, d) +# define SEQAN_PP_REPEAT_3_160(m, d) SEQAN_PP_REPEAT_3_159(m, d) m(4, 159, d) +# define SEQAN_PP_REPEAT_3_161(m, d) SEQAN_PP_REPEAT_3_160(m, d) m(4, 160, d) +# define SEQAN_PP_REPEAT_3_162(m, d) SEQAN_PP_REPEAT_3_161(m, d) m(4, 161, d) +# define SEQAN_PP_REPEAT_3_163(m, d) SEQAN_PP_REPEAT_3_162(m, d) m(4, 162, d) +# define SEQAN_PP_REPEAT_3_164(m, d) SEQAN_PP_REPEAT_3_163(m, d) m(4, 163, d) +# define SEQAN_PP_REPEAT_3_165(m, d) SEQAN_PP_REPEAT_3_164(m, d) m(4, 164, d) +# define SEQAN_PP_REPEAT_3_166(m, d) SEQAN_PP_REPEAT_3_165(m, d) m(4, 165, d) +# define SEQAN_PP_REPEAT_3_167(m, d) SEQAN_PP_REPEAT_3_166(m, d) m(4, 166, d) +# define SEQAN_PP_REPEAT_3_168(m, d) SEQAN_PP_REPEAT_3_167(m, d) m(4, 167, d) +# define SEQAN_PP_REPEAT_3_169(m, d) SEQAN_PP_REPEAT_3_168(m, d) m(4, 168, d) +# define SEQAN_PP_REPEAT_3_170(m, d) SEQAN_PP_REPEAT_3_169(m, d) m(4, 169, d) +# define SEQAN_PP_REPEAT_3_171(m, d) SEQAN_PP_REPEAT_3_170(m, d) m(4, 170, d) +# define SEQAN_PP_REPEAT_3_172(m, d) SEQAN_PP_REPEAT_3_171(m, d) m(4, 171, d) +# define SEQAN_PP_REPEAT_3_173(m, d) SEQAN_PP_REPEAT_3_172(m, d) m(4, 172, d) +# define SEQAN_PP_REPEAT_3_174(m, d) SEQAN_PP_REPEAT_3_173(m, d) m(4, 173, d) +# define SEQAN_PP_REPEAT_3_175(m, d) SEQAN_PP_REPEAT_3_174(m, d) m(4, 174, d) +# define SEQAN_PP_REPEAT_3_176(m, d) SEQAN_PP_REPEAT_3_175(m, d) m(4, 175, d) +# define SEQAN_PP_REPEAT_3_177(m, d) SEQAN_PP_REPEAT_3_176(m, d) m(4, 176, d) +# define SEQAN_PP_REPEAT_3_178(m, d) SEQAN_PP_REPEAT_3_177(m, d) m(4, 177, d) +# define SEQAN_PP_REPEAT_3_179(m, d) SEQAN_PP_REPEAT_3_178(m, d) m(4, 178, d) +# define SEQAN_PP_REPEAT_3_180(m, d) SEQAN_PP_REPEAT_3_179(m, d) m(4, 179, d) +# define SEQAN_PP_REPEAT_3_181(m, d) SEQAN_PP_REPEAT_3_180(m, d) m(4, 180, d) +# define SEQAN_PP_REPEAT_3_182(m, d) SEQAN_PP_REPEAT_3_181(m, d) m(4, 181, d) +# define SEQAN_PP_REPEAT_3_183(m, d) SEQAN_PP_REPEAT_3_182(m, d) m(4, 182, d) +# define SEQAN_PP_REPEAT_3_184(m, d) SEQAN_PP_REPEAT_3_183(m, d) m(4, 183, d) +# define SEQAN_PP_REPEAT_3_185(m, d) SEQAN_PP_REPEAT_3_184(m, d) m(4, 184, d) +# define SEQAN_PP_REPEAT_3_186(m, d) SEQAN_PP_REPEAT_3_185(m, d) m(4, 185, d) +# define SEQAN_PP_REPEAT_3_187(m, d) SEQAN_PP_REPEAT_3_186(m, d) m(4, 186, d) +# define SEQAN_PP_REPEAT_3_188(m, d) SEQAN_PP_REPEAT_3_187(m, d) m(4, 187, d) +# define SEQAN_PP_REPEAT_3_189(m, d) SEQAN_PP_REPEAT_3_188(m, d) m(4, 188, d) +# define SEQAN_PP_REPEAT_3_190(m, d) SEQAN_PP_REPEAT_3_189(m, d) m(4, 189, d) +# define SEQAN_PP_REPEAT_3_191(m, d) SEQAN_PP_REPEAT_3_190(m, d) m(4, 190, d) +# define SEQAN_PP_REPEAT_3_192(m, d) SEQAN_PP_REPEAT_3_191(m, d) m(4, 191, d) +# define SEQAN_PP_REPEAT_3_193(m, d) SEQAN_PP_REPEAT_3_192(m, d) m(4, 192, d) +# define SEQAN_PP_REPEAT_3_194(m, d) SEQAN_PP_REPEAT_3_193(m, d) m(4, 193, d) +# define SEQAN_PP_REPEAT_3_195(m, d) SEQAN_PP_REPEAT_3_194(m, d) m(4, 194, d) +# define SEQAN_PP_REPEAT_3_196(m, d) SEQAN_PP_REPEAT_3_195(m, d) m(4, 195, d) +# define SEQAN_PP_REPEAT_3_197(m, d) SEQAN_PP_REPEAT_3_196(m, d) m(4, 196, d) +# define SEQAN_PP_REPEAT_3_198(m, d) SEQAN_PP_REPEAT_3_197(m, d) m(4, 197, d) +# define SEQAN_PP_REPEAT_3_199(m, d) SEQAN_PP_REPEAT_3_198(m, d) m(4, 198, d) +# define SEQAN_PP_REPEAT_3_200(m, d) SEQAN_PP_REPEAT_3_199(m, d) m(4, 199, d) +# define SEQAN_PP_REPEAT_3_201(m, d) SEQAN_PP_REPEAT_3_200(m, d) m(4, 200, d) +# define SEQAN_PP_REPEAT_3_202(m, d) SEQAN_PP_REPEAT_3_201(m, d) m(4, 201, d) +# define SEQAN_PP_REPEAT_3_203(m, d) SEQAN_PP_REPEAT_3_202(m, d) m(4, 202, d) +# define SEQAN_PP_REPEAT_3_204(m, d) SEQAN_PP_REPEAT_3_203(m, d) m(4, 203, d) +# define SEQAN_PP_REPEAT_3_205(m, d) SEQAN_PP_REPEAT_3_204(m, d) m(4, 204, d) +# define SEQAN_PP_REPEAT_3_206(m, d) SEQAN_PP_REPEAT_3_205(m, d) m(4, 205, d) +# define SEQAN_PP_REPEAT_3_207(m, d) SEQAN_PP_REPEAT_3_206(m, d) m(4, 206, d) +# define SEQAN_PP_REPEAT_3_208(m, d) SEQAN_PP_REPEAT_3_207(m, d) m(4, 207, d) +# define SEQAN_PP_REPEAT_3_209(m, d) SEQAN_PP_REPEAT_3_208(m, d) m(4, 208, d) +# define SEQAN_PP_REPEAT_3_210(m, d) SEQAN_PP_REPEAT_3_209(m, d) m(4, 209, d) +# define SEQAN_PP_REPEAT_3_211(m, d) SEQAN_PP_REPEAT_3_210(m, d) m(4, 210, d) +# define SEQAN_PP_REPEAT_3_212(m, d) SEQAN_PP_REPEAT_3_211(m, d) m(4, 211, d) +# define SEQAN_PP_REPEAT_3_213(m, d) SEQAN_PP_REPEAT_3_212(m, d) m(4, 212, d) +# define SEQAN_PP_REPEAT_3_214(m, d) SEQAN_PP_REPEAT_3_213(m, d) m(4, 213, d) +# define SEQAN_PP_REPEAT_3_215(m, d) SEQAN_PP_REPEAT_3_214(m, d) m(4, 214, d) +# define SEQAN_PP_REPEAT_3_216(m, d) SEQAN_PP_REPEAT_3_215(m, d) m(4, 215, d) +# define SEQAN_PP_REPEAT_3_217(m, d) SEQAN_PP_REPEAT_3_216(m, d) m(4, 216, d) +# define SEQAN_PP_REPEAT_3_218(m, d) SEQAN_PP_REPEAT_3_217(m, d) m(4, 217, d) +# define SEQAN_PP_REPEAT_3_219(m, d) SEQAN_PP_REPEAT_3_218(m, d) m(4, 218, d) +# define SEQAN_PP_REPEAT_3_220(m, d) SEQAN_PP_REPEAT_3_219(m, d) m(4, 219, d) +# define SEQAN_PP_REPEAT_3_221(m, d) SEQAN_PP_REPEAT_3_220(m, d) m(4, 220, d) +# define SEQAN_PP_REPEAT_3_222(m, d) SEQAN_PP_REPEAT_3_221(m, d) m(4, 221, d) +# define SEQAN_PP_REPEAT_3_223(m, d) SEQAN_PP_REPEAT_3_222(m, d) m(4, 222, d) +# define SEQAN_PP_REPEAT_3_224(m, d) SEQAN_PP_REPEAT_3_223(m, d) m(4, 223, d) +# define SEQAN_PP_REPEAT_3_225(m, d) SEQAN_PP_REPEAT_3_224(m, d) m(4, 224, d) +# define SEQAN_PP_REPEAT_3_226(m, d) SEQAN_PP_REPEAT_3_225(m, d) m(4, 225, d) +# define SEQAN_PP_REPEAT_3_227(m, d) SEQAN_PP_REPEAT_3_226(m, d) m(4, 226, d) +# define SEQAN_PP_REPEAT_3_228(m, d) SEQAN_PP_REPEAT_3_227(m, d) m(4, 227, d) +# define SEQAN_PP_REPEAT_3_229(m, d) SEQAN_PP_REPEAT_3_228(m, d) m(4, 228, d) +# define SEQAN_PP_REPEAT_3_230(m, d) SEQAN_PP_REPEAT_3_229(m, d) m(4, 229, d) +# define SEQAN_PP_REPEAT_3_231(m, d) SEQAN_PP_REPEAT_3_230(m, d) m(4, 230, d) +# define SEQAN_PP_REPEAT_3_232(m, d) SEQAN_PP_REPEAT_3_231(m, d) m(4, 231, d) +# define SEQAN_PP_REPEAT_3_233(m, d) SEQAN_PP_REPEAT_3_232(m, d) m(4, 232, d) +# define SEQAN_PP_REPEAT_3_234(m, d) SEQAN_PP_REPEAT_3_233(m, d) m(4, 233, d) +# define SEQAN_PP_REPEAT_3_235(m, d) SEQAN_PP_REPEAT_3_234(m, d) m(4, 234, d) +# define SEQAN_PP_REPEAT_3_236(m, d) SEQAN_PP_REPEAT_3_235(m, d) m(4, 235, d) +# define SEQAN_PP_REPEAT_3_237(m, d) SEQAN_PP_REPEAT_3_236(m, d) m(4, 236, d) +# define SEQAN_PP_REPEAT_3_238(m, d) SEQAN_PP_REPEAT_3_237(m, d) m(4, 237, d) +# define SEQAN_PP_REPEAT_3_239(m, d) SEQAN_PP_REPEAT_3_238(m, d) m(4, 238, d) +# define SEQAN_PP_REPEAT_3_240(m, d) SEQAN_PP_REPEAT_3_239(m, d) m(4, 239, d) +# define SEQAN_PP_REPEAT_3_241(m, d) SEQAN_PP_REPEAT_3_240(m, d) m(4, 240, d) +# define SEQAN_PP_REPEAT_3_242(m, d) SEQAN_PP_REPEAT_3_241(m, d) m(4, 241, d) +# define SEQAN_PP_REPEAT_3_243(m, d) SEQAN_PP_REPEAT_3_242(m, d) m(4, 242, d) +# define SEQAN_PP_REPEAT_3_244(m, d) SEQAN_PP_REPEAT_3_243(m, d) m(4, 243, d) +# define SEQAN_PP_REPEAT_3_245(m, d) SEQAN_PP_REPEAT_3_244(m, d) m(4, 244, d) +# define SEQAN_PP_REPEAT_3_246(m, d) SEQAN_PP_REPEAT_3_245(m, d) m(4, 245, d) +# define SEQAN_PP_REPEAT_3_247(m, d) SEQAN_PP_REPEAT_3_246(m, d) m(4, 246, d) +# define SEQAN_PP_REPEAT_3_248(m, d) SEQAN_PP_REPEAT_3_247(m, d) m(4, 247, d) +# define SEQAN_PP_REPEAT_3_249(m, d) SEQAN_PP_REPEAT_3_248(m, d) m(4, 248, d) +# define SEQAN_PP_REPEAT_3_250(m, d) SEQAN_PP_REPEAT_3_249(m, d) m(4, 249, d) +# define SEQAN_PP_REPEAT_3_251(m, d) SEQAN_PP_REPEAT_3_250(m, d) m(4, 250, d) +# define SEQAN_PP_REPEAT_3_252(m, d) SEQAN_PP_REPEAT_3_251(m, d) m(4, 251, d) +# define SEQAN_PP_REPEAT_3_253(m, d) SEQAN_PP_REPEAT_3_252(m, d) m(4, 252, d) +# define SEQAN_PP_REPEAT_3_254(m, d) SEQAN_PP_REPEAT_3_253(m, d) m(4, 253, d) +# define SEQAN_PP_REPEAT_3_255(m, d) SEQAN_PP_REPEAT_3_254(m, d) m(4, 254, d) +# define SEQAN_PP_REPEAT_3_256(m, d) SEQAN_PP_REPEAT_3_255(m, d) m(4, 255, d) +# +//# endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/repetition/for.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_REPETITION_FOR_HPP +// # define SEQAN_PREPROCESSOR_REPETITION_FOR_HPP +# +// # include +// # include +// # include +# +# /* SEQAN_PP_FOR */ +# +// # if 0 +// # define SEQAN_PP_FOR(state, pred, op, macro) +// # endif +# +# define SEQAN_PP_FOR SEQAN_PP_CAT(SEQAN_PP_FOR_, SEQAN_PP_AUTO_REC(SEQAN_PP_FOR_P, 256)) +# +# define SEQAN_PP_FOR_P(n) SEQAN_PP_CAT(SEQAN_PP_FOR_CHECK_, SEQAN_PP_FOR_ ## n(1, SEQAN_PP_FOR_SR_P, SEQAN_PP_FOR_SR_O, SEQAN_PP_FOR_SR_M)) +# +# define SEQAN_PP_FOR_SR_P(r, s) s +# define SEQAN_PP_FOR_SR_O(r, s) 0 +# define SEQAN_PP_FOR_SR_M(r, s) SEQAN_PP_NIL +# +// # if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() +// # include +// # elif SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MSVC() +// # include +// # elif SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_DMC() +// # include +// # else +// # include +// # endif +# +# define SEQAN_PP_FOR_257(s, p, o, m) SEQAN_PP_ERROR(0x0002) +# +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_NIL 1 +# +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_1(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_2(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_3(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_4(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_5(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_6(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_7(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_8(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_9(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_10(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_11(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_12(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_13(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_14(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_15(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_16(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_17(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_18(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_19(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_20(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_21(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_22(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_23(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_24(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_25(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_26(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_27(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_28(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_29(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_30(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_31(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_32(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_33(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_34(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_35(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_36(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_37(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_38(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_39(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_40(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_41(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_42(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_43(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_44(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_45(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_46(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_47(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_48(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_49(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_50(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_51(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_52(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_53(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_54(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_55(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_56(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_57(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_58(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_59(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_60(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_61(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_62(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_63(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_64(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_65(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_66(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_67(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_68(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_69(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_70(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_71(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_72(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_73(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_74(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_75(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_76(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_77(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_78(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_79(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_80(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_81(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_82(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_83(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_84(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_85(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_86(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_87(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_88(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_89(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_90(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_91(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_92(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_93(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_94(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_95(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_96(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_97(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_98(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_99(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_100(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_101(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_102(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_103(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_104(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_105(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_106(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_107(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_108(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_109(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_110(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_111(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_112(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_113(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_114(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_115(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_116(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_117(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_118(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_119(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_120(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_121(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_122(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_123(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_124(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_125(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_126(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_127(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_128(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_129(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_130(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_131(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_132(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_133(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_134(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_135(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_136(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_137(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_138(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_139(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_140(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_141(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_142(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_143(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_144(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_145(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_146(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_147(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_148(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_149(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_150(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_151(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_152(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_153(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_154(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_155(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_156(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_157(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_158(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_159(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_160(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_161(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_162(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_163(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_164(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_165(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_166(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_167(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_168(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_169(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_170(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_171(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_172(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_173(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_174(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_175(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_176(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_177(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_178(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_179(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_180(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_181(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_182(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_183(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_184(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_185(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_186(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_187(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_188(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_189(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_190(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_191(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_192(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_193(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_194(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_195(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_196(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_197(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_198(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_199(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_200(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_201(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_202(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_203(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_204(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_205(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_206(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_207(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_208(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_209(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_210(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_211(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_212(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_213(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_214(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_215(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_216(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_217(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_218(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_219(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_220(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_221(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_222(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_223(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_224(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_225(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_226(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_227(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_228(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_229(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_230(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_231(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_232(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_233(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_234(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_235(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_236(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_237(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_238(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_239(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_240(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_241(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_242(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_243(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_244(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_245(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_246(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_247(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_248(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_249(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_250(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_251(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_252(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_253(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_254(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_255(s, p, o, m) 0 +# define SEQAN_PP_FOR_CHECK_SEQAN_PP_FOR_256(s, p, o, m) 0 + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/facilities/empty.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_FACILITIES_EMPTY_HPP +// # define SEQAN_PREPROCESSOR_FACILITIES_EMPTY_HPP +# +# /* SEQAN_PP_EMPTY */ +# +# define SEQAN_PP_EMPTY() +# +// # endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/seq/elem.hpp <== +// -------------------------------------------------------------------------- + +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_SEQ_ELEM_HPP +// # define SEQAN_PREPROCESSOR_SEQ_ELEM_HPP +# +// # include +// # include +// # include +# +# /* SEQAN_PP_SEQ_ELEM */ +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_SEQ_ELEM(i, seq) SEQAN_PP_SEQ_ELEM_I(i, seq) +// # else +// # define SEQAN_PP_SEQ_ELEM(i, seq) SEQAN_PP_SEQ_ELEM_I((i, seq)) +// # endif +# +// # if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MSVC() +#ifdef STDLIB_VS +# define SEQAN_PP_SEQ_ELEM_I(i, seq) SEQAN_PP_SEQ_ELEM_II((SEQAN_PP_SEQ_ELEM_ ## i seq)) +# define SEQAN_PP_SEQ_ELEM_II(res) SEQAN_PP_SEQ_ELEM_IV(SEQAN_PP_SEQ_ELEM_III res) +# define SEQAN_PP_SEQ_ELEM_III(x, _) x SEQAN_PP_EMPTY() +# define SEQAN_PP_SEQ_ELEM_IV(x) x +// # elif SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +// # define SEQAN_PP_SEQ_ELEM_I(par) SEQAN_PP_SEQ_ELEM_II ## par +// # define SEQAN_PP_SEQ_ELEM_II(i, seq) SEQAN_PP_SEQ_ELEM_III(SEQAN_PP_SEQ_ELEM_ ## i ## seq) +// # define SEQAN_PP_SEQ_ELEM_III(im) SEQAN_PP_SEQ_ELEM_IV(im) +// # define SEQAN_PP_SEQ_ELEM_IV(x, _) x +# else // #ifdef STDLIB_VS +// # if defined(__IBMC__) || defined(__IBMCPP__) +// # define SEQAN_PP_SEQ_ELEM_I(i, seq) SEQAN_PP_SEQ_ELEM_II(SEQAN_PP_CAT(SEQAN_PP_SEQ_ELEM_ ## i, seq)) +// # else +# define SEQAN_PP_SEQ_ELEM_I(i, seq) SEQAN_PP_SEQ_ELEM_II(SEQAN_PP_SEQ_ELEM_ ## i seq) +// # endif +# define SEQAN_PP_SEQ_ELEM_II(im) SEQAN_PP_SEQ_ELEM_III(im) +# define SEQAN_PP_SEQ_ELEM_III(x, _) x +# endif // #ifdef STDLIB_VS +# +# define SEQAN_PP_SEQ_ELEM_0(x) x, SEQAN_PP_NIL +# define SEQAN_PP_SEQ_ELEM_1(_) SEQAN_PP_SEQ_ELEM_0 +# define SEQAN_PP_SEQ_ELEM_2(_) SEQAN_PP_SEQ_ELEM_1 +# define SEQAN_PP_SEQ_ELEM_3(_) SEQAN_PP_SEQ_ELEM_2 +# define SEQAN_PP_SEQ_ELEM_4(_) SEQAN_PP_SEQ_ELEM_3 +# define SEQAN_PP_SEQ_ELEM_5(_) SEQAN_PP_SEQ_ELEM_4 +# define SEQAN_PP_SEQ_ELEM_6(_) SEQAN_PP_SEQ_ELEM_5 +# define SEQAN_PP_SEQ_ELEM_7(_) SEQAN_PP_SEQ_ELEM_6 +# define SEQAN_PP_SEQ_ELEM_8(_) SEQAN_PP_SEQ_ELEM_7 +# define SEQAN_PP_SEQ_ELEM_9(_) SEQAN_PP_SEQ_ELEM_8 +# define SEQAN_PP_SEQ_ELEM_10(_) SEQAN_PP_SEQ_ELEM_9 +# define SEQAN_PP_SEQ_ELEM_11(_) SEQAN_PP_SEQ_ELEM_10 +# define SEQAN_PP_SEQ_ELEM_12(_) SEQAN_PP_SEQ_ELEM_11 +# define SEQAN_PP_SEQ_ELEM_13(_) SEQAN_PP_SEQ_ELEM_12 +# define SEQAN_PP_SEQ_ELEM_14(_) SEQAN_PP_SEQ_ELEM_13 +# define SEQAN_PP_SEQ_ELEM_15(_) SEQAN_PP_SEQ_ELEM_14 +# define SEQAN_PP_SEQ_ELEM_16(_) SEQAN_PP_SEQ_ELEM_15 +# define SEQAN_PP_SEQ_ELEM_17(_) SEQAN_PP_SEQ_ELEM_16 +# define SEQAN_PP_SEQ_ELEM_18(_) SEQAN_PP_SEQ_ELEM_17 +# define SEQAN_PP_SEQ_ELEM_19(_) SEQAN_PP_SEQ_ELEM_18 +# define SEQAN_PP_SEQ_ELEM_20(_) SEQAN_PP_SEQ_ELEM_19 +# define SEQAN_PP_SEQ_ELEM_21(_) SEQAN_PP_SEQ_ELEM_20 +# define SEQAN_PP_SEQ_ELEM_22(_) SEQAN_PP_SEQ_ELEM_21 +# define SEQAN_PP_SEQ_ELEM_23(_) SEQAN_PP_SEQ_ELEM_22 +# define SEQAN_PP_SEQ_ELEM_24(_) SEQAN_PP_SEQ_ELEM_23 +# define SEQAN_PP_SEQ_ELEM_25(_) SEQAN_PP_SEQ_ELEM_24 +# define SEQAN_PP_SEQ_ELEM_26(_) SEQAN_PP_SEQ_ELEM_25 +# define SEQAN_PP_SEQ_ELEM_27(_) SEQAN_PP_SEQ_ELEM_26 +# define SEQAN_PP_SEQ_ELEM_28(_) SEQAN_PP_SEQ_ELEM_27 +# define SEQAN_PP_SEQ_ELEM_29(_) SEQAN_PP_SEQ_ELEM_28 +# define SEQAN_PP_SEQ_ELEM_30(_) SEQAN_PP_SEQ_ELEM_29 +# define SEQAN_PP_SEQ_ELEM_31(_) SEQAN_PP_SEQ_ELEM_30 +# define SEQAN_PP_SEQ_ELEM_32(_) SEQAN_PP_SEQ_ELEM_31 +# define SEQAN_PP_SEQ_ELEM_33(_) SEQAN_PP_SEQ_ELEM_32 +# define SEQAN_PP_SEQ_ELEM_34(_) SEQAN_PP_SEQ_ELEM_33 +# define SEQAN_PP_SEQ_ELEM_35(_) SEQAN_PP_SEQ_ELEM_34 +# define SEQAN_PP_SEQ_ELEM_36(_) SEQAN_PP_SEQ_ELEM_35 +# define SEQAN_PP_SEQ_ELEM_37(_) SEQAN_PP_SEQ_ELEM_36 +# define SEQAN_PP_SEQ_ELEM_38(_) SEQAN_PP_SEQ_ELEM_37 +# define SEQAN_PP_SEQ_ELEM_39(_) SEQAN_PP_SEQ_ELEM_38 +# define SEQAN_PP_SEQ_ELEM_40(_) SEQAN_PP_SEQ_ELEM_39 +# define SEQAN_PP_SEQ_ELEM_41(_) SEQAN_PP_SEQ_ELEM_40 +# define SEQAN_PP_SEQ_ELEM_42(_) SEQAN_PP_SEQ_ELEM_41 +# define SEQAN_PP_SEQ_ELEM_43(_) SEQAN_PP_SEQ_ELEM_42 +# define SEQAN_PP_SEQ_ELEM_44(_) SEQAN_PP_SEQ_ELEM_43 +# define SEQAN_PP_SEQ_ELEM_45(_) SEQAN_PP_SEQ_ELEM_44 +# define SEQAN_PP_SEQ_ELEM_46(_) SEQAN_PP_SEQ_ELEM_45 +# define SEQAN_PP_SEQ_ELEM_47(_) SEQAN_PP_SEQ_ELEM_46 +# define SEQAN_PP_SEQ_ELEM_48(_) SEQAN_PP_SEQ_ELEM_47 +# define SEQAN_PP_SEQ_ELEM_49(_) SEQAN_PP_SEQ_ELEM_48 +# define SEQAN_PP_SEQ_ELEM_50(_) SEQAN_PP_SEQ_ELEM_49 +# define SEQAN_PP_SEQ_ELEM_51(_) SEQAN_PP_SEQ_ELEM_50 +# define SEQAN_PP_SEQ_ELEM_52(_) SEQAN_PP_SEQ_ELEM_51 +# define SEQAN_PP_SEQ_ELEM_53(_) SEQAN_PP_SEQ_ELEM_52 + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/seq/seq.hpp <== +// -------------------------------------------------------------------------- + +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_SEQ_SEQ_HPP +// # define SEQAN_PREPROCESSOR_SEQ_SEQ_HPP +# +// # include +// # include +# +# /* SEQAN_PP_SEQ_HEAD */ +# +# define SEQAN_PP_SEQ_HEAD(seq) SEQAN_PP_SEQ_ELEM(0, seq) +# +# /* SEQAN_PP_SEQ_TAIL */ +# +// # if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +// # define SEQAN_PP_SEQ_TAIL(seq) SEQAN_PP_SEQ_TAIL_1((seq)) +// # define SEQAN_PP_SEQ_TAIL_1(par) SEQAN_PP_SEQ_TAIL_2 ## par +// # define SEQAN_PP_SEQ_TAIL_2(seq) SEQAN_PP_SEQ_TAIL_I ## seq +// # elif SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MSVC() +#ifdef STDLIB_VS +# define SEQAN_PP_SEQ_TAIL(seq) SEQAN_PP_SEQ_TAIL_ID(SEQAN_PP_SEQ_TAIL_I seq) +# define SEQAN_PP_SEQ_TAIL_ID(id) id +// # elif SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() +// # define SEQAN_PP_SEQ_TAIL(seq) SEQAN_PP_SEQ_TAIL_D(seq) +// # define SEQAN_PP_SEQ_TAIL_D(seq) SEQAN_PP_SEQ_TAIL_I seq +# else // #ifdef STDLIB_VS +# define SEQAN_PP_SEQ_TAIL(seq) SEQAN_PP_SEQ_TAIL_I seq +# endif // #ifdef STDLIB_VS +# +# define SEQAN_PP_SEQ_TAIL_I(x) +# +# /* SEQAN_PP_SEQ_NIL */ +# +# define SEQAN_PP_SEQ_NIL(x) (x) +# +// # endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/arithmetic/inc.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +//# ifndef SEQAN_PREPROCESSOR_ARITHMETIC_INC_HPP +//# define SEQAN_PREPROCESSOR_ARITHMETIC_INC_HPP +# +//# include +# +# /* SEQAN_PP_INC */ +# +//# if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_INC(x) SEQAN_PP_INC_I(x) +//# else +//# define SEQAN_PP_INC(x) SEQAN_PP_INC_OO((x)) +//# define SEQAN_PP_INC_OO(par) SEQAN_PP_INC_I ## par +//# endif +# +# define SEQAN_PP_INC_I(x) SEQAN_PP_INC_ ## x +# +# define SEQAN_PP_INC_0 1 +# define SEQAN_PP_INC_1 2 +# define SEQAN_PP_INC_2 3 +# define SEQAN_PP_INC_3 4 +# define SEQAN_PP_INC_4 5 +# define SEQAN_PP_INC_5 6 +# define SEQAN_PP_INC_6 7 +# define SEQAN_PP_INC_7 8 +# define SEQAN_PP_INC_8 9 +# define SEQAN_PP_INC_9 10 +# define SEQAN_PP_INC_10 11 +# define SEQAN_PP_INC_11 12 +# define SEQAN_PP_INC_12 13 +# define SEQAN_PP_INC_13 14 +# define SEQAN_PP_INC_14 15 +# define SEQAN_PP_INC_15 16 +# define SEQAN_PP_INC_16 17 +# define SEQAN_PP_INC_17 18 +# define SEQAN_PP_INC_18 19 +# define SEQAN_PP_INC_19 20 +# define SEQAN_PP_INC_20 21 +# define SEQAN_PP_INC_21 22 +# define SEQAN_PP_INC_22 23 +# define SEQAN_PP_INC_23 24 +# define SEQAN_PP_INC_24 25 +# define SEQAN_PP_INC_25 26 +# define SEQAN_PP_INC_26 27 +# define SEQAN_PP_INC_27 28 +# define SEQAN_PP_INC_28 29 +# define SEQAN_PP_INC_29 30 +# define SEQAN_PP_INC_30 31 +# define SEQAN_PP_INC_31 32 +# define SEQAN_PP_INC_32 33 +# define SEQAN_PP_INC_33 34 +# define SEQAN_PP_INC_34 35 +# define SEQAN_PP_INC_35 36 +# define SEQAN_PP_INC_36 37 +# define SEQAN_PP_INC_37 38 +# define SEQAN_PP_INC_38 39 +# define SEQAN_PP_INC_39 40 +# define SEQAN_PP_INC_40 41 +# define SEQAN_PP_INC_41 42 +# define SEQAN_PP_INC_42 43 +# define SEQAN_PP_INC_43 44 +# define SEQAN_PP_INC_44 45 +# define SEQAN_PP_INC_45 46 +# define SEQAN_PP_INC_46 47 +# define SEQAN_PP_INC_47 48 +# define SEQAN_PP_INC_48 49 +# define SEQAN_PP_INC_49 50 +# define SEQAN_PP_INC_50 51 +# define SEQAN_PP_INC_51 52 +# define SEQAN_PP_INC_52 53 +# define SEQAN_PP_INC_53 54 +# define SEQAN_PP_INC_54 55 +# define SEQAN_PP_INC_55 56 +# define SEQAN_PP_INC_56 57 +# define SEQAN_PP_INC_57 58 +# define SEQAN_PP_INC_58 59 +# define SEQAN_PP_INC_59 60 +# define SEQAN_PP_INC_60 61 +# define SEQAN_PP_INC_61 62 +# define SEQAN_PP_INC_62 63 +# define SEQAN_PP_INC_63 64 +# define SEQAN_PP_INC_64 65 +# define SEQAN_PP_INC_65 66 +# define SEQAN_PP_INC_66 67 +# define SEQAN_PP_INC_67 68 +# define SEQAN_PP_INC_68 69 +# define SEQAN_PP_INC_69 70 +# define SEQAN_PP_INC_70 71 +# define SEQAN_PP_INC_71 72 +# define SEQAN_PP_INC_72 73 +# define SEQAN_PP_INC_73 74 +# define SEQAN_PP_INC_74 75 +# define SEQAN_PP_INC_75 76 +# define SEQAN_PP_INC_76 77 +# define SEQAN_PP_INC_77 78 +# define SEQAN_PP_INC_78 79 +# define SEQAN_PP_INC_79 80 +# define SEQAN_PP_INC_80 81 +# define SEQAN_PP_INC_81 82 +# define SEQAN_PP_INC_82 83 +# define SEQAN_PP_INC_83 84 +# define SEQAN_PP_INC_84 85 +# define SEQAN_PP_INC_85 86 +# define SEQAN_PP_INC_86 87 +# define SEQAN_PP_INC_87 88 +# define SEQAN_PP_INC_88 89 +# define SEQAN_PP_INC_89 90 +# define SEQAN_PP_INC_90 91 +# define SEQAN_PP_INC_91 92 +# define SEQAN_PP_INC_92 93 +# define SEQAN_PP_INC_93 94 +# define SEQAN_PP_INC_94 95 +# define SEQAN_PP_INC_95 96 +# define SEQAN_PP_INC_96 97 +# define SEQAN_PP_INC_97 98 +# define SEQAN_PP_INC_98 99 +# define SEQAN_PP_INC_99 100 +# define SEQAN_PP_INC_100 101 +# define SEQAN_PP_INC_101 102 +# define SEQAN_PP_INC_102 103 +# define SEQAN_PP_INC_103 104 +# define SEQAN_PP_INC_104 105 +# define SEQAN_PP_INC_105 106 +# define SEQAN_PP_INC_106 107 +# define SEQAN_PP_INC_107 108 +# define SEQAN_PP_INC_108 109 +# define SEQAN_PP_INC_109 110 +# define SEQAN_PP_INC_110 111 +# define SEQAN_PP_INC_111 112 +# define SEQAN_PP_INC_112 113 +# define SEQAN_PP_INC_113 114 +# define SEQAN_PP_INC_114 115 +# define SEQAN_PP_INC_115 116 +# define SEQAN_PP_INC_116 117 +# define SEQAN_PP_INC_117 118 +# define SEQAN_PP_INC_118 119 +# define SEQAN_PP_INC_119 120 +# define SEQAN_PP_INC_120 121 +# define SEQAN_PP_INC_121 122 +# define SEQAN_PP_INC_122 123 +# define SEQAN_PP_INC_123 124 +# define SEQAN_PP_INC_124 125 +# define SEQAN_PP_INC_125 126 +# define SEQAN_PP_INC_126 127 +# define SEQAN_PP_INC_127 128 +# define SEQAN_PP_INC_128 129 +# define SEQAN_PP_INC_129 130 +# define SEQAN_PP_INC_130 131 +# define SEQAN_PP_INC_131 132 +# define SEQAN_PP_INC_132 133 +# define SEQAN_PP_INC_133 134 +# define SEQAN_PP_INC_134 135 +# define SEQAN_PP_INC_135 136 +# define SEQAN_PP_INC_136 137 +# define SEQAN_PP_INC_137 138 +# define SEQAN_PP_INC_138 139 +# define SEQAN_PP_INC_139 140 +# define SEQAN_PP_INC_140 141 +# define SEQAN_PP_INC_141 142 +# define SEQAN_PP_INC_142 143 +# define SEQAN_PP_INC_143 144 +# define SEQAN_PP_INC_144 145 +# define SEQAN_PP_INC_145 146 +# define SEQAN_PP_INC_146 147 +# define SEQAN_PP_INC_147 148 +# define SEQAN_PP_INC_148 149 +# define SEQAN_PP_INC_149 150 +# define SEQAN_PP_INC_150 151 +# define SEQAN_PP_INC_151 152 +# define SEQAN_PP_INC_152 153 +# define SEQAN_PP_INC_153 154 +# define SEQAN_PP_INC_154 155 +# define SEQAN_PP_INC_155 156 +# define SEQAN_PP_INC_156 157 +# define SEQAN_PP_INC_157 158 +# define SEQAN_PP_INC_158 159 +# define SEQAN_PP_INC_159 160 +# define SEQAN_PP_INC_160 161 +# define SEQAN_PP_INC_161 162 +# define SEQAN_PP_INC_162 163 +# define SEQAN_PP_INC_163 164 +# define SEQAN_PP_INC_164 165 +# define SEQAN_PP_INC_165 166 +# define SEQAN_PP_INC_166 167 +# define SEQAN_PP_INC_167 168 +# define SEQAN_PP_INC_168 169 +# define SEQAN_PP_INC_169 170 +# define SEQAN_PP_INC_170 171 +# define SEQAN_PP_INC_171 172 +# define SEQAN_PP_INC_172 173 +# define SEQAN_PP_INC_173 174 +# define SEQAN_PP_INC_174 175 +# define SEQAN_PP_INC_175 176 +# define SEQAN_PP_INC_176 177 +# define SEQAN_PP_INC_177 178 +# define SEQAN_PP_INC_178 179 +# define SEQAN_PP_INC_179 180 +# define SEQAN_PP_INC_180 181 +# define SEQAN_PP_INC_181 182 +# define SEQAN_PP_INC_182 183 +# define SEQAN_PP_INC_183 184 +# define SEQAN_PP_INC_184 185 +# define SEQAN_PP_INC_185 186 +# define SEQAN_PP_INC_186 187 +# define SEQAN_PP_INC_187 188 +# define SEQAN_PP_INC_188 189 +# define SEQAN_PP_INC_189 190 +# define SEQAN_PP_INC_190 191 +# define SEQAN_PP_INC_191 192 +# define SEQAN_PP_INC_192 193 +# define SEQAN_PP_INC_193 194 +# define SEQAN_PP_INC_194 195 +# define SEQAN_PP_INC_195 196 +# define SEQAN_PP_INC_196 197 +# define SEQAN_PP_INC_197 198 +# define SEQAN_PP_INC_198 199 +# define SEQAN_PP_INC_199 200 +# define SEQAN_PP_INC_200 201 +# define SEQAN_PP_INC_201 202 +# define SEQAN_PP_INC_202 203 +# define SEQAN_PP_INC_203 204 +# define SEQAN_PP_INC_204 205 +# define SEQAN_PP_INC_205 206 +# define SEQAN_PP_INC_206 207 +# define SEQAN_PP_INC_207 208 +# define SEQAN_PP_INC_208 209 +# define SEQAN_PP_INC_209 210 +# define SEQAN_PP_INC_210 211 +# define SEQAN_PP_INC_211 212 +# define SEQAN_PP_INC_212 213 +# define SEQAN_PP_INC_213 214 +# define SEQAN_PP_INC_214 215 +# define SEQAN_PP_INC_215 216 +# define SEQAN_PP_INC_216 217 +# define SEQAN_PP_INC_217 218 +# define SEQAN_PP_INC_218 219 +# define SEQAN_PP_INC_219 220 +# define SEQAN_PP_INC_220 221 +# define SEQAN_PP_INC_221 222 +# define SEQAN_PP_INC_222 223 +# define SEQAN_PP_INC_223 224 +# define SEQAN_PP_INC_224 225 +# define SEQAN_PP_INC_225 226 +# define SEQAN_PP_INC_226 227 +# define SEQAN_PP_INC_227 228 +# define SEQAN_PP_INC_228 229 +# define SEQAN_PP_INC_229 230 +# define SEQAN_PP_INC_230 231 +# define SEQAN_PP_INC_231 232 +# define SEQAN_PP_INC_232 233 +# define SEQAN_PP_INC_233 234 +# define SEQAN_PP_INC_234 235 +# define SEQAN_PP_INC_235 236 +# define SEQAN_PP_INC_236 237 +# define SEQAN_PP_INC_237 238 +# define SEQAN_PP_INC_238 239 +# define SEQAN_PP_INC_239 240 +# define SEQAN_PP_INC_240 241 +# define SEQAN_PP_INC_241 242 +# define SEQAN_PP_INC_242 243 +# define SEQAN_PP_INC_243 244 +# define SEQAN_PP_INC_244 245 +# define SEQAN_PP_INC_245 246 +# define SEQAN_PP_INC_246 247 +# define SEQAN_PP_INC_247 248 +# define SEQAN_PP_INC_248 249 +# define SEQAN_PP_INC_249 250 +# define SEQAN_PP_INC_250 251 +# define SEQAN_PP_INC_251 252 +# define SEQAN_PP_INC_252 253 +# define SEQAN_PP_INC_253 254 +# define SEQAN_PP_INC_254 255 +# define SEQAN_PP_INC_255 256 +# define SEQAN_PP_INC_256 256 +# +//# endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/arithmetic/dec.hpp <== +// -------------------------------------------------------------------------- + +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_ARITHMETIC_DEC_HPP +// # define SEQAN_PREPROCESSOR_ARITHMETIC_DEC_HPP +# +// # include +# +# /* SEQAN_PP_DEC */ +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_MWCC() +# define SEQAN_PP_DEC(x) SEQAN_PP_DEC_I(x) +// # else +// # define SEQAN_PP_DEC(x) SEQAN_PP_DEC_OO((x)) +// # define SEQAN_PP_DEC_OO(par) SEQAN_PP_DEC_I ## par +// # endif +# +# define SEQAN_PP_DEC_I(x) SEQAN_PP_DEC_ ## x +# +# define SEQAN_PP_DEC_0 0 +# define SEQAN_PP_DEC_1 0 +# define SEQAN_PP_DEC_2 1 +# define SEQAN_PP_DEC_3 2 +# define SEQAN_PP_DEC_4 3 +# define SEQAN_PP_DEC_5 4 +# define SEQAN_PP_DEC_6 5 +# define SEQAN_PP_DEC_7 6 +# define SEQAN_PP_DEC_8 7 +# define SEQAN_PP_DEC_9 8 +# define SEQAN_PP_DEC_10 9 +# define SEQAN_PP_DEC_11 10 +# define SEQAN_PP_DEC_12 11 +# define SEQAN_PP_DEC_13 12 +# define SEQAN_PP_DEC_14 13 +# define SEQAN_PP_DEC_15 14 +# define SEQAN_PP_DEC_16 15 +# define SEQAN_PP_DEC_17 16 +# define SEQAN_PP_DEC_18 17 +# define SEQAN_PP_DEC_19 18 +# define SEQAN_PP_DEC_20 19 +# define SEQAN_PP_DEC_21 20 +# define SEQAN_PP_DEC_22 21 +# define SEQAN_PP_DEC_23 22 +# define SEQAN_PP_DEC_24 23 +# define SEQAN_PP_DEC_25 24 +# define SEQAN_PP_DEC_26 25 +# define SEQAN_PP_DEC_27 26 +# define SEQAN_PP_DEC_28 27 +# define SEQAN_PP_DEC_29 28 +# define SEQAN_PP_DEC_30 29 +# define SEQAN_PP_DEC_31 30 +# define SEQAN_PP_DEC_32 31 +# define SEQAN_PP_DEC_33 32 +# define SEQAN_PP_DEC_34 33 +# define SEQAN_PP_DEC_35 34 +# define SEQAN_PP_DEC_36 35 +# define SEQAN_PP_DEC_37 36 +# define SEQAN_PP_DEC_38 37 +# define SEQAN_PP_DEC_39 38 +# define SEQAN_PP_DEC_40 39 +# define SEQAN_PP_DEC_41 40 +# define SEQAN_PP_DEC_42 41 +# define SEQAN_PP_DEC_43 42 +# define SEQAN_PP_DEC_44 43 +# define SEQAN_PP_DEC_45 44 +# define SEQAN_PP_DEC_46 45 +# define SEQAN_PP_DEC_47 46 +# define SEQAN_PP_DEC_48 47 +# define SEQAN_PP_DEC_49 48 +# define SEQAN_PP_DEC_50 49 +# define SEQAN_PP_DEC_51 50 +# define SEQAN_PP_DEC_52 51 +# define SEQAN_PP_DEC_53 52 +# define SEQAN_PP_DEC_54 53 +# define SEQAN_PP_DEC_55 54 +# define SEQAN_PP_DEC_56 55 +# define SEQAN_PP_DEC_57 56 +# define SEQAN_PP_DEC_58 57 +# define SEQAN_PP_DEC_59 58 +# define SEQAN_PP_DEC_60 59 +# define SEQAN_PP_DEC_61 60 +# define SEQAN_PP_DEC_62 61 +# define SEQAN_PP_DEC_63 62 +# define SEQAN_PP_DEC_64 63 +# define SEQAN_PP_DEC_65 64 +# define SEQAN_PP_DEC_66 65 +# define SEQAN_PP_DEC_67 66 +# define SEQAN_PP_DEC_68 67 +# define SEQAN_PP_DEC_69 68 +# define SEQAN_PP_DEC_70 69 +# define SEQAN_PP_DEC_71 70 +# define SEQAN_PP_DEC_72 71 +# define SEQAN_PP_DEC_73 72 +# define SEQAN_PP_DEC_74 73 +# define SEQAN_PP_DEC_75 74 +# define SEQAN_PP_DEC_76 75 +# define SEQAN_PP_DEC_77 76 +# define SEQAN_PP_DEC_78 77 +# define SEQAN_PP_DEC_79 78 +# define SEQAN_PP_DEC_80 79 +# define SEQAN_PP_DEC_81 80 +# define SEQAN_PP_DEC_82 81 +# define SEQAN_PP_DEC_83 82 +# define SEQAN_PP_DEC_84 83 +# define SEQAN_PP_DEC_85 84 +# define SEQAN_PP_DEC_86 85 +# define SEQAN_PP_DEC_87 86 +# define SEQAN_PP_DEC_88 87 +# define SEQAN_PP_DEC_89 88 +# define SEQAN_PP_DEC_90 89 +# define SEQAN_PP_DEC_91 90 +# define SEQAN_PP_DEC_92 91 +# define SEQAN_PP_DEC_93 92 +# define SEQAN_PP_DEC_94 93 +# define SEQAN_PP_DEC_95 94 +# define SEQAN_PP_DEC_96 95 +# define SEQAN_PP_DEC_97 96 +# define SEQAN_PP_DEC_98 97 +# define SEQAN_PP_DEC_99 98 +# define SEQAN_PP_DEC_100 99 +# define SEQAN_PP_DEC_101 100 +# define SEQAN_PP_DEC_102 101 +# define SEQAN_PP_DEC_103 102 +# define SEQAN_PP_DEC_104 103 +# define SEQAN_PP_DEC_105 104 +# define SEQAN_PP_DEC_106 105 +# define SEQAN_PP_DEC_107 106 +# define SEQAN_PP_DEC_108 107 +# define SEQAN_PP_DEC_109 108 +# define SEQAN_PP_DEC_110 109 +# define SEQAN_PP_DEC_111 110 +# define SEQAN_PP_DEC_112 111 +# define SEQAN_PP_DEC_113 112 +# define SEQAN_PP_DEC_114 113 +# define SEQAN_PP_DEC_115 114 +# define SEQAN_PP_DEC_116 115 +# define SEQAN_PP_DEC_117 116 +# define SEQAN_PP_DEC_118 117 +# define SEQAN_PP_DEC_119 118 +# define SEQAN_PP_DEC_120 119 +# define SEQAN_PP_DEC_121 120 +# define SEQAN_PP_DEC_122 121 +# define SEQAN_PP_DEC_123 122 +# define SEQAN_PP_DEC_124 123 +# define SEQAN_PP_DEC_125 124 +# define SEQAN_PP_DEC_126 125 +# define SEQAN_PP_DEC_127 126 +# define SEQAN_PP_DEC_128 127 +# define SEQAN_PP_DEC_129 128 +# define SEQAN_PP_DEC_130 129 +# define SEQAN_PP_DEC_131 130 +# define SEQAN_PP_DEC_132 131 +# define SEQAN_PP_DEC_133 132 +# define SEQAN_PP_DEC_134 133 +# define SEQAN_PP_DEC_135 134 +# define SEQAN_PP_DEC_136 135 +# define SEQAN_PP_DEC_137 136 +# define SEQAN_PP_DEC_138 137 +# define SEQAN_PP_DEC_139 138 +# define SEQAN_PP_DEC_140 139 +# define SEQAN_PP_DEC_141 140 +# define SEQAN_PP_DEC_142 141 +# define SEQAN_PP_DEC_143 142 +# define SEQAN_PP_DEC_144 143 +# define SEQAN_PP_DEC_145 144 +# define SEQAN_PP_DEC_146 145 +# define SEQAN_PP_DEC_147 146 +# define SEQAN_PP_DEC_148 147 +# define SEQAN_PP_DEC_149 148 +# define SEQAN_PP_DEC_150 149 +# define SEQAN_PP_DEC_151 150 +# define SEQAN_PP_DEC_152 151 +# define SEQAN_PP_DEC_153 152 +# define SEQAN_PP_DEC_154 153 +# define SEQAN_PP_DEC_155 154 +# define SEQAN_PP_DEC_156 155 +# define SEQAN_PP_DEC_157 156 +# define SEQAN_PP_DEC_158 157 +# define SEQAN_PP_DEC_159 158 +# define SEQAN_PP_DEC_160 159 +# define SEQAN_PP_DEC_161 160 +# define SEQAN_PP_DEC_162 161 +# define SEQAN_PP_DEC_163 162 +# define SEQAN_PP_DEC_164 163 +# define SEQAN_PP_DEC_165 164 +# define SEQAN_PP_DEC_166 165 +# define SEQAN_PP_DEC_167 166 +# define SEQAN_PP_DEC_168 167 +# define SEQAN_PP_DEC_169 168 +# define SEQAN_PP_DEC_170 169 +# define SEQAN_PP_DEC_171 170 +# define SEQAN_PP_DEC_172 171 +# define SEQAN_PP_DEC_173 172 +# define SEQAN_PP_DEC_174 173 +# define SEQAN_PP_DEC_175 174 +# define SEQAN_PP_DEC_176 175 +# define SEQAN_PP_DEC_177 176 +# define SEQAN_PP_DEC_178 177 +# define SEQAN_PP_DEC_179 178 +# define SEQAN_PP_DEC_180 179 +# define SEQAN_PP_DEC_181 180 +# define SEQAN_PP_DEC_182 181 +# define SEQAN_PP_DEC_183 182 +# define SEQAN_PP_DEC_184 183 +# define SEQAN_PP_DEC_185 184 +# define SEQAN_PP_DEC_186 185 +# define SEQAN_PP_DEC_187 186 +# define SEQAN_PP_DEC_188 187 +# define SEQAN_PP_DEC_189 188 +# define SEQAN_PP_DEC_190 189 +# define SEQAN_PP_DEC_191 190 +# define SEQAN_PP_DEC_192 191 +# define SEQAN_PP_DEC_193 192 +# define SEQAN_PP_DEC_194 193 +# define SEQAN_PP_DEC_195 194 +# define SEQAN_PP_DEC_196 195 +# define SEQAN_PP_DEC_197 196 +# define SEQAN_PP_DEC_198 197 +# define SEQAN_PP_DEC_199 198 +# define SEQAN_PP_DEC_200 199 +# define SEQAN_PP_DEC_201 200 +# define SEQAN_PP_DEC_202 201 +# define SEQAN_PP_DEC_203 202 +# define SEQAN_PP_DEC_204 203 +# define SEQAN_PP_DEC_205 204 +# define SEQAN_PP_DEC_206 205 +# define SEQAN_PP_DEC_207 206 +# define SEQAN_PP_DEC_208 207 +# define SEQAN_PP_DEC_209 208 +# define SEQAN_PP_DEC_210 209 +# define SEQAN_PP_DEC_211 210 +# define SEQAN_PP_DEC_212 211 +# define SEQAN_PP_DEC_213 212 +# define SEQAN_PP_DEC_214 213 +# define SEQAN_PP_DEC_215 214 +# define SEQAN_PP_DEC_216 215 +# define SEQAN_PP_DEC_217 216 +# define SEQAN_PP_DEC_218 217 +# define SEQAN_PP_DEC_219 218 +# define SEQAN_PP_DEC_220 219 +# define SEQAN_PP_DEC_221 220 +# define SEQAN_PP_DEC_222 221 +# define SEQAN_PP_DEC_223 222 +# define SEQAN_PP_DEC_224 223 +# define SEQAN_PP_DEC_225 224 +# define SEQAN_PP_DEC_226 225 +# define SEQAN_PP_DEC_227 226 +# define SEQAN_PP_DEC_228 227 +# define SEQAN_PP_DEC_229 228 +# define SEQAN_PP_DEC_230 229 +# define SEQAN_PP_DEC_231 230 +# define SEQAN_PP_DEC_232 231 +# define SEQAN_PP_DEC_233 232 +# define SEQAN_PP_DEC_234 233 +# define SEQAN_PP_DEC_235 234 +# define SEQAN_PP_DEC_236 235 +# define SEQAN_PP_DEC_237 236 +# define SEQAN_PP_DEC_238 237 +# define SEQAN_PP_DEC_239 238 +# define SEQAN_PP_DEC_240 239 +# define SEQAN_PP_DEC_241 240 +# define SEQAN_PP_DEC_242 241 +# define SEQAN_PP_DEC_243 242 +# define SEQAN_PP_DEC_244 243 +# define SEQAN_PP_DEC_245 244 +# define SEQAN_PP_DEC_246 245 +# define SEQAN_PP_DEC_247 246 +# define SEQAN_PP_DEC_248 247 +# define SEQAN_PP_DEC_249 248 +# define SEQAN_PP_DEC_250 249 +# define SEQAN_PP_DEC_251 250 +# define SEQAN_PP_DEC_252 251 +# define SEQAN_PP_DEC_253 252 +# define SEQAN_PP_DEC_254 253 +# define SEQAN_PP_DEC_255 254 +# define SEQAN_PP_DEC_256 255 + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/seq/for_each.hpp <== +// -------------------------------------------------------------------------- + +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +// # ifndef SEQAN_PREPROCESSOR_SEQ_FOR_EACH_HPP +// # define SEQAN_PREPROCESSOR_SEQ_FOR_EACH_HPP +# +// # include +// # include +// # include +// # include +// # include +// # include +// # include +# +# /* SEQAN_PP_SEQ_FOR_EACH */ +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() +# define SEQAN_PP_SEQ_FOR_EACH(macro, data, seq) SEQAN_PP_FOR((macro, data, seq (nil)), SEQAN_PP_SEQ_FOR_EACH_P, SEQAN_PP_SEQ_FOR_EACH_O, SEQAN_PP_SEQ_FOR_EACH_M) +// # else +// # define SEQAN_PP_SEQ_FOR_EACH(macro, data, seq) SEQAN_PP_SEQ_FOR_EACH_D(macro, data, seq) +// # define SEQAN_PP_SEQ_FOR_EACH_D(macro, data, seq) SEQAN_PP_FOR((macro, data, seq (nil)), SEQAN_PP_SEQ_FOR_EACH_P, SEQAN_PP_SEQ_FOR_EACH_O, SEQAN_PP_SEQ_FOR_EACH_M) +// # endif +# +# define SEQAN_PP_SEQ_FOR_EACH_P(r, x) SEQAN_PP_DEC(SEQAN_PP_SEQ_SIZE(SEQAN_PP_TUPLE_ELEM(3, 2, x))) +# +// # if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_STRICT() +#ifndef STDLIB_VS +# define SEQAN_PP_SEQ_FOR_EACH_O(r, x) SEQAN_PP_SEQ_FOR_EACH_O_I x +# else // #ifndef STDLIB_VS +# define SEQAN_PP_SEQ_FOR_EACH_O(r, x) SEQAN_PP_SEQ_FOR_EACH_O_I(SEQAN_PP_TUPLE_ELEM(3, 0, x), SEQAN_PP_TUPLE_ELEM(3, 1, x), SEQAN_PP_TUPLE_ELEM(3, 2, x)) +# endif // #ifndef STDLIB_VS +# +# define SEQAN_PP_SEQ_FOR_EACH_O_I(macro, data, seq) (macro, data, SEQAN_PP_SEQ_TAIL(seq)) +# +// # if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_STRICT() +#ifndef STDLIB_VS +# define SEQAN_PP_SEQ_FOR_EACH_M(r, x) SEQAN_PP_SEQ_FOR_EACH_M_IM(r, SEQAN_PP_TUPLE_REM_3 x) +# define SEQAN_PP_SEQ_FOR_EACH_M_IM(r, im) SEQAN_PP_SEQ_FOR_EACH_M_I(r, im) +# else // #ifndef STDLIB_VS +# define SEQAN_PP_SEQ_FOR_EACH_M(r, x) SEQAN_PP_SEQ_FOR_EACH_M_I(r, SEQAN_PP_TUPLE_ELEM(3, 0, x), SEQAN_PP_TUPLE_ELEM(3, 1, x), SEQAN_PP_TUPLE_ELEM(3, 2, x)) +# endif // #ifndef STDLIB_VS +# +# define SEQAN_PP_SEQ_FOR_EACH_M_I(r, macro, data, seq) macro(r, data, SEQAN_PP_SEQ_HEAD(seq)) +# +# /* SEQAN_PP_SEQ_FOR_EACH_R */ +# +// # if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() +# define SEQAN_PP_SEQ_FOR_EACH_R(r, macro, data, seq) SEQAN_PP_FOR_ ## r((macro, data, seq (nil)), SEQAN_PP_SEQ_FOR_EACH_P, SEQAN_PP_SEQ_FOR_EACH_O, SEQAN_PP_SEQ_FOR_EACH_M) +// # else +// # define SEQAN_PP_SEQ_FOR_EACH_R(r, macro, data, seq) SEQAN_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq) +// # define SEQAN_PP_SEQ_FOR_EACH_R_I(r, macro, data, seq) SEQAN_PP_FOR_ ## r((macro, data, seq (nil)), SEQAN_PP_SEQ_FOR_EACH_P, SEQAN_PP_SEQ_FOR_EACH_O, SEQAN_PP_SEQ_FOR_EACH_M) +// # endif +# +// # endif + +// -------------------------------------------------------------------------- +// ==> boost/preprocessor/seq/for_each_i.hpp <== +// -------------------------------------------------------------------------- + +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * Distributed under the Boost Software License, Version 1.0. (See +# * accompanying file LICENSE_1_0.txt or copy at +# * http://www.boost.org/LICENSE_1_0.txt) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +//# ifndef SEQAN_PREPROCESSOR_SEQ_FOR_EACH_I_HPP +//# define SEQAN_PREPROCESSOR_SEQ_FOR_EACH_I_HPP +# +//# include +//# include +//# include +//# include +//# include +//# include +//# include +//# include +# +# /* SEQAN_PP_SEQ_FOR_EACH_I */ +# +//# if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() +# define SEQAN_PP_SEQ_FOR_EACH_I(macro, data, seq) SEQAN_PP_FOR((macro, data, seq (nil), 0), SEQAN_PP_SEQ_FOR_EACH_I_P, SEQAN_PP_SEQ_FOR_EACH_I_O, SEQAN_PP_SEQ_FOR_EACH_I_M) +//# else +//# define SEQAN_PP_SEQ_FOR_EACH_I(macro, data, seq) SEQAN_PP_SEQ_FOR_EACH_I_I(macro, data, seq) +//# define SEQAN_PP_SEQ_FOR_EACH_I_I(macro, data, seq) SEQAN_PP_FOR((macro, data, seq (nil), 0), SEQAN_PP_SEQ_FOR_EACH_I_P, SEQAN_PP_SEQ_FOR_EACH_I_O, SEQAN_PP_SEQ_FOR_EACH_I_M) +//# endif +# +# define SEQAN_PP_SEQ_FOR_EACH_I_P(r, x) SEQAN_PP_DEC(SEQAN_PP_SEQ_SIZE(SEQAN_PP_TUPLE_ELEM(4, 2, x))) +# +//# if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_STRICT() +# define SEQAN_PP_SEQ_FOR_EACH_I_O(r, x) SEQAN_PP_SEQ_FOR_EACH_I_O_I x +//# else +//# define SEQAN_PP_SEQ_FOR_EACH_I_O(r, x) SEQAN_PP_SEQ_FOR_EACH_I_O_I(SEQAN_PP_TUPLE_ELEM(4, 0, x), SEQAN_PP_TUPLE_ELEM(4, 1, x), SEQAN_PP_TUPLE_ELEM(4, 2, x), SEQAN_PP_TUPLE_ELEM(4, 3, x)) +//# endif +# +# define SEQAN_PP_SEQ_FOR_EACH_I_O_I(macro, data, seq, i) (macro, data, SEQAN_PP_SEQ_TAIL(seq), SEQAN_PP_INC(i)) +# +//# if SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_STRICT() +//# define SEQAN_PP_SEQ_FOR_EACH_I_M(r, x) SEQAN_PP_SEQ_FOR_EACH_I_M_IM(r, SEQAN_PP_TUPLE_REM_4 x) +//# define SEQAN_PP_SEQ_FOR_EACH_I_M_IM(r, im) SEQAN_PP_SEQ_FOR_EACH_I_M_I(r, im) +//# else +# define SEQAN_PP_SEQ_FOR_EACH_I_M(r, x) SEQAN_PP_SEQ_FOR_EACH_I_M_I(r, SEQAN_PP_TUPLE_ELEM(4, 0, x), SEQAN_PP_TUPLE_ELEM(4, 1, x), SEQAN_PP_TUPLE_ELEM(4, 2, x), SEQAN_PP_TUPLE_ELEM(4, 3, x)) +//# endif +# +# define SEQAN_PP_SEQ_FOR_EACH_I_M_I(r, macro, data, seq, i) macro(r, data, i, SEQAN_PP_SEQ_HEAD(seq)) +# +# /* SEQAN_PP_SEQ_FOR_EACH_I_R */ +# +//# if ~SEQAN_PP_CONFIG_FLAGS() & SEQAN_PP_CONFIG_EDG() +# define SEQAN_PP_SEQ_FOR_EACH_I_R(r, macro, data, seq) SEQAN_PP_FOR_ ## r((macro, data, seq (nil), 0), SEQAN_PP_SEQ_FOR_EACH_I_P, SEQAN_PP_SEQ_FOR_EACH_I_O, SEQAN_PP_SEQ_FOR_EACH_I_M) +//# else +//# define SEQAN_PP_SEQ_FOR_EACH_I_R(r, macro, data, seq) SEQAN_PP_SEQ_FOR_EACH_I_R_I(r, macro, data, seq) +//# define SEQAN_PP_SEQ_FOR_EACH_I_R_I(r, macro, data, seq) SEQAN_PP_FOR_ ## r((macro, data, seq (nil), 0), SEQAN_PP_SEQ_FOR_EACH_I_P, SEQAN_PP_SEQ_FOR_EACH_I_O, SEQAN_PP_SEQ_FOR_EACH_I_M) +//# endif +# +//# endif + +// -------------------------------------------------------------------------- +// ==> boost/config/suffix.hpp <== +// -------------------------------------------------------------------------- + +// Copyright (c) 2001-2003 John Maddock +// Copyright (c) 2001 Darin Adler +// Copyright (c) 2001 Peter Dimov +// Copyright (c) 2002 Bill Kempf +// Copyright (c) 2002 Jens Maurer +// Copyright (c) 2002-2003 David Abrahams +// Copyright (c) 2003 Gennaro Prota +// Copyright (c) 2003 Eric Friedman +// Copyright (c) 2010 Eric Jourdanneau, Joel Falcou +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// +// Helper macro SEQAN_JOIN: +// The following piece of macro magic joins the two +// arguments together, even when one of the arguments is +// itself a macro (see 16.3.1 in C++ standard). The key +// is that macro expansion of macro arguments does not +// occur in SEQAN_DO_JOIN2 but does in SEQAN_DO_JOIN. +// +#define SEQAN_JOIN( X, Y ) SEQAN_DO_JOIN( X, Y ) +#define SEQAN_DO_JOIN( X, Y ) SEQAN_DO_JOIN2(X,Y) +#define SEQAN_DO_JOIN2( X, Y ) X##Y + + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_SEQAN_PREPROCESSOR_SUBSET_H_ diff --git a/seqan/basic/builtin_functions.h b/seqan/basic/builtin_functions.h new file mode 100644 index 0000000..a16edfb --- /dev/null +++ b/seqan/basic/builtin_functions.h @@ -0,0 +1,63 @@ +// ========================================================================== +// builtin_functions.h +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: Manuel Holtgrewe +// ========================================================================== +// Documentation for built-in functions. +// +// This is used for documenting that certain global functions and operators +// are overridden for some classes. +// ========================================================================== + +#ifndef SEQAN_INCLUDE_SEQAN_BASIC_BUILTIN_FUNCTIONS_H_ +#define SEQAN_INCLUDE_SEQAN_BASIC_BUILTIN_FUNCTIONS_H_ + +namespace seqan { + +// ============================================================================ +// Forwards +// ============================================================================ + +// ============================================================================ +// Tags, Classes, Enums +// ============================================================================ + +// ============================================================================ +// Metafunctions +// ============================================================================ + +// ============================================================================ +// Functions +// ============================================================================ + +} // namespace seqan + +#endif // #ifndef SEQAN_INCLUDE_SEQAN_BASIC_BUILTIN_FUNCTIONS_H_ diff --git a/seqan/basic/concept_checking.h b/seqan/basic/concept_checking.h new file mode 100644 index 0000000..96dcc8a --- /dev/null +++ b/seqan/basic/concept_checking.h @@ -0,0 +1,731 @@ +// ========================================================================== +// SeqAn - The Library for Sequence Analysis +// ========================================================================== +// Copyright (c) 2006-2016, Knut Reinert, FU Berlin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Knut Reinert or the FU Berlin nor the names of +// its contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. +// +// ========================================================================== +// Author: David Weese +// Author: Manuel Holtgrewe +// ========================================================================== +// A minimal subset of the Boost Concept Checking Library. A lot of the code +// in the BCCL deals with support of non-conforming compilers and we cut this +// away. The code here has been adjusted to work with the compilers supported +// by SeqAn and be as simple as possible while still creating useful compiler +// errors. +// ========================================================================== + +// SEQAN_NO_GENERATED_FORWARDS + +#ifndef INCLUDE_SEQAN_BASIC_CONCEPT_CHECKING_H_ +#define INCLUDE_SEQAN_BASIC_CONCEPT_CHECKING_H_ + +namespace seqan { + +// --------------------------------------------------------------------------- +// ==> boost/static_assert.hpp <== +// --------------------------------------------------------------------------- + +// (C) Copyright John Maddock 2000. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/static_assert for documentation. + +#define SEQAN_STATIC_ASSERT_MSG( B, Msg ) static_assert(B, Msg) + +// +// If the compiler issues warnings about old C style casts, +// then enable this: +// +#define SEQAN_STATIC_ASSERT_BOOL_CAST(x) (bool)(x) + +#define SEQAN_STATIC_ASSERT( B ) static_assert(B, #B) + +// --------------------------------------------------------------------------- +// ==> boost/parameter/aux_/paranthesized_type.hpp <== +// --------------------------------------------------------------------------- + +// Copyright David Abrahams 2006. Distributed under the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +template +struct unaryfunptr_arg_type; + +template +struct unaryfunptr_arg_type +{ + typedef Arg type; +}; + +template <> +struct unaryfunptr_arg_type +{ + typedef void type; +}; + +// --------------------------------------------------------------------------- +// ==> boost/concept_check/general.hpp <== +// --------------------------------------------------------------------------- + +// Copyright David Abrahams 2006. Distributed under the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +namespace concept_checking +{ +template struct instantiate {}; +} + +template struct concept_check_; + +template +void concept_check_failed() +{ + Model *p = static_cast(NULL); + p->~Model(); +} + +template +struct concept_check +{ + concept_checking::instantiate > x; + enum { instantiate = 1 }; +}; + +template +struct concept_check_ + : concept_check +{}; + +# define SEQAN_CONCEPT_ASSERT_FN( ModelFnPtr ) \ + typedef seqan::detail::instantiate< \ + &seqan::requirement_::failed> \ + SEQAN_PP_CAT(seqan_concept_check,__LINE__) SEQAN_UNUSED + +// --------------------------------------------------------------------------- +// ==> boost/concept/assert.hpp <== +// --------------------------------------------------------------------------- + +// Copyright David Abrahams 2006. Distributed under the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +/*! + * @defgroup ConceptChecking Concept Checking + * @brief Macros for the concept checking system in SeqAn. + * + * SeqAn's concept checking system is copied from Boost. The license for the library is as follows: + * + * @code{.cpp} + * // Copyright David Abrahams 2006. Distributed under the Boost Software + * // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + * // http://www.boost.org/LICENSE_1_0.txt). + * @endcode + */ + +/*! + * @macro ConceptChecking#SEQAN_CONCEPT_ASSERT + * @brief Perform a concept check. + * @headerfile + * + * @signature SEQAN_CONCEPT_ASSERT((concept)) + * + * @param concept Concept specialized with a the type that should be checked. + * + * This macro is a compile-time assertion and requires the concept specialized + * with the tested types to compile. The check neither consumes memory nor + * running time. The macro can be used at the beginning of a function or within + * a struct/class definition. The checked concepts should be as restrictive and + * generic as possible to on the one hand cover all used functionality and on + * the other hand not limit the applicability of a function/class. + * + * @section Examples + * + * @code{.cpp} + * typedef typename Value::Type TValue; + * typedef typename Position::Type TPosition; + * typedef typename Difference::Type TDifference; + * + * SEQAN_CONCEPT_ASSERT((AlphabetConcept)); + * SEQAN_CONCEPT_ASSERT((SignedIntegerConcept)); + * SEQAN_CONCEPT_ASSERT((UnsignedIntegerConcept)); + * @endcode + * @see Is + */ + +// Usage, in class or function context: +// SEQAN_CONCEPT_ASSERT((UnaryFunctionConcept)); +# define SEQAN_CONCEPT_ASSERT(ModelInParens) \ + SEQAN_CONCEPT_ASSERT_FN(void(*)ModelInParens) + +// usage.hpp + +template +struct usage_requirements +{ + ~usage_requirements() + { + Model *p = static_cast(NULL); + p->~Model(); + } +}; + +/*! + * @macro ConceptChecking#SEQAN_CONCEPT_USAGE + * @headerfile + * @brief Defines valid expressions. + * + * @signature SEQAN_CONCEPT_USAGE(name) + * + * @param[in] name Identifier of the concept defined with @link ConceptChecking#SEQAN_CONCEPT @endlink or + * @link ConceptChecking#SEQAN_CONCEPT_REFINE @endlink. + * + * This macro should be used to introduce a block (enclosed with curly braces) of valid expressions within a newly + * defined concept. Valid expressions should test for available functions, operators and the correctness of return + * types. Use helper functions, e.g. @link ignoreUnusedVariableWarning @endlink, + * @link ConceptChecking#requireBooleanExpr @endlink and @link ConceptChecking#sameType @endlink. + * + * @section Examples + * + * @code{.cpp} + * SEQAN_CONCEPT(EqualityComparable,(T)) + * { + * SEQAN_CONCEPT_USAGE(EqualityComparable) + * { + * requireBooleanExpr(a == b); + * requireBooleanExpr(a != b); + * } + * private: + * T a, b; + * }; + * @endcode + * + * @see ConceptChecking#requireBooleanExpr + * @see ConceptChecking#SEQAN_CONCEPT + * @see ConceptChecking#SEQAN_CONCEPT_REFINE + */ + +#define SEQAN_CONCEPT_USAGE(model) \ + SEQAN_CONCEPT_ASSERT((seqan::usage_requirements)); \ + ~model() + +// --------------------------------------------------------------------------- +// ==> boost/concept/detail/has_constraints.hpp <== +// --------------------------------------------------------------------------- + +// Copyright David Abrahams 2006. Distributed under the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +namespace detail { + typedef char yes; + typedef char (&no)[2]; + + template + struct wrap_constraints {}; + + template + inline yes has_constraints_(Model*, wrap_constraints* = 0); + inline no has_constraints_(...); +} + +// This would be called "detail::has_constraints," but it has a strong +// tendency to show up in error messages. +template +struct not_satisfied +{ + enum {value = sizeof( detail::has_constraints_((Model*)0) ) == sizeof(detail::yes) }; + typedef typename Eval::Type Type; +}; + +// --------------------------------------------------------------------------- +// ==> boost/concept_check/detail/general.hpp <== +// --------------------------------------------------------------------------- + +// Copyright David Abrahams 2006. Distributed under the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +template +struct requirement_; + +namespace detail +{ + template struct instantiate {}; +} + +template +struct requirement +{ + static void failed() + { + Model *p = static_cast(NULL); + p->~Model(); + } +}; + +struct failed {}; + +template +struct requirement +{ + static void failed() + { + Model *p = static_cast(NULL); + p->~Model(); + } +}; + +template +struct constraint +{ + static void failed() + { + Model *p = static_cast(NULL); + p->constraints(); + } +}; + +template +struct requirement_ + : IfC::Type::VALUE, /* should be called "has_constraints", see above */ + constraint, + requirement + >::Type +{}; + +# define SEQAN_CONCEPT_ASSERT_FN( ModelFnPtr ) \ + typedef seqan::detail::instantiate< \ + &seqan::requirement_::failed> \ + SEQAN_PP_CAT(seqan_concept_check,__LINE__) SEQAN_UNUSED + +// --------------------------------------------------------------------------- +// ==> boost/concept_check/detail/requires.hpp <== +// --------------------------------------------------------------------------- + +// Copyright David Abrahams 2006. Distributed under the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +// Template for use in handwritten assertions +template +struct requires_ : More +{ + SEQAN_CONCEPT_ASSERT((Model)); +}; + +// Template for use by macros, where models must be wrapped in parens. +// This isn't in namespace detail to keep extra cruft out of resulting +// error messages. + +template +struct _requires_ +{ + enum { value = 0 }; + SEQAN_CONCEPT_ASSERT_FN(ModelFn); +}; + +template +struct Requires_ : unaryfunptr_arg_type +{}; + +# define SEQAN_CONCEPT_REQUIRES_(r,data,t) + (seqan::_requires_::value) + +#if defined(NDEBUG) + +# define SEQAN_CONCEPT_REQUIRES(models, result) \ + typename unaryfunptr_arg_type::type + +#else // #if defined(NDEBUG) + +# define SEQAN_CONCEPT_REQUIRES(models, result) \ + typename seqan::Requires_< \ + (0 SEQAN_PP_SEQ_FOR_EACH(SEQAN_CONCEPT_REQUIRES_, ~, models)), \ + void(*)result \ + >::type + +#endif // #if defined(NDEBUG) + +// --------------------------------------------------------------------------- +// ==> boost/concept_check.hpp <== +// --------------------------------------------------------------------------- + +// +// (C) Copyright Jeremy Siek 2000. +// Copyright 2002 The Trustees of Indiana University. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // +// Backward compatibility +// + +template +inline void functionRequires(Model* = 0) +{ + SEQAN_CONCEPT_ASSERT((Model)); +} + +/*! + * @fn ignoreUnusedVariableWarning + * @headerfile + * @brief Removes unused variable warning. + * + * @signature void ignoreUnusedVariableWarning(x); + * + * @param[in] x Variable that causes the unused variable warning. + * + * It sometimes is necessary to define variables which are not further used, e.g. to check available assignment + * operators. Use this functions to remove a compile warning that otherwise would be raised in this case. + */ + +template inline void ignoreUnusedVariableWarning(T const&) {} + +// --------------------------------------------------------------------------- +// ==> boost/concept/detail/concept_def.hpp <== +// --------------------------------------------------------------------------- + +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// SEQAN_CONCEPT_REFINE added by David Weese + +/*! + * @macro ConceptChecking#SEQAN_CONCEPT + * @brief Defines a new concept. + * @headerfile + * + * @signature SEQAN_CONCEPT(name, params) + * + * @param params Template paramter list in parantheses, e.g. (T) or (T1)(T2). + * Typically, template parameters are models, i.e. one or multiple + * classes that should be checked for fulfilling a concept.This is + * a sequence of the Boost Preprocessor Library, read more. + * @param name Concept identifier. Non-trivial concepts should have an + * identifier with a Concept-suffix. + * + * A concept is implemented as a template struct with name name and + * arguments params. The concept checking should be part of the struct + * definition. Associated types should be checked via @link ConceptChecking#SEQAN_CONCEPT_ASSERT + * @endlink and valid expressions in a function @link ConceptChecking#SEQAN_CONCEPT_USAGE + * @endlink, see below. Variables used in valid expressions should be (private) + * struct members instead of local variables in member functions (read more. + * + * @section Examples + * + * @code{.cpp} + * SEQAN_CONCEPT(Assignable,(T)) + * { + * SEQAN_CONCEPT_USAGE(Assignable) + * { + * a = b; // require assignment operator + * constConstraints(b); + * } + * private: + * void constConstraints(const T& x) + * { + * a = x; // const required for argument to assignment + * ignoreUnusedVariableWarning(x); + * } + * private: + * T a; + * T b; + * }; + * + * SEQAN_CONCEPT(EqualityComparable,(T)) + * { + * SEQAN_CONCEPT_USAGE(EqualityComparable) + * { + * requireBooleanExpr(a == b); + * requireBooleanExpr(a != b); + * } + * private: + * T a, b; + * }; + * @endcode + * + * @see ConceptChecking#SEQAN_CONCEPT_USAGE + */ + +# define SEQAN_CONCEPT(name, params) \ + template < SEQAN_PP_SEQ_FOR_EACH_I(SEQAN_CONCEPT_typename,~,params) > \ + struct name + +/*! + * @macro ConceptChecking#SEQAN_CONCEPT_REFINE + * @brief Defines a new concept as a refinement of existing concepts. + * @headerfile + * + * @signature SEQAN_CONCEPT_REFINE(name, params, refinedConcepts) + * + * @param params Template parameter list in parantheses, e.g. (T) or (T1)(T2). + * Typically, template parameters are models, i.e. one or multiple + * classes that should be checked for fulfilling a concept.This is + * a sequence of the Boost Preprocessor Library, read more. + * @param name Concept identifier. Non-trivial concepts should have an + * identifier with a Concept-suffix. + * @param refinedConcepts Identifiers of concepts that are refined by the new + * concept.Refined concepts are implicitly integrated + * into the requirements of the new concept.This is a + * sequence of the Boost Preprocessor Library, read + * more + * + * A concept is implemented as a template struct with name name and + * arguments params. The struct inherits all refined concept structs. + * The concept checking should be part of the struct definition. For more + * information, see @link ConceptChecking#SEQAN_CONCEPT @endlink. + * + * @section Examples + * + * @code{.cpp} + * SEQAN_CONCEPT_REFINE(AlphabetConcept, (TValue), (Assignable)(DefaultConstructible)(CopyConstructible)) + * { + * TValue val, val2; + * + * SEQAN_CONCEPT_USAGE(AlphabetConcept) + * { + * assign(val, val2); + * } + * }; + * @endcode + * @see ConceptChecking#SEQAN_CONCEPT_USAGE + */ + +# define SEQAN_CONCEPT_REFINE(name, params, refinedConcepts) \ + template < SEQAN_PP_SEQ_FOR_EACH_I(SEQAN_CONCEPT_typename,~,params) > \ + struct name; \ + \ + template < SEQAN_PP_SEQ_FOR_EACH_I(SEQAN_CONCEPT_typename,~,params) > \ + struct Refines< name > \ + { \ + typedef \ + SEQAN_PP_SEQ_FOR_EACH_I(SEQAN_CONCEPT_LIST_prefix,params,refinedConcepts) \ + SEQAN_PP_REPEAT(SEQAN_PP_SEQ_SIZE(refinedConcepts),SEQAN_CONCEPT_LIST_suffix,~) Type; \ + }; \ + \ + template < SEQAN_PP_SEQ_FOR_EACH_I(SEQAN_CONCEPT_typename,~,params) > \ + struct name: \ + SEQAN_PP_SEQ_FOR_EACH_I(SEQAN_CONCEPT_REFINE_superclass,params,refinedConcepts) + +/*! + * @macro ConceptChecking#SEQAN_CONCEPT_IMPL + * @brief Defines which concepts a model fulfills. + * @headerfile + * + * + * @signature template<> // required, even if name has no template arguments + * SEQAN_CONCEPT_IMPL((name), implementedConcepts) + * + * template + * SEQAN_CONCEPT_IMPL((name), implementedConcepts) + * + * @param implementedConcepts Identifiers of concepts that are fulfilled by the model. This is a sequence of the + * Boost Preprocessor Library, read more. + * @param name Model type, i.e. an identifier or an identifier with template + * arguments. + * + * The metafunction @link Is @endlink can be used to determine whether a class + * models (fulfills) a concepts. A model of a concept must pass the concept + * check via @link ConceptChecking#SEQAN_CONCEPT_ASSERT @endlink. + * + * @section Examples + * + * @code{.cpp} + * template + * SEQAN_CONCEPT_IMPL((String), (StringConcept)); + * @endcode + */ + + +// STRIP_PARENS macro by Steven Watanabe (http://lists.boost.org/boost-users/2010/08/61429.php) +#define SEQAN_APPLY(macro, args) SEQAN_APPLY_I(macro, args) +#define SEQAN_APPLY_I(macro, args) macro args +#define SEQAN_STRIP_PARENS(x) SEQAN_EVAL((SEQAN_STRIP_PARENS_I x), x) +#define SEQAN_STRIP_PARENS_I(...) 1,1 +#define SEQAN_EVAL(test, x) SEQAN_EVAL_I(test, x) +#define SEQAN_EVAL_I(test, x) SEQAN_MAYBE_STRIP_PARENS(SEQAN_TEST_ARITY test, x) +#define SEQAN_TEST_ARITY(...) SEQAN_APPLY(SEQAN_TEST_ARITY_I, (__VA_ARGS__, 2, 1)) +#define SEQAN_TEST_ARITY_I(a,b,c,...) c +#define SEQAN_MAYBE_STRIP_PARENS(cond, x) SEQAN_MAYBE_STRIP_PARENS_I(cond, x) +#define SEQAN_MAYBE_STRIP_PARENS_I(cond, x) SEQAN_PP_CAT(SEQAN_MAYBE_STRIP_PARENS_, cond)(x) +#define SEQAN_MAYBE_STRIP_PARENS_1(x) x +#define SEQAN_MAYBE_STRIP_PARENS_2(x) SEQAN_APPLY(SEQAN_MAYBE_STRIP_PARENS_2_I, x) +#define SEQAN_MAYBE_STRIP_PARENS_2_I(...) __VA_ARGS__ + +# define SEQAN_CONCEPT_IMPL(model, implementedConcepts) \ + struct Implements \ + { \ + typedef \ + SEQAN_PP_SEQ_FOR_EACH_I(SEQAN_CONCEPT_LIST_prefix,model,implementedConcepts) \ + SEQAN_PP_REPEAT(SEQAN_PP_SEQ_SIZE(implementedConcepts),SEQAN_CONCEPT_LIST_suffix,~) Type; \ + } + +// helper for the SEQAN_CONCEPT, above. +# define SEQAN_CONCEPT_typename(r, ignored, index, t) \ + SEQAN_PP_COMMA_IF(index) typename t + +// helper for the SEQAN_CONCEPT, above. +# define SEQAN_CONCEPT_REFINE_superclass(r, params, index, t) \ + SEQAN_PP_COMMA_IF(index) t +# define SEQAN_CONCEPT_LIST_prefix(r, params, index, t) \ + SEQAN_PP_COMMA_IF(index) TagList +# define SEQAN_CONCEPT_LIST_suffix(z, n, text) > + +// ============================================================================ +// Functions +// ============================================================================ + +/*! + * @fn ConceptChecking#sameType + * @brief Tests for equality of types. + * + * @signature void sameType(x, y); + * + * @param[in] x Object of a certain type. + * @param[in] y Object that must be of the same type. + * + * This function can be used to test for the correctness of function return types or the type of an expression in + * concept tests. + * + * @see ConceptChecking#SEQAN_CONCEPT_USAGE + */ + +template +void sameType(T, T) { } + + +// ============================================================================ +// Metafunctions +// ============================================================================ + +/*! + * @mfn Is + * @brief Returns whether a concept is fulfilled. + * @headerfile + * + * @signature Is::Type + * @signature Is::VALUE + * + * @tparam TConcept A concept that is specialized with type(s) that should be + * tested for fulfilling the concept. + * + * @return Type @link LogicalValuesTags#True @endlink/true if + * TConcept is a fulfilled concept, otherwise @link + * LogicalValuesTags#False @endlink/false. + * + * The @link Is @endlink-metafunction can be used to test types for fulfilling a concept without causing compilation + * errors. If True or true is returned, TConcept must pass the concept test via @link + * ConceptChecking#SEQAN_CONCEPT_ASSERT @endlink. It can be used to switch between different implementations + * depending on the concept of a type, or in combination with @link EnableIfFunctionality#SEQAN_FUNC_ENABLE_IF + * @endlink to make a function only visible to types of certain concepts. + * + * @section Examples + * + * @code{.cpp} + * Is >::Type + * IfC >::VALUE, T1, T2>::Type + * + * std::cout << Is >::VALUE << std::endl; // 1 + * std::cout << Is >::VALUE << std::endl; // 0 + * @endcode + * Define a hierarchy of concepts and two models Alice and Bob + * that implements some of them. @link Is @endlink determines which concepts are + * explicitly or implicitly fulfilled. + * + * @code{.cpp} + * struct Alice {}; + * struct Bob {}; + * + * SEQAN_CONCEPT(ConceptA, (T)) {}; + * SEQAN_CONCEPT(ConceptB, (T)) {}; + * SEQAN_CONCEPT_REFINE(ConceptC, (T), (ConceptA)(ConceptB)) {}; + * SEQAN_CONCEPT_REFINE(ConceptD, (T), (ConceptC)) {}; + * + * template<> // Alice has no template arguments + * SEQAN_CONCEPT_IMPL(Alice, (ConceptA)(ConceptB)); + * + * template<> // Bob has no template arguments + * SEQAN_CONCEPT_IMPL(Bob, (ConceptC)); + * + * std::cout << Is< ConceptA >::VALUE << std::endl; // 1 + * std::cout << Is< ConceptB >::VALUE << std::endl; // 1 + * std::cout << Is< ConceptC >::VALUE << std::endl; // 0 + * std::cout << Is< ConceptD >::VALUE << std::endl; // 0 + * + * std::cout << Is< ConceptA >::VALUE << std::endl; // 1 + * std::cout << Is< ConceptB >::VALUE << std::endl; // 1 + * std::cout << Is< ConceptC >::VALUE << std::endl; // 1 + * std::cout << Is< ConceptD >::VALUE << std::endl; // 0 + * @endcode + * + * @see EnableIfFunctionality#SEQAN_FUNC_ENABLE_IF + * @see ConceptChecking#SEQAN_CONCEPT_ASSERT + */ + +// test whether a concept is fulfilled (without concept checking) +template +struct Implements: False {}; + +template +struct Refines +{ + typedef void Type; +}; + + +template +struct IsRecurse_: False {}; + +template +struct IsRecurse_ >: True {}; + +template +struct IsRecurse_< TConceptModel, TagList >: + Or< + IsRecurse_::Type >, + IsRecurse_ + > {}; + +template +struct Is; + +template