discoSnp/0000755000000000000000000000000012424174530011340 5ustar rootrootdiscoSnp/minia/0000755000000000000000000000000012236717702012442 5ustar rootrootdiscoSnp/minia/Kmer.h0000644000000000000000000000603412316502726013511 0ustar rootroot#ifndef Kmer64_h #define Kmer64_h #include #ifdef _largeint #include "LargeInt.h" typedef LargeInt kmer_type; #else #ifdef _ttmath #include "ttmath/ttmath.h" typedef ttmath::UInt kmer_type; #else #if (! defined kmer_type) || (! defined _LP64) typedef uint64_t kmer_type; #endif #endif #endif extern int sizeKmer; extern kmer_type kmerMask; extern kmer_type kmerMaskm1; extern uint64_t nsolids; int NT2int(char nt); int revcomp_int(int nt_int); kmer_type codeSeed(char *seq, int sizeKmer, kmer_type kmerMask); kmer_type codeSeed(char *seq); kmer_type codeSeedRight(char *seq, kmer_type val_seed, bool new_read); kmer_type codeSeedRight(char *seq, kmer_type val_seed, bool new_read, int sizeKmer, kmer_type kmerMask); kmer_type codeSeedRight_revcomp(char *seq, kmer_type val_seed, bool new_read); kmer_type codeSeedRight_revcomp(char *seq, kmer_type val_seed, bool new_read, int sizeKmer, kmer_type kmerMask); unsigned char code_n_NT(char *seq, int nb); unsigned char code4NT(char *seq); uint64_t revcomp(uint64_t x); uint64_t revcomp(uint64_t x, int size); #ifdef _largeint LargeInt revcomp(LargeInt x); LargeInt revcomp(LargeInt x, int size); #endif #ifdef _ttmath ttmath::UInt revcomp(ttmath::UInt x); ttmath::UInt revcomp(ttmath::UInt x, int size); #endif #ifdef _LP64 __uint128_t revcomp(__uint128_t x); __uint128_t revcomp(__uint128_t x, int size); #endif int code2seq ( kmer_type code,char *seq); int code2seq ( kmer_type code,char *seq, int sizeKmer, kmer_type kmerMask); int code2nucleotide( kmer_type code, int which_nucleotide); kmer_type extractKmerFromRead(char *readSeq, int position, kmer_type *graine, kmer_type *graine_revcomp); kmer_type extractKmerFromRead(char *readSeq, int position, kmer_type *graine, kmer_type *graine_revcomp, bool sequential); kmer_type extractKmerFromRead(char *readSeq, int position, kmer_type *graine, kmer_type *graine_revcomp, bool sequential, int sizeKmer, kmer_type kmerMask); // compute the next kmer w.r.t forward or reverse strand, e.g. for ACTG (revcomp = CAGT) // it makes sure the result is the min(kmer,revcomp_kmer) // indicates if the result is the revcomp_kmer by setting *strand // examples: // next_kmer(ACTG,A,&0)=CTGA with strand = 0 (because revcomp=TCAG); // next_kmer(ACTG,A,&1)= (revcomp of ACTG + A = CAGT+A = ) AGTA with strand = 0 (because revcomp = TACT) kmer_type next_kmer(kmer_type graine, int added_nt, int *strand); void revcomp_sequence(char s[], int len); kmer_type codeSeed_bin(char *seq); kmer_type codeSeedRight_bin(char *seq, kmer_type val_seed, bool new_read); kmer_type codeSeedRight_revcomp_bin(char *seq, kmer_type val_seed, bool new_read); kmer_type extractKmerFromRead_bin(char *readSeq, int position, kmer_type *graine, kmer_type *graine_revcomp, bool use_compressed); char* print_kmer(kmer_type kmer); // debugging char* print_kmer(kmer_type kmer, int sizeKmer, kmer_type kmerMask); // debugging #endif discoSnp/minia/LinearCounter.h0000644000000000000000000000104212122310524015343 0ustar rootroot// // LinearCounter.h #ifndef LinearCounter_h #define LinearCounter_h #include #include #include #include // for log2f #include "Bank.h" #include "Bloom.h" class LinearCounter{ protected: Bloom *bloom; unsigned long desired_size, bloom_size; public: void add(bloom_elem kmer); long count(); int contains(bloom_elem kmer); // dummy, because bloom_pass_reads wants this method to be exposed bool is_accurate(); LinearCounter(long size); ~LinearCounter(); }; #endif discoSnp/minia/Hash16.h0000644000000000000000000000360212062133074013635 0ustar rootroot// // Hash16.h // // Created by Guillaume Rizk on 19/02/12. // #ifndef Hash16_h #define Hash16_h #include #include #include #include "Pool.h" #include "Bloom.h" #include "Bank.h" //memory usage : sizeof(cell_ptr_t)*tai + sizeof(cell)*Nb_inserted // ie 4B*tai + 16B*nb_inserted #ifdef _largeint #include "LargeInt.h" typedef LargeInt hash_elem; #else #ifdef _ttmath #include "ttmath/ttmath.h" typedef ttmath::UInt hash_elem; #else #if (! defined kmer_type) || (! defined _LP64) typedef uint64_t hash_elem; #else typedef kmer_type hash_elem; #endif #endif #endif class Hash16{ protected: cell_ptr_t * datah; Pool* storage; uint64_t mask ; #ifdef _largeint inline uint64_t hashcode(LargeInt elem); #endif #ifdef _ttmath inline uint64_t hashcode(ttmath::UInt elem); #endif #ifdef _LP64 unsigned int hashcode( __uint128_t elem); #endif unsigned int hashcode( uint64_t elem); public: //print stats of elem having their value >=nks // void printstat(int nks); int printstat(int nks, bool print_collisions=0); void empty_all(); void insert(hash_elem graine, int val); int add(hash_elem elem); void dump(FILE * count_file);//file should already be opened for writing int64_t getsolids( Bloom* bloom_to_insert, BinaryBank* solids, int nks); int get( hash_elem elem, int * val); int has_key( hash_elem elem); int remove( hash_elem graine, int * val); // iterator functions: struct { int64_t cell_index; cell * cell_ptr; cell_ptr_t cell_internal_ptr; } iterator; void start_iterator(); bool next_iterator(); uint64_t tai; uint64_t nb_elem; Hash16(int tai_Hash16); Hash16(); ~Hash16(); }; #endif discoSnp/minia/Utils.h0000644000000000000000000000627612424137004013714 0ustar rootroot#include #include #include #include #include #include #include #include // for log2f #include // for max #include // for truncate #include // for INT_MAX #ifndef UTILS_H #define UTILS_H #include "Bank.h" #include "Kmer.h" #ifndef NO_BLOOM_UTILS #include "Bloom.h" #include "Hash16.h" #include "LinearCounter.h" #endif using namespace std; # extern struct timeval tim; #define STARTWALL(TT) \ gettimeofday(&tim, NULL);\ double wdebut ## TT =tim.tv_sec +(tim.tv_usec/1000000.0); #define STOPWALL(TT,MESSAGE) \ gettimeofday(&tim, NULL);\ double wfin ## TT =tim.tv_sec +(tim.tv_usec/1000000.0); \ fprintf(stderr,"-------------------%s time Wallclock %g s\n",MESSAGE, wfin ## TT-wdebut ## TT ); // global variables extern int nks; extern uint32_t max_couv; extern char prefix[1024]; extern float NBITS_PER_KMER; // constants extern const char *solid_kmers_file;// = (char *)"solid_kmers_binary"; extern const char *false_positive_kmers_file ;//= (char *)"false_positive_kmers"; extern const char *bloom_file ;//= (char *)"bloom_data"; extern const char *assembly_file ;//= (char *)"contigs.fa"; extern const char *branching_kmers_file ;//= (char *)"branching_kmers"; // (only useful for multiple assemblies with same bloom&debloom structure (ie debugging)) extern const char *binary_read_file;// = (char *)"reads_binary"; extern const char *histo_file_name ;//= (char *)"histo"; extern const char *breakpoints_file_name; // = (char *)"breakpoints"; extern const char *assoc_kmer_file ; char *return_file_name(const char *suffix); void estimate_distinct_kmers(unsigned long genome_size, Bank *Reads); uint64_t extrapolate_distinct_kmers(Bank *Reads); uint64_t extrapolate_distinct_kmers_wrapped(unsigned long nbytes_memory, Bank *Reads); #ifndef NO_BLOOM_UTILS void bloom_count(Bank * reads, unsigned long max_memory); template Bloom *bloom_create_bloo1(T *bloom_counter); template Bloom *bloom_create_bloo1(T *bloom_counter, bool from_dump); templatevoid bloom_pass_reads_binary(T *bloom_to_insert,BloomCpt *bloom_counter,char *stderr_message); templatevoid bloom_pass_reads(Bank *Sequences,T *bloom_to_insert,U *bloom_counter,char *stderr_message); #endif float needleman_wunch(string a, string b ); float needleman_wunch_mtg(string a, string b, int * nbmatch=NULL,int * nbmis=NULL,int * nbgaps=NULL, int deb =-1 ); class Progress { public: int timer_mode; struct timeval timestamp; double heure_debut, heure_actuelle ; uint64_t done; uint64_t todo; int subdiv ; // progress printed every 1/subdiv of total to do double partial; double partial_threaded[16]; uint64_t done_threaded[16]; double steps ; //steps = todo/subidv void init(uint64_t ntasks, const char * msg); void finish(); void finish_threaded();// called by only one of the threads void inc(uint64_t ntasks_done); void inc(uint64_t ntasks_done, int tid); //threads collaborate to this same progress bar void set(uint64_t ntasks_done); Progress () : timer_mode(0) {} //include timer, to print ETA ? }; #endif discoSnp/minia/Traversal.cpp0000644000000000000000000010220112304050544015073 0ustar rootroot#include #include // for max() #include "Traversal.h" using namespace std; Traversal::~Traversal() { } void Traversal::set_maxlen(int given_maxlen) { maxlen = given_maxlen; } void Traversal::commit_stats() { final_stats = stats; } void Traversal::revert_stats() { stats = final_stats; } // -------------------------- // generic structure for traversals void Traversal::set_max_depth(int given_max_depth) { max_depth = given_max_depth; } void Traversal::set_max_breadth(int given_max_breadth) { max_breadth = given_max_breadth; } // mark recorded extensions void Traversal::mark_extensions(set *extensions_to_mark) { if (terminator == NULL) return; for(set::iterator it = extensions_to_mark->begin(); it != extensions_to_mark->end() ; ++it) { terminator->mark(*it); } } // return the number of extension possibilities, the variable nt will contain one of them // order=0: just examine immediate neighbors // order>0: don't return extensions yielding to deadends of length <= order // todo-order>0: there is probably a minor bug: it is likely to return 0 extensions too early for end of contigs int traversal_extensions(kmer_type kmer, int strand, int &nt, Bloom *bloom_solid_kmers, Set *debloom) { if (order==0) // faster order=0 extensions (note: in fact, order is always equal to 0) { int nb_extensions = 0; for(int test_nt=0; test_nt<4; test_nt++) { int current_strand = strand; kmer_type current_kmer = next_kmer(kmer,test_nt,¤t_strand); if (bloom_solid_kmers->contains(current_kmer) && !debloom->contains(current_kmer)) { nt = test_nt; nb_extensions ++; } } return nb_extensions; } else { if (order==1) // optimized code for order=1 (copied from assemb.cpp) { int nb_extensions = 0; for(int test_nt=0; test_nt<4; test_nt++) { int current_strand = strand; kmer_type current_kmer = next_kmer(kmer,test_nt, ¤t_strand); if(bloom_solid_kmers->contains(current_kmer) && !debloom->contains(current_kmer)){ bool is_linked = false; for(int tip_nt=0; tip_nt<4; tip_nt++) { int new_strand = current_strand; kmer_type kmer_after_possible_tip = next_kmer(current_kmer,tip_nt, &new_strand); if(bloom_solid_kmers->contains(kmer_after_possible_tip) && !debloom->contains(kmer_after_possible_tip)) { is_linked = true; break; } } if (!is_linked) continue; // it's a tip, because it's linked to nothing nt = test_nt; nb_extensions++; } } return nb_extensions; } else { // slower, general code for order>=0 Frontline frontline( kmer, strand, bloom_solid_kmers, debloom, NULL, 0); while (frontline.depth <= order) // go one step further than order { frontline.go_next_depth(); if (frontline.size() <= 1) // stop when no more ambiguous choices break; if (frontline.size() > 10) // don't allow a breadth too large anyway break; } if (frontline.size() > 0) // recover the nt that lead to this node nt = frontline.front().nt; return frontline.size(); } } } int Traversal::extensions(kmer_type kmer, int strand, int &nt) { return traversal_extensions(kmer,strand,nt,bloom,debloom); } /* * this function is actually only used when order > 0 * tip is: * one strand: 0 extension * other strand: 1 extension to N * N: >= 3 neighbors * */ bool is_tip(kmer_type kmer, Bloom *bloom_solid_kmers, Set *debloom) { int nb_extensions[2]={0}; kmer_type N=0; int N_strand=0; for (int strand=0;strand<2; strand++) { for(int test_nt=0; test_nt<4; test_nt++) { int current_strand = strand; kmer_type current_kmer = next_kmer(kmer,test_nt, ¤t_strand); if(bloom_solid_kmers->contains(current_kmer) && !debloom->contains(current_kmer)){ N = current_kmer; N_strand = current_strand; nb_extensions[strand]++; } } } /* if (nb_extensions[0] != 0 && nb_extensions[1] != 0) return false;*/ // fixme-order>0: too strict, because includes ends of contigs if (nb_extensions[0] == 0 || nb_extensions[1] == 0) return true; // now test degree of N int N_degree = 0; for(int test_nt=0; test_nt<4; test_nt++) { int current_strand = N_strand; kmer_type current_kmer = next_kmer(N,test_nt, ¤t_strand); if(bloom_solid_kmers->contains(current_kmer) && !debloom->contains(current_kmer)){ N_degree++; } } return N_degree>=3; } // from a branching kmer, get a new node that has never been used before // (very simple initial k-mer selection, current used in minia-graph) bool Traversal::get_new_starting_node(kmer_type branching_kmer, kmer_type &starting_kmer) { char newNT[2]; int nt; // start with the branching kmer itself if ( ! terminator->is_marked(branching_kmer) ) { terminator->mark(branching_kmer); starting_kmer = branching_kmer; return true; } for (int current_strand = 0; current_strand<2 ; current_strand++) { for(nt=0; nt<4; nt++) { int strand = current_strand; kmer_type current_kmer; current_kmer = next_kmer(branching_kmer,nt,&strand); if (bloom->contains(current_kmer) && !debloom->contains(current_kmer)) { // only start from an unmarked nt/strand combo if (terminator->is_marked(current_kmer)) continue; terminator->mark(current_kmer); starting_kmer = current_kmer; return true; } } } return false; } // improved version of the code above // TODO: port minia-graph to use this version, make sure it doesn't break the simple paths traversal bool Traversal::get_new_starting_node_improved(kmer_type branching_kmer, kmer_type &starting_kmer) { char newNT[2]; int nt; for (int current_strand = 0; current_strand<2 ; current_strand++) { for(nt=0; nt<4; nt++) { int strand = current_strand; kmer_type current_kmer; current_kmer = next_kmer(branching_kmer,nt,&strand); if (bloom->contains(current_kmer) && !debloom->contains(current_kmer)) { // alright let's use this convention now: // to select new kmers: mark non-branching neighbors of branching nodes // to mark as used in assembly: mark branching nodes // only start from a non-branching k-mer if (terminator->is_branching(current_kmer)) continue; if (terminator->is_marked(current_kmer)) continue; terminator->mark(current_kmer); starting_kmer = current_kmer; return true; } } } // actually never start in a branching k-mer // if ( ! terminator->is_marked(branching_kmer) ) // { // terminator->mark(branching_kmer); // starting_kmer = branching_kmer; // return true; // } return false; } /* the initial k-mer selection function from original Minia release (up until fall 2013) was: detect a 2k+2 simple path (anything NOT deadend or snp) around the branching kmer and start to extend from it the rationale was: -> what if it's a simplepathtraversal and it chooses to start in a deadend? -> what if it's a monumenttraversal and the kmer is a true branching: won't be traversed yet, branching kmers are the only indexed ones //bool Traversal::find_starting_kmer_inside_simple_path(kmer_type branching_kmer, kmer_type &starting_kmer) * this function was unused since fall 2013 and to prevent bugs due to new marking conventions, it has been removed on 10 Feb 2014. * now we use this: -> get a better starting point than a branching kmer inside a long (~2k) simple path: -> a k-mer that isn't inside a bubble/tip */ bool MonumentTraversal::find_starting_kmer(kmer_type branching_kmer, kmer_type &starting_kmer) { char newNT[2]; int nt; bool debug=false; int sum_depths = 0; if (!get_new_starting_node_improved(branching_kmer, starting_kmer)) return false; if (debug) printf("getting new starting kmer\n"); for (int strand = 0; strand<2 ; strand++) { kmer_type previous_kmer = 0; int previous_strand = 0; // do a BFS to make sure we're not inside a bubble or tip Frontline frontline( starting_kmer, strand, bloom, debloom, terminator, NULL, 0, false); do { bool should_continue = frontline.go_next_depth(); if (!should_continue) { if (debug) printf("strand %d shouldnt continue\n", strand); break; } // put the same contraints as in a bubble if (frontline.depth > max_depth || frontline.size() > max_breadth) { if (debug) printf("strand %d reached max depth or breadth (%d %d)\n",strand, frontline.depth,frontline.size()); break; } // stopping condition: nothing more to explore if (frontline.size() == 0) { if (debug) printf("strand %d nothing more to explore\n", strand); break; } char useless_string[max_depth+1]; int useless_int; if (frontline.size() <= 1) { kmer_type current_kmer = 0; if (frontline.size() == 1) { node current_node = frontline.front(); current_kmer = current_node.kmer; } if ((previous_kmer != 0) && terminator->is_branching(previous_kmer)) { /* the current situation is: * * current_kmer previous_kmer * -O-------------O------------- ... ---starting_kmer * \_.... * * or * * [no extension] previous_kmer * X O------------- ... ---starting_kmer * \_.... * * so, by looking one k-mer ahead, we make sure that previous_kmer only branches to the right * */ set all_involved_extensions; Terminator *save_terminator = terminator; terminator = NULL; // do not use terminator in the following bubble traversal if (explore_branching(previous_kmer, 1-previous_strand, (char*)useless_string, useless_int, current_kmer, &all_involved_extensions)) { if (debug) printf("depth %d useless int %d and starting belongs %d nb involved nodes %lu\n",frontline.depth,useless_int,all_involved_extensions.find(starting_kmer) != all_involved_extensions.end(),all_involved_extensions.size()); if (all_involved_extensions.find(starting_kmer) != all_involved_extensions.end()) { terminator = save_terminator; return false; // starting_kmer is in a tip/bubble starting from current_kmer } } terminator = save_terminator; } } // update previous_kmer if (frontline.size() == 1) { node current_node = frontline.front(); kmer_type current_kmer = current_node.kmer; previous_kmer = current_kmer; previous_strand = current_node.strand; } else previous_kmer = 0; } while (1); if (debug) printf("strand %d depth %d\n",strand,frontline.depth); sum_depths += frontline.depth; } // don't even assemble those regions which have no chance to yield a long contig if (sum_depths < (sizeKmer+1)) return false; return true; } // main traversal function, which calls avance() // important: // for MonumentTraversal, either "previous_kmer" is unspecified and then "starting_kmer" is required to be non-branching, // or, if starting_kmer is branching, please specify the "previous_kmer" parameter, corresponding to a left k-mer that will // be ignored during in-branching checks int Traversal::traverse(kmer_type starting_kmer, char* resulting_sequence, int starting_strand, kmer_type previous_kmer) { kmer_type current_kmer = starting_kmer; int current_strand = starting_strand; // 0 = forward, 1 = reverse; int len_extension = 0; char newNT[max_depth+1]; int nnt = 0; bool looping = false; int bubble_start, bubble_end; bubbles_positions.clear(); //printf(" traversing %llX strand:%d\n",starting_kmer,current_strand); while( (nnt=avance(current_kmer, current_strand, len_extension == 0, newNT, previous_kmer))) { if (nnt < 0) // found branching or marked kmers break; if (nnt > 1) // it's a bubble for sure bubble_start = len_extension; // keep re-walking the nucleotides we just discovered, to append to consensus and mark kmers as we go for (int cur_nt = 0; cur_nt < nnt; cur_nt++) { resulting_sequence[len_extension]=newNT[cur_nt]; len_extension++; previous_kmer = current_kmer; current_kmer = next_kmer(current_kmer,NT2int(newNT[cur_nt]),¤t_strand); #ifndef DONTMARK terminator->mark(current_kmer); // mark kmer as used in the assembly #endif if (current_kmer == starting_kmer) // perfectly circular regions with no large branching can happen (rarely) looping = true; } if (nnt > 1) { bubble_end = len_extension; bubbles_positions.push_back(std::make_pair(bubble_start,bubble_end)); } if (looping) break; if (len_extension > maxlen) { // fprintf(stderr,"max contig len reached \n"); break; } } resulting_sequence[len_extension]='\0'; return len_extension; } // ---------------- // random branching traversal char Traversal::random_unmarked_avance(kmer_type kmer, int current_strand, bool first_extension, char * newNT) { char bin2NT[4] = {'A','C','T','G'}; int nt; for(nt=0; nt<4; nt++) //takes first branch we find { int strand = current_strand; kmer_type new_graine = next_kmer(kmer,nt,&strand); if(bloom->contains(new_graine) && !debloom->contains(new_graine) && !terminator->is_marked(kmer, nt, current_strand)){ *newNT = bin2NT[nt]; return 1; } } return 0; } char RandomBranchingTraversal::avance(kmer_type kmer, int current_strand, bool first_extension, char * newNT, kmer_type previous_kmer) { return random_unmarked_avance(kmer,current_strand,first_extension,newNT); } // ---------------- // simple paths traversal // invariant: the input kmer has no in-branching. // returns: // 1 if a good extension is found // 0 if a deadend was reached // -1 if out-branching was detected // -2 if no out-branching but next kmer has in-branching int Traversal::simple_paths_avance(kmer_type kmer, int strand, bool first_extension, char * newNT) { char bin2NT[4] = {'A','C','T','G'}; int nb_extensions = 0, in_branching_degree = 0; int good_nt; // return the number of possible forward extensions nb_extensions = extensions(kmer, strand, good_nt); if (nb_extensions == 1) { // if the next kmer has in-branching, don't extend the current kmer int second_strand = strand; kmer_type second_kmer = next_kmer(kmer,good_nt,&second_strand); int osef; in_branching_degree = extensions(second_kmer,1-second_strand,osef); if (in_branching_degree > 1) return -2; *newNT = bin2NT[good_nt]; return 1; } if (nb_extensions > 1) // if this kmer has out-branching, don't extend it return -1; return 0; } char SimplePathsTraversal::avance(kmer_type kmer, int current_strand, bool first_extension, char * newNT, kmer_type previous_kmer) { return max(simple_paths_avance(kmer,current_strand,first_extension,newNT),0); } // ---------------- // // Monument traversal // a frontline is a set of nodes having equal depth in the BFS Frontline::Frontline(kmer_type starting_kmer, int starting_strand, Bloom *bloom, Set *debloom, Terminator *terminator, set *all_involved_extensions, kmer_type previous_kmer, bool check_in_branching) : starting_kmer(starting_kmer), starting_strand(starting_strand), bloom(bloom), debloom(debloom), terminator(terminator), all_involved_extensions(all_involved_extensions), previous_kmer(previous_kmer), check_in_branching(check_in_branching), depth(0) { already_frontlined.insert(starting_kmer); already_frontlined.insert(previous_kmer); node first_node(starting_kmer,starting_strand,-1); frontline.push(first_node); } bool Frontline::go_next_depth() { // extend all nodes in this frontline simultaneously, creating a new frontline stopped_reason=NONE; queue_nodes new_frontline; while (!frontline.empty()) { node current_node = frontline.front(); frontline.pop(); kmer_type current_kmer = current_node.kmer; int current_strand = current_node.strand; // make sure this node doesn't have large in-branching. if ( check_in_branching && check_inbranching(current_kmer,current_strand)) { //printf("######## found large in-branching (depth=%d)\n",depth); return false; // detected that the bubble isn't simple (there is large in-branching inside) } // enqueue all neighbors of this node, except these that were already in a frontline for(int nt=0; nt<4; nt++) { kmer_type new_kmer = current_kmer; int new_strand = current_strand; // propagate information where this node comes from int from_nt = (current_node.nt == -1) ? nt : current_node.nt; // go to next kmer new_kmer = next_kmer(new_kmer,nt,&new_strand); // test if that node hasn't already been explored if (already_frontlined.find(new_kmer)!= already_frontlined.end()) continue; if(bloom->contains(new_kmer) && ((debloom == NULL) || (!debloom->contains(new_kmer)))) { // if this bubble contains a marked (branching) kmer, stop everyone at once (to avoid redundancy) if (terminator != NULL && terminator->is_branching(new_kmer)) if (terminator->is_marked_branching(new_kmer)) { stopped_reason=Frontline::MARKED; return false; } node new_node(new_kmer,new_strand,from_nt); new_frontline.push(new_node); already_frontlined.insert(new_kmer); //if (check_in_branching) //printf("frontline _depth: %d enqueuing kmer %s\n",depth ,print_kmer(new_kmer)); // since this extension is validated, insert into the list of involved ones if (all_involved_extensions != NULL) all_involved_extensions->insert(new_kmer); } } } frontline = new_frontline; ++depth; return true; } int Frontline::size() { return frontline.size(); } node Frontline::front() { return frontline.front(); } // new code, not in monument, to detect any in-branching longer than 3k bool Frontline::check_inbranching(kmer_type from_kmer, int from_strand) { int nt; for(nt=0; nt<4; nt++) { int strand = 1-from_strand; kmer_type current_kmer; current_kmer = next_kmer(from_kmer,nt,&strand); // only check in-branching from kmers not already frontlined // which, for the first extension, includes the previously traversed kmer (previous_kmer) // btw due to avance() invariant, previous_kmer is always within a simple path if (already_frontlined.find(current_kmer) != already_frontlined.end()) continue; if (bloom->contains(current_kmer) && !debloom->contains(current_kmer)) { // create a new frontline inside this frontline to check for large in-branching (i know, we need to go deeper, etc..) Frontline frontline( current_kmer, strand, bloom, debloom, terminator, all_involved_extensions,from_kmer, false); do { bool should_continue = frontline.go_next_depth(); if (!should_continue) { stopped_reason=Frontline::IN_BRANCHING_OTHER; break; } // don't allow a depth > 3k if (frontline.depth > 3 * sizeKmer) { stopped_reason=Frontline::IN_BRANCHING_DEPTH; break; } // don't allow a breadth too large if (frontline.size()> 10) { stopped_reason=Frontline::IN_BRANCHING_BREADTH; break; } // stopping condition: no more in-branching if (frontline.size() == 0) break; } while (1); if (frontline.size() > 0) return true; // found large in-branching } } // didn't find any in-branching return false; } // similar to Monument's extension_graph.py:find_end_of_branching // basically do a bounded-depth, bounded-breadth BFS int MonumentTraversal::find_end_of_branching(kmer_type starting_kmer, int starting_strand, kmer_type &end_kmer, int &end_strand, kmer_type previous_kmer, set *all_involved_extensions) { bool check_in_branching = true; Frontline frontline( starting_kmer, starting_strand, bloom, debloom, terminator, all_involved_extensions, previous_kmer, check_in_branching); do { bool should_continue = frontline.go_next_depth(); if (!should_continue) { if (frontline.stopped_reason == Frontline::MARKED) stats.couldnt_because_marked_kmer++; if (frontline.stopped_reason == Frontline::IN_BRANCHING_DEPTH) stats.couldnt_inbranching_depth++; if (frontline.stopped_reason == Frontline::IN_BRANCHING_BREADTH) stats.couldnt_inbranching_breadth++; if (frontline.stopped_reason == Frontline::IN_BRANCHING_OTHER) stats.couldnt_inbranching_other++; return 0; } // don't allow a depth too large if (frontline.depth > max_depth) { stats.couldnt_traverse_bubble_depth++; return 0; } // don't allow a breadth too large if (frontline.size()> max_breadth) { stats.couldnt_traverse_bubble_breadth++; return 0; } // stopping condition: frontline is either empty, or contains only 1 kmer // needs the kmer to be non-branching, in order to avoid a special case of bubble immediatly after a bubble // affects mismatch rate in ecoli greatly if (frontline.size() == 0) { stats.couldnt_find_extension++; return 0; } // if (frontline.size() == 1) // longer contigs but for some reason, higher mismatch rate if (frontline.size() == 1 && (terminator == NULL || ( !terminator->is_branching(frontline.front().kmer) ))) break; } while (1); if (frontline.size()==1) { node end_node = frontline.front(); end_kmer = end_node.kmer; end_strand = end_node.strand; return frontline.depth; } return 0; } // similar to Monument's extension_graph.py:all_paths_between set MonumentTraversal::all_consensuses_between(kmer_type start_kmer, int start_strand, kmer_type end_kmer, int end_strand, int traversal_depth, set used_kmers, string current_consensus, bool &success) { char bin2NT[4] = {'A','C','T','G'}; //printf("all consensuses between traversal_depth: %d kmer %s success %d\n",traversal_depth,print_kmer(start_kmer),success); set consensuses; // find_end_of_branching and all_consensues_between do not always agree on clean bubbles ends // until I can fix the problem, here is a fix // to reproduce the problem: SRR001665.fasta 21 4 if (traversal_depth < -1) { success = false; return consensuses; } if (start_kmer == end_kmer)// not testing for end_strand anymore because find_end_of_branching doesn't care about strands { consensuses.insert(current_consensus); return consensuses; } // visit all neighbors for(int nt=0; nt<4; nt++) { // craft neighbor node int new_strand = start_strand; kmer_type new_graine = next_kmer(start_kmer,nt,&new_strand); // check if the neighbor node is valid if(bloom->contains(new_graine) && !debloom->contains(new_graine)){ // don't resolve bubbles containing loops // (tandem repeats make things more complicated) // that's a job for a gapfiller if (used_kmers.find(new_graine) != used_kmers.end()) { success = false; return consensuses; } // generate extended consensus sequence string extended_consensus(current_consensus); extended_consensus.append(1,bin2NT[nt]); // generate list of used kmers (to prevent loops) set extended_kmers(used_kmers); extended_kmers.insert(new_graine); // recursive call to all_consensuses_between set new_consensuses = all_consensuses_between(new_graine, new_strand, end_kmer, end_strand, traversal_depth - 1, extended_kmers, extended_consensus, success); consensuses.insert(new_consensuses.begin(), new_consensuses.end()); // mark to stop we end up with too many consensuses if (consensuses.size() > (unsigned int )max_breadth) success = false; } // propagate the stop if too many consensuses reached if (success == false) return consensuses; } return consensuses; } // just a wrapper set MonumentTraversal::all_consensuses_between(kmer_type start_kmer, int start_strand, kmer_type end_kmer, int end_strand, int traversal_depth, bool &success) { set used_kmers; used_kmers.insert(start_kmer); string current_consensus; success = true; //printf("all cons between - end kmer = %s\n",print_kmer(end_kmer)); return all_consensuses_between(start_kmer, start_strand, end_kmer, end_strand, traversal_depth, used_kmers, current_consensus, success); } // similar to Monument's extension_graph.py:validate_paths // return true if, basically, the consensuses aren't too different bool MonumentTraversal::validate_consensuses(set consensuses, char *result, int &result_length) { bool debug = false; // compute mean and stdev of consensuses int mean = 0; int path_number = 0; for(set::iterator it = consensuses.begin(); it != consensuses.end() ; ++it) { if (debug) printf("bubble path %d: %s (len=%lu)\n",path_number,(*it).c_str(),(*it).length()); mean+=(*it).length(); path_number++; } mean/=consensuses.size(); double stdev = 0; for(set::iterator it = consensuses.begin(); it != consensuses.end() ; ++it) { int consensus_length = (*it).length(); stdev += pow(fabs(consensus_length-mean),2); } stdev = sqrt(stdev/consensuses.size()); // don't traverse large bubbles if (mean > max_depth) return false; // don't traverse large deadends (here, having one consensus means the other paths were large deadends) if (consensuses.size() == 1 && mean > sizeKmer+1) // deadend length should be < k+1 (most have length 1, but have seen up to 10 in ecoli) return false; if (debug) printf("%lu-bubble mean %d, stdev %.1f\n",consensuses.size(),mean,stdev); // traverse bubbles if paths have roughly the same length if (stdev>mean/5) return false; // check that all consensuses are similar if (! all_consensuses_almost_identical(consensuses)) return false; // if all good, an arbitrary consensus is chosen string chosen_consensus = *consensuses.begin(); result_length = chosen_consensus.length(); if (result_length> max_depth) // it can happen that consensus is longer than max_depth, despite that we didn't explore that far (in a messy bubble with branchings inside) return false; chosen_consensus.copy(result, result_length); return true; } bool MonumentTraversal::all_consensuses_almost_identical(set consensuses) { for (set::iterator it_a = consensuses.begin(); it_a != consensuses.end(); it_a++) { set::iterator it_b = it_a; advance(it_b,1); while (it_b != consensuses.end()) { if (needleman_wunch(*it_a,*it_b) * 100 < consensuses_identity) return false; advance(it_b,1); } } return true; } // similar to Monument's extension_graph.py:explore_branching // return true if the branching can be traversed, and mark all involved nodes bool MonumentTraversal::explore_branching(kmer_type start_kmer, int start_strand, char *consensus, int &consensus_length, kmer_type previous_kmer, set *all_involved_extensions) { kmer_type end_kmer; int end_strand; // find end of branching, record all involved extensions (for future marking) // it returns false iff it's a complex bubble int traversal_depth = find_end_of_branching(start_kmer, start_strand, end_kmer, end_strand, previous_kmer, all_involved_extensions); if (!traversal_depth) { stats.couldnt_find_all_consensuses++; return false; } // find all consensuses between start node and end node set consensuses; bool success; consensuses = all_consensuses_between(start_kmer, start_strand, end_kmer, end_strand, traversal_depth+1, success); // if consensus phase failed, stop if (!success) return false; // validate paths, based on identity bool validated = validate_consensuses(consensuses, consensus, consensus_length); if (!validated) { stats.couldnt_validate_consensuses++; return false; } // the consensuses agree, mark all the involved extensions // (corresponding to alternative paths we will never traverse again) mark_extensions(all_involved_extensions); return true; } // wrapper bool MonumentTraversal::explore_branching(kmer_type start_kmer, int start_strand, char *consensus, int &consensus_length, kmer_type previous_kmer) { set *all_involved_extensions = new set; bool res = explore_branching(start_kmer, start_strand, consensus, consensus_length, previous_kmer, all_involved_extensions); delete all_involved_extensions; return res; } // invariant here: // kmer is always obtained after traversing a non-branching kmer // in other words, the only in-branching of that kmer is previous_kmer char MonumentTraversal::avance(kmer_type kmer, int current_strand, bool first_extension, char * newNT, kmer_type previous_kmer) { // if we're on a simple path, just traverse it int is_simple_path = simple_paths_avance(kmer, current_strand, first_extension, newNT); if (is_simple_path > 0) return 1; // the following function does: // * a bfs from the starting kmer, stopping when: // - breadth > max_breadth // or // - depth > max_depth // * check if there a single end point // * computing all possible paths between start and end // * returns one flattened consensus sequence int newNT_length; bool success = explore_branching(kmer, current_strand, newNT, newNT_length, previous_kmer); if (!success) { stats.ended_traversals++; return 0; } return newNT_length; } discoSnp/minia/Debloom.h0000644000000000000000000000167112364215742014200 0ustar rootroot#include #include #include #include #include #include #include // for log2f #include // for max #include // for truncate #ifndef DEBLOOM_H #define DEBLOOM_H #include "Bank.h" #include "Bloom.h" #include "Kmer.h" #include "Hash16.h" #include "Utils.h" #include "Traversal.h" #define DEBUGE(a) //printf a using namespace std; extern uint64_t b1_size ; extern uint64_t nbkmers_solid ; typedef ListSet FPSet; // list-based //typedef HashSet FPSet; // hash-based // GUS: see comment in Debloom.cpp, where false_positive is been declared extern Set *false_positives; int debloom(int order, int max_memory); void end_debloom_partition(bool last_partition); Set *dummy_false_positives(); Set *load_false_positives(); Set *load_false_positives_cascading4(); void print_size_summary(FPSet *fp); void print_size_summary(FPSetCascading4 *fp); #endif discoSnp/minia/Bloom.cpp0000644000000000000000000002467712316502726014233 0ustar rootroot// // Bloom.cpp // // Created by Guillaume Rizk on 9/02/12. // #include #include #include #include "Bloom.h" Bloom::Bloom() { //empty default constructor nb_elem = 0; blooma = NULL; } BloomCpt::BloomCpt() { //empty default constructor nb_elem = 0; blooma = NULL; } void Bloom::setSeed(uint64_t seed) { if(user_seed==0) { user_seed = seed; this->generate_hash_seed(); //regenerate the hash with the new seed } else{ fprintf(stderr,"Warning! you should not change the seed a second time!, resuming with previous seed %llu \n",(unsigned long long)user_seed); } } void Bloom::set_number_of_hash_func(int i) { if(i>NSEEDSBLOOM || i<1){ fprintf(stderr,"%i is not a valid value for number of hash funcs, should be in [1-%i], resuming wild old value %i\n",i,NSEEDSBLOOM,n_hash_func ); return; } n_hash_func = i; } void Bloom::generate_hash_seed() { unsigned int i; for ( i = 0; i < NSEEDSBLOOM; ++i) { seed_tab[i]= rbase[i]; } for ( i = 0; i < NSEEDSBLOOM; ++i) { seed_tab[i]= seed_tab[i] * seed_tab[(i+3) % NSEEDSBLOOM] + user_seed ; } } #ifdef _largeint inline uint64_t Bloom::hash_func(LargeInt elem, int num_hash) { // hash = XOR_of_series[hash(i-th chunk iof 64 bits)] uint64_t result = 0, chunk, mask = ~0; LargeInt intermediate = elem; int i; for (i=0;i> 64; result ^= hash_func(chunk,num_hash); } return result; } #endif #ifdef _ttmath inline uint64_t Bloom::hash_func(ttmath::UInt elem, int num_hash) { // hash = XOR_of_series[hash(i-th chunk iof 64 bits)] uint64_t result = 0, to_hash; ttmath::UInt intermediate = elem; uint32_t mask=~0, chunk; int i; for (i=0;i>= 32; (intermediate & mask).ToInt(chunk); to_hash |= ((uint64_t)chunk) << 32 ; intermediate >>= 32; result ^= hash_func(to_hash,num_hash); } return result; } #endif #ifdef _LP64 inline uint64_t Bloom::hash_func( __uint128_t elem, int num_hash) { // hash(uint128) = ( hash(upper 64 bits) xor hash(lower 64 bits)) return hash_func((uint64_t)(elem>>64),num_hash) ^ hash_func((uint64_t)(elem&((((__uint128_t)1)<<64)-1)),num_hash); } #endif inline uint64_t Bloom::hash_func( uint64_t key, int num_hash) { uint64_t hash = seed_tab[num_hash]; hash ^= (hash << 7) ^ key * (hash >> 3) ^ (~((hash << 11) + (key ^ (hash >> 5)))); hash = (~hash) + (hash << 21); // hash = (hash << 21) - hash - 1; hash = hash ^ (hash >> 24); hash = (hash + (hash << 3)) + (hash << 8); // hash * 265 hash = hash ^ (hash >> 14); hash = (hash + (hash << 2)) + (hash << 4); // hash * 21 hash = hash ^ (hash >> 28); hash = hash + (hash << 31); return hash; } //tai is 2^tai_bloom Bloom::Bloom(int tai_bloom) { n_hash_func = 4 ;//def user_seed =0; nb_elem = 0; tai = (1LL << tai_bloom); nchar = tai/8LL; blooma =(unsigned char *) malloc( nchar *sizeof(unsigned char)); // 1 bit per elem memset(blooma,0,nchar *sizeof(unsigned char)); //fprintf(stderr,"malloc Power-of-two bloom %lli MB nchar %llu %llu\n",(long long)((tai/8LL)/1024LL/1024LL),(unsigned long long)nchar,(unsigned long long)(tai/8)); this->generate_hash_seed(); } Bloom::Bloom(uint64_t tai_bloom) { //printf("custom construc \n"); n_hash_func = 4 ;//def user_seed =0; nb_elem = 0; tai = tai_bloom; nchar = (1+tai/8LL); blooma =(unsigned char *) malloc( nchar *sizeof(unsigned char)); // 1 bit per elem memset(blooma,0,nchar *sizeof(unsigned char)); //fprintf(stderr,"malloc bloom %lli MB \n",(tai/8LL)/1024LL/1024LL); this->generate_hash_seed(); } // //tai is 2^tai_bloom BloomCpt::BloomCpt(int tai_bloom) { n_hash_func = 2; user_seed = 0; nb_elem = 0; tai = (1LL << tai_bloom); blooma =(unsigned char *) malloc( (tai/2) *sizeof(unsigned char)); //4bits per elem memset(blooma,0,(tai/2) *sizeof(unsigned char)); fprintf(stderr,"malloc bloom cpt %lli MB \n",(tai/2LL)/1024LL/1024LL); this->generate_hash_seed(); } // //tai is 2^tai_bloom BloomCpt3::BloomCpt3(int tai_bloom) { n_hash_func = 2; user_seed = 0; nb_elem = 0; tai = (1LL << tai_bloom); //blooma =(unsigned char *) malloc( (tai/2) *sizeof(unsigned char)); //4bits per elem blooma3 = (uint64_t*) malloc( ((tai/21)+1) *sizeof(uint64_t)); //3bits per elem, 21 elem per uint64 memset(blooma3,0, ((tai/21)+1) *sizeof(uint64_t)); fprintf(stderr,"malloc bloom cpt64 3 bits %lli MB \n",8*(tai/21LL)/1024LL/1024LL); this->generate_hash_seed(); } // //tai is 2^tai_bloom BloomCpt2::BloomCpt2(int tai_bloom) { n_hash_func = 2; user_seed = 0; nb_elem = 0; tai = (1LL << tai_bloom); //blooma =(unsigned char *) malloc( (tai/2) *sizeof(unsigned char)); //4bits per elem blooma2 = (uint64_t*) malloc( (tai/32) *sizeof(uint64_t)); //2bits per elem, 32 elem per uint64 memset(blooma2,0, (tai/32) *sizeof(uint64_t)); fprintf(stderr,"malloc bloom cpt64 2 bits %lli MB \n",8*(tai/32LL)/1024LL/1024LL); this->generate_hash_seed(); } Bloom::~Bloom() { if(blooma!=NULL) free(blooma); } BloomCpt3::~BloomCpt3() { if(blooma3!=NULL) free(blooma3); } BloomCpt2::~BloomCpt2() { if(blooma2!=NULL) free(blooma2); } void Bloom::dump(char * filename) { FILE *file_data; file_data = fopen(filename,"wb"); fwrite(blooma, sizeof(unsigned char), nchar, file_data); //1+ printf("bloom dumped \n"); } void Bloom::load(char * filename) { FILE *file_data; file_data = fopen(filename,"rb"); printf("loading bloom filter from file, nelem %lli \n",nchar); fread(blooma, sizeof(unsigned char), nchar, file_data); printf("bloom loaded\n"); } long Bloom::weight() { // return the number of 1's in the Bloom, nibble by nibble const unsigned char oneBits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4}; long weight = 0; for(uint64_t index = 0; index < nchar; index++) { unsigned char current_char = blooma[index]; weight += oneBits[current_char&0x0f]; weight += oneBits[current_char>>4]; } return weight; } void Bloom::add(bloom_elem elem) { uint64_t h1; int i; for(i=0; i> 3] |= bit_mask[h1 & 7]; } //nb_elem++; } int Bloom::contains(bloom_elem elem) { uint64_t h1; int i; for(i=0; i> 3 ] & bit_mask[h1 & 7]) != bit_mask[h1 & 7]) return 0; } return 1; } void BloomCpt::add(bloom_elem elem) { uint64_t h1; unsigned char val,cpt_per_key; int i; for(i=0; i> (4* (h1 & 1)) ; cpt_per_key++; if(cpt_per_key==16) cpt_per_key = 15; //satur at 15 val &= ~ cpt_mask[h1 & 1]; val |= cpt_per_key << (4* (h1 & 1)) ; blooma [h1 / cpt_per_char] = val; } } //9698232370296160 int BloomCpt::contains_n_occ(bloom_elem elem, int nks) { uint64_t h1; unsigned char cpt_per_key; int i; for(i=0; i> (4* (h1 & 1)); if(cpt_per_key> (3* (h1 %21)) ; cpt_per_key++; if(cpt_per_key==8) cpt_per_key = 7; //satur at 7 val &= ~ cpt_mask21[h1 % 21]; val |= cpt_per_key << (3* (h1 % 21)) ; blooma3 [h1 / 21] = val; // if(elem==9698232370296160) printf("--%016llX %i\n", val,cpt_per_key); } } int BloomCpt3::contains_n_occ(bloom_elem elem, int nks) { uint64_t h1; unsigned char cpt_per_key; int i; // printf("--contains-- \n"); // if(elem==9698232370296160) printf ("\nquery3 elem %lli \n",elem); for(i=0; i> (3* (h1 % 21)); //printf("%016llX\n", blooma3 [h1 / 21]); //printf("cpt %i \n", cpt_per_key); //if(elem==9698232370296160) printf("bloocpt3 %i \n", cpt_per_key); if(cpt_per_key> (2* (h1 & 31)) ; cpt_per_key++; if(cpt_per_key==4) cpt_per_key = 3; //satur at 3 val &= ~ cpt_mask32[h1 & 31]; val |= cpt_per_key << (2* (h1 & 31)) ; blooma2 [h1 / 32] = val; // if(elem==9698232370296160) printf("--%016llX %i\n", val,cpt_per_key); } } int BloomCpt2::contains_n_occ(bloom_elem elem, int nks) { uint64_t h1; unsigned char cpt_per_key; int i; for(i=0; i> (2* (h1 & 31)); if(cpt_per_key #include #include #include // for max #include "OAHash.h" using namespace::std; OAHash::OAHash(uint64_t max_memory) // in bytes { hash_size = max_memory / sizeof(element_pair); if (hash_size == 0) { printf("empty OAHash allocated\n"); exit(1); } nb_inserted_keys = 0; data = (element_pair *) calloc( hash_size, sizeof(element_pair)); //create hashtable } OAHash::~OAHash() { free(data); } int OAHash::size_entry() { return sizeof(element_pair); } // hash functions: [ any integer type, e.g. 64 bits, 128 bits or ttmath ] -> [ 64 bits hash ] #ifdef _largeint inline uint64_t OAHash::hashcode(LargeInt elem) { // hash = XOR_of_series[hash(i-th chunk iof 64 bits)] uint64_t result = 0, chunk, mask = ~0; LargeInt intermediate = elem; int i; for (i=0;i> 64; result ^= hashcode(chunk); } return result; } #endif #ifdef _ttmath inline uint64_t OAHash::hashcode(ttmath::UInt elem) { // hash = XOR_of_series[hash(i-th chunk iof 64 bits) uint64_t result = 0, to_hash; ttmath::UInt intermediate = elem; uint32_t cmask=~0, chunk; int i; for (i=0;i>= 32; (intermediate & cmask).ToInt(chunk); to_hash |= ((uint64_t)chunk) << 32 ; intermediate >>= 32; result ^= hashcode(to_hash); } return result; } #endif #ifdef _LP64 inline uint64_t OAHash::hashcode( __uint128_t elem ) { // hashcode(uint128) = ( hashcode(upper 64 bits) xor hashcode(lower 64 bits)) return (hashcode((uint64_t)(elem>>64)) ^ hashcode((uint64_t)(elem&((((__uint128_t)1)<<64)-1)))); } #endif inline uint64_t OAHash::hashcode( uint64_t elem ) { uint64_t code = elem; code = code ^ (code >> 14); //supp code = (~code) + (code << 18); code = code ^ (code >> 31); code = code * 21; code = code ^ (code >> 11); code = code + (code << 6); code = code ^ (code >> 22); return code; } bool OAHash::is_occupied(element_pair *element) { return (element->value != 0); } OAHash::element_pair * OAHash::find_slot(key_type key) { uint64_t ptr = hashcode(key) % hash_size; element_pair *element = data+ptr; uint64_t retries = 0; // search until we either find the key, or find an empty slot. while ( ( is_occupied(element)) && ( element->key != key ) && (retries < hash_size)) { ptr = (ptr + 1) % hash_size; element = data+ptr; retries++; } if (retries == hash_size) { printf("OAHash: max rehashes reached: %lld (notify a developer)\n",(long long)hash_size); exit(1); } return element; } //if graine already here, overwrite old value void OAHash::insert(key_type graine, int value) { element_pair *element = find_slot(graine); if (!is_occupied(element)) { element->key = graine; nb_inserted_keys++; } element->value = value; } // increment the value of a graine void OAHash::increment(key_type graine) { element_pair *element = find_slot(graine); if (!is_occupied(element)) { element->key = graine; nb_inserted_keys++; } if( element->value == -1) element->value = 0; //special case, emulate 0 value with -1, (0 is not a valid value, used for empty cell) element->value = element->value + 1; } bool OAHash::get( key_type graine, int * val) { element_pair *element = find_slot(graine); if (!is_occupied(element)) return false; if ((element->key) == graine && (val != NULL)) *val = element->value; if( element->value ==-1) *val = 0; // 0 is emulated with -1 return true; } bool OAHash::has_key(key_type graine) { return get(graine,NULL); } // call start_iterator to reinit the iterator, then do a while(next_iterator()) {..} to traverse every cell void OAHash::start_iterator() { iterator = data-1; } // returns true as long as the iterator contains a valid cell bool OAHash::next_iterator() { while (1) { iterator++; if (iterator == data+hash_size) return false; if (iterator->value != 0) break; } return true; } float OAHash::load_factor() { return (float)nb_inserted_keys/(float)hash_size; } uint64_t OAHash::memory_usage() { return hash_size* sizeof(element_pair); // in bits } void OAHash::printstat() { fprintf(stderr,"\n----------------------Stat OA Hash Table ---------------------\n"); fprintf(stderr,"max elements: %lld, memory usage: %lld\n",(long long)hash_size,(long long)memory_usage()); fprintf(stderr,"load factor: %.2f\n",load_factor()); } discoSnp/minia/README0000644000000000000000000000064412166477050013327 0ustar rootroottype `make` then `./minia` for usage. short manual: ./manual/manual.pdf we have set up a Q&A website, see the Support section in http://minia.genouest.org to contact an author directly: rayan.chikhi@ens-cachan.org if you read the source code, disregard any code where (order > 0). [internal information] list of projects which import minia as svn:external: dsk minia-graph ultimategf kissnp2 mapsembler2 kmergenie discoSnp/minia/lut.h0000644000000000000000000000376212062133074013416 0ustar rootroot#ifndef CODE_H #define CODE_H //look up table conversion (with A,C,T,G <--> 0,1,2,3) //complement of one NT const unsigned char comp_NT[4] = { 2,3,0,1 }; //reverse complement of 4NT, ie one byte const unsigned char revcomp_4NT[256] = { 0xaa, 0xea, 0x2a, 0x6a, 0xba, 0xfa, 0x3a, 0x7a, 0x8a, 0xca, 0xa, 0x4a, 0x9a, 0xda, 0x1a, 0x5a, 0xae, 0xee, 0x2e, 0x6e, 0xbe, 0xfe, 0x3e, 0x7e, 0x8e, 0xce, 0xe, 0x4e, 0x9e, 0xde, 0x1e, 0x5e, 0xa2, 0xe2, 0x22, 0x62, 0xb2, 0xf2, 0x32, 0x72, 0x82, 0xc2, 0x2, 0x42, 0x92, 0xd2, 0x12, 0x52, 0xa6, 0xe6, 0x26, 0x66, 0xb6, 0xf6, 0x36, 0x76, 0x86, 0xc6, 0x6, 0x46, 0x96, 0xd6, 0x16, 0x56, 0xab, 0xeb, 0x2b, 0x6b, 0xbb, 0xfb, 0x3b, 0x7b, 0x8b, 0xcb, 0xb, 0x4b, 0x9b, 0xdb, 0x1b, 0x5b, 0xaf, 0xef, 0x2f, 0x6f, 0xbf, 0xff, 0x3f, 0x7f, 0x8f, 0xcf, 0xf, 0x4f, 0x9f, 0xdf, 0x1f, 0x5f, 0xa3, 0xe3, 0x23, 0x63, 0xb3, 0xf3, 0x33, 0x73, 0x83, 0xc3, 0x3, 0x43, 0x93, 0xd3, 0x13, 0x53, 0xa7, 0xe7, 0x27, 0x67, 0xb7, 0xf7, 0x37, 0x77, 0x87, 0xc7, 0x7, 0x47, 0x97, 0xd7, 0x17, 0x57, 0xa8, 0xe8, 0x28, 0x68, 0xb8, 0xf8, 0x38, 0x78, 0x88, 0xc8, 0x8, 0x48, 0x98, 0xd8, 0x18, 0x58, 0xac, 0xec, 0x2c, 0x6c, 0xbc, 0xfc, 0x3c, 0x7c, 0x8c, 0xcc, 0xc, 0x4c, 0x9c, 0xdc, 0x1c, 0x5c, 0xa0, 0xe0, 0x20, 0x60, 0xb0, 0xf0, 0x30, 0x70, 0x80, 0xc0, 0x0, 0x40, 0x90, 0xd0, 0x10, 0x50, 0xa4, 0xe4, 0x24, 0x64, 0xb4, 0xf4, 0x34, 0x74, 0x84, 0xc4, 0x4, 0x44, 0x94, 0xd4, 0x14, 0x54, 0xa9, 0xe9, 0x29, 0x69, 0xb9, 0xf9, 0x39, 0x79, 0x89, 0xc9, 0x9, 0x49, 0x99, 0xd9, 0x19, 0x59, 0xad, 0xed, 0x2d, 0x6d, 0xbd, 0xfd, 0x3d, 0x7d, 0x8d, 0xcd, 0xd, 0x4d, 0x9d, 0xdd, 0x1d, 0x5d, 0xa1, 0xe1, 0x21, 0x61, 0xb1, 0xf1, 0x31, 0x71, 0x81, 0xc1, 0x1, 0x41, 0x91, 0xd1, 0x11, 0x51, 0xa5, 0xe5, 0x25, 0x65, 0xb5, 0xf5, 0x35, 0x75, 0x85, 0xc5, 0x5, 0x45, 0x95, 0xd5, 0x15, 0x55 }; #endif discoSnp/minia/LinearCounter.cpp0000644000000000000000000000260112122310524015700 0ustar rootroot#include // for max #include "LinearCounter.h" using namespace std; // for max // counter the number of distinct kmers // implements a linear counter following [1] K. Whang, B. T. Vander-Zaden, H.M. Taylor. A Liner-Time Probabilistic Counting Algorithm for Database Applications // an easier presentation is there: http://highlyscalable.wordpress.com/2012/05/01/probabilistic-structures-web-analytics-data-mining/ // here, it's implements as a wrapper around a special Bloom LinearCounter::LinearCounter(long size) : desired_size(size) { int bloom_nbits = max( (int)ceilf(log2f(size)), 1); bloom = new Bloom(bloom_nbits); bloom->set_number_of_hash_func(1); bloom_size = 1L << bloom_nbits; } void LinearCounter::add(bloom_elem kmer) { bloom->add(kmer); } int LinearCounter::contains(bloom_elem kmer) { // dummy, because bloom_pass_reads wants this method to be exposed return 0; } long LinearCounter::count() { long weight = bloom->weight(); //printf("linear counter load factor: %0.2f\n",(1.0*weight/bloom_size)); return (long) ( (-1.0*bloom_size) * logf( (1.0*bloom_size - weight) / bloom_size ) ); // linear counter cardinality estimation } bool LinearCounter::is_accurate() { long weight = bloom->weight(); float load_factor = (1.0*weight/bloom_size); return load_factor < 0.99; } LinearCounter::~LinearCounter() { delete bloom; } discoSnp/minia/Set.cpp0000644000000000000000000001417612364215742013711 0ustar rootroot#include "Set.h" int ListSet::bits_per_element = sizeof(set_elem)*8; ListSet::ListSet(uint64_t taille_approx) { liste.reserve(taille_approx); } ListSet::ListSet() { } void ListSet::insert(set_elem elem) { liste.push_back(elem); } void ListSet::finalize() { sort(liste.begin(), liste.end()); } bool ListSet::contains(set_elem elem) { return binary_search(liste.begin(), liste.end(), elem); } //Raluca bool ListSet::containsNotBinary(set_elem elem) { int i; for (i=0; i)*8; HashSet::HashSet(uint64_t taille_approx) { int NBITS_HT = max( (int)ceilf(log2f(taille_approx)) , 1); hash = new Hash16(NBITS_HT); } void HashSet::insert(set_elem elem) { hash->insert(elem,1); // dummy value } void HashSet::finalize() { // NOP } bool HashSet::contains(set_elem elem) { return hash->has_key(elem); } //-------------- // emulates a hash table with two lists // benefits: lower memory usage // but logarithmic acess instead of constant void AssocSet::finalize() { sort(liste.begin(), liste.end()); liste_value.assign(liste.size(),0); } int AssocSet::get( set_elem elem, set_value_t * val) { vector::iterator it; it = lower_bound(liste.begin(), liste.end(),elem); if (it == liste.end() || elem != *it) return 0; size_t rank = it - liste.begin(); *val = liste_value[rank]; return 1; } AssocSet::AssocSet() { } //return -1 if elem is not in the set int AssocSet::set(set_elem elem, set_value_t val) { vector::iterator it; it = lower_bound(liste.begin(), liste.end(),elem); if (it == liste.end() ||elem != *it) return 0; size_t rank = it - liste.begin(); liste_value[rank]=val; return 1; } void AssocSet::start_iterator() { iterator = liste.begin()-1; } bool AssocSet::next_iterator() { iterator++; if (iterator==liste.end()) return false; return true; } void AssocSet::print_total_size() { printf("Assoc set size: %li\n",liste.size()); printf("Assoc set capacity: listekmer %li liste val%li\n",liste.capacity(),liste_value.capacity()); printf("%li *%li + %li* %li = %li MB \n",liste.capacity(),sizeof(set_elem),liste_value.capacity(),sizeof(set_value_t), (liste.capacity()*sizeof(set_elem)+liste_value.capacity()*sizeof(set_value_t))/1024/1024 ); } void AssocSet::clear() { liste_value.assign(liste_value.size(),0); // liste_value.clear(); } //Raluca //-------------- // emulates a hash table with two lists for paired reads (elements=branching kmers in the second read file, values=pairs of corresponding kmers in the first read file + next nucleotide in the second read file) void copy_nt_kmer (nt_kmer_t from, nt_kmer_t* to){ to->nt = from.nt; to->prev_kmer = from.prev_kmer; } void copy_pair_nt_kmer (pair_nt_kmer_t from, pair_nt_kmer_t* to){ copy_nt_kmer(from.nk1, &(to->nk1)); copy_nt_kmer(from.nk2, &(to->nk2)); } void AssocPairedSet::finalize() { sort(liste.begin(), liste.end()); //liste_value.assign(liste.size(),0); liste_value.reserve(liste.size()); // printf("finalize %i elems \n",liste_value.size()); liste_value.resize(liste.size()); int i; for (i=0; i::iterator it; it = lower_bound(liste.begin(), liste.end(),elem); if (it == liste.end() || elem != *it) return 0; size_t rank = it - liste.begin(); copy_pair_nt_kmer(liste_value[rank], val); return 1; } AssocPairedSet::AssocPairedSet() { } //return -1 if elem is not in the set int AssocPairedSet::set(set_elem elem, pair_nt_kmer_t val) { vector::iterator it; it = lower_bound(liste.begin(), liste.end(),elem); if (it == liste.end() ||elem != *it) return 0; size_t rank = it - liste.begin(); copy_pair_nt_kmer(val, &liste_value[rank]); return 1; } void AssocPairedSet::start_iterator() { iterator = liste.begin()-1; } bool AssocPairedSet::next_iterator() { iterator++; if (iterator==liste.end()) return false; return true; } void AssocPairedSet::print() { int i; char seq[100]; printf("print %lu elems \n",liste.size()); for (i=0; irewind_all(); kmer_type kmer; while (branches->read_element(&kmer)) liste.push_back(kmer); printf("done loaded branching kmers in AssocPairedSet \n"); } void AssocPairedSet::dump(char * filename) { FILE *file_data; file_data = fopen(filename,"wb"); fwrite(&liste_value[0], sizeof(pair_nt_kmer_t), liste_value.size(), file_data); //1+ printf("liste_value dumped \n"); } void AssocPairedSet::load(char * filename) { FILE *file_data; file_data = fopen(filename,"rb"); printf("loading assoc paired kmer index from file\n"); liste_value.reserve(liste.size()); liste_value.resize(liste.size()); fread(&liste_value[0], sizeof(pair_nt_kmer_t), liste_value.size(), file_data); printf("assoc paired loaded\n"); } void AssocPairedSet::print_total_size() { printf("Assoc paired set size: %li\n",liste.size()); printf("Assoc paired set capacity: listekmer %li liste val%li\n",liste.capacity(),liste_value.capacity()); printf("%li *%li + %li* %li = %li MB \n",liste.capacity(),sizeof(set_elem),liste_value.capacity(),sizeof(set_value_t), (liste.capacity()*sizeof(set_elem)+liste_value.capacity()*sizeof(set_value_t))/1024/1024 ); } discoSnp/minia/Traversal.h0000644000000000000000000001535312304050544014553 0ustar rootroot#ifndef Traversal_h #define Traversal_h #include #include #include #include // only for pow() #include "Kmer.h" #include "Terminator.h" #include "Bloom.h" #include "Set.h" #include "Utils.h" // for needleman_wunch using namespace std; // types using in advanced traversal functions struct kmer_strand_nt { kmer_type kmer; int strand; int nt; kmer_strand_nt(kmer_type kmer, int strand, int nt) : kmer(kmer), strand(strand), nt(nt) {} bool operator<(const kmer_strand_nt &other) const { // need to define a strict weak ordering if (kmer != other.kmer) return (kmer < other.kmer); if (strand != other.strand) return (strand < other.strand); return (nt < other.nt); } }; // in traversals, a node is just a tuple (kmer, strand, nt initially chosen to reach that node) // so it just happens that it's the same type as kmer_strand_nt typedef kmer_strand_nt node; typedef queue queue_nodes; // some stats struct TraversalStats { long ended_traversals; long couldnt_find_all_consensuses; long couldnt_validate_consensuses; long couldnt_traverse_bubble_breadth; long couldnt_traverse_bubble_depth; long couldnt_because_marked_kmer; long couldnt_inbranching_depth; long couldnt_inbranching_breadth; long couldnt_inbranching_other; long couldnt_find_extension; }; // semi-abstract class. implements traverse but not avance class Traversal{ protected: Bloom *bloom; Set *debloom; Terminator *terminator; int maxlen; int max_depth; int max_breadth; virtual char avance(kmer_type graine, int current_strand, bool first_extension, char * newNT, kmer_type previous_kmer) = 0; void mark_extensions(set *extensions_to_mark); public: Traversal(Bloom *given_bloom, Set *given_debloom, Terminator *given_terminator) : bloom(given_bloom), debloom(given_debloom), terminator(given_terminator), maxlen(1000000),max_depth(500),max_breadth(20), stats(TraversalStats()), final_stats(TraversalStats()) { } ~Traversal(); void set_maxlen(int); void set_max_depth(int); void set_max_breadth(int); int traverse(kmer_type starting_kmer, char* resulting_sequence, int current_strand, kmer_type previous_kmer = 0); // n-order extension function, to ignore tips int extensions(kmer_type kmer, int strand, int &nt); // useful atomic avance functions int simple_paths_avance(kmer_type graine, int current_strand, bool first_extension, char * newNT); char random_unmarked_avance(kmer_type graine, int current_strand, bool first_extension, char * newNT); // high level starting kmer selection bool get_new_starting_node(kmer_type branching_kmer, kmer_type &starting_kmer); bool get_new_starting_node_improved(kmer_type branching_kmer, kmer_type &starting_kmer); bool find_starting_kmer_inside_simple_path(kmer_type kmer, kmer_type &starting_kmer); // now unused vector > bubbles_positions; // record the start/end positions of traversed bubbles (only from the latest traverse() call) TraversalStats final_stats, stats; void commit_stats(); // save current stats into final stats void revert_stats(); // discard changes in stats (because discarded contig) }; // n-order extension function, to ignore tips extern int order; // declared and initialized in assemb.cpp int traversal_extensions(kmer_type kmer, int strand, int &nt, Bloom *bloom_solid_kmers, Set *debloom); bool is_tip(kmer_type kmer, Bloom *bloom_solid_kmers, Set *debloom); class RandomBranchingTraversal: public Traversal { protected: char avance(kmer_type graine, int current_strand, bool first_extension, char * newNT, kmer_type previous_kmer); public: RandomBranchingTraversal(Bloom *given_bloom, Set *given_debloom, Terminator *given_terminator) : Traversal(given_bloom,given_debloom,given_terminator) {} }; class SimplePathsTraversal: public Traversal { char avance(kmer_type graine, int current_strand, bool first_extension, char * newNT, kmer_type previous_kmer); public: SimplePathsTraversal(Bloom *given_bloom, Set *given_debloom, Terminator *given_terminator) : Traversal(given_bloom,given_debloom,given_terminator) {} }; // auxiliary class that is used by MonumentTraversal and deblooming class Frontline { kmer_type starting_kmer; int starting_strand; Bloom *bloom; Set *debloom; Terminator *terminator; set *all_involved_extensions; kmer_type previous_kmer; queue_nodes frontline; // set already_frontlined; set already_frontlined; // making it simpler now public: bool check_in_branching; int depth; Frontline(kmer_type starting_kmer, int starting_strand, Bloom *bloom, Set *debloom, Terminator *terminator, set *all_involved_extensions, kmer_type previous_kmer = 0, bool check_in_branching = true); bool go_next_depth(); int size(); node front(); bool check_inbranching(kmer_type from_kmer, int current_strand); enum reason { NONE, ALREADY_FRONTLINED, IN_BRANCHING_DEPTH, IN_BRANCHING_BREADTH, IN_BRANCHING_OTHER, MARKED }; reason stopped_reason; }; class MonumentTraversal: public Traversal { //int max_length_deadend = 150; // replaced by sizeKmer+1 static const int consensuses_identity = 90; // traversing bubble if paths are all pair-wise identical by > 90% char avance(kmer_type graine, int current_strand, bool first_extension, char * newNT, kmer_type previous_kmer); set all_consensuses_between(kmer_type start_kmer, int start_strand, kmer_type end_kmer, int end_strand, int traversal_depth, set used_kmers, string current_consensus, bool &success); set all_consensuses_between(kmer_type start_kmer, int start_strand, kmer_type end_kmer, int end_node, int traversal_depth, bool &success); int find_end_of_branching(kmer_type starting_kmer, int starting_strand, kmer_type &end_kmer, int &end_strand, kmer_type previous_kmer, set *all_involved_extensions); bool explore_branching(kmer_type start_kmer, int start_strand, char *consensus, int &consensus_length, kmer_type previous_kmer); bool explore_branching(kmer_type start_kmer, int start_strand, char *consensus, int &consensus_length, kmer_type previous_kmer, set *all_involved_extensions); bool validate_consensuses(set consensuses, char *result, int &result_length); public: static bool all_consensuses_almost_identical(set consensuses); MonumentTraversal(Bloom *given_bloom, Set *given_debloom, Terminator *given_terminator) : Traversal(given_bloom,given_debloom,given_terminator) {} bool find_starting_kmer(kmer_type kmer, kmer_type &starting_kmer); }; #endif discoSnp/minia/manual/0000755000000000000000000000000012304050544013705 5ustar rootrootdiscoSnp/minia/manual/manual.tex0000644000000000000000000001307312304050544015710 0ustar rootroot\documentclass[a4paper]{article} \usepackage{fancyvrb} \usepackage{pdfpages} \begin{document} \newcommand\vitem[1][]{\SaveVerb[% to use verb in description aftersave={\item[\textnormal{\UseVerb[#1]{vsave}}]}]{vsave}} \title{\Huge \texttt{Minia} --- Short manual} \author{R. Chikhi \& G. Rizk\\ {\small{rayan.chikhi@ens-cachan.org}}} \maketitle \begin{abstract} \noindent {\normalsize Minia is a software for ultra-low memory DNA sequence assembly. It takes as input a set of short genomic sequences (typically, data produced by the Illumina DNA sequencer). Its output is a set of contigs (assembled sequences), forming an approximation of the expected genome. Minia is based on a succinct representation of the de Bruijn graph. The computational resources required to run Minia are significantly lower than that of other assemblers.} \end{abstract} \tableofcontents \section{Installation} To install Minia, just type \verb+make+ in the Minia folder. Minia has been tested on Linux and MacOS systems. To run Minia, type \verb+./minia+. \section{Parameters} The usage is:\\ \verb+./minia [input_file] [kmer_size] [min_abundance] [estimated_genome_size] [prefix]+\\ An example command line is:\\ \verb+./minia reads.fastq 31 3 100000000 minia_assembly_k31_m3+\\ All the parameters need to be specified, in the following order: \begin{enumerate} \item \verb+input_file+ -- the input file \item \verb+kmer_size+ -- k-mer length \item \verb+min_abundance+ -- filters out k-mers seen less than the specified number of times \item \verb+estimated_genome_size+ -- rough estimation of the size of the genome to assemble, in base pairs. \item \verb+prefix+ -- any prefix string to store unique temporary files for this assembly \end{enumerate} Minia now uses the Cascading Bloom filters improvement (http://arxiv.org/abs/1302.7278) by default, thanks to Gustavo Sacomoto for the implementation in Minia. Launch Minia with the \verb!--original! option to revert to the original data structure. \section{Explanation of parameters} \begin{description} \vitem+kmer_size+ The $k$-mer length is the length of the nodes in the de Bruijn graph. It strongly depends on the input dataset. A typical value to try for short Illumina reads (read length above $50$) is 27. For longer Illumina reads ($\approx 100$ bp) with sufficient coverage ($>$ 40x), we had good results with $k=43$. \vitem+min_abundance+ The \verb+min_abundance+ is used to remove erroneous, low-abundance $k$-mers. This parameter also strongly depends on the dataset. It corresponds to the smallest amount of times a correct $k$-mer appears in the reads. A typical value is $3$. Setting it to $1$ is not recommended\footnote{as no erroneous $k$-mer will be discarded, which will likely result in a very large memory usage}. If the dataset has high coverage, try larger values. \vitem+estimated_genome_size+ The estimated genome size parameter (in base pairs) only controls the memory usage during the first phase of Minia (graph construction). \emph{It has no impact on the assembly}. \vitem+prefix+ The \verb+prefix+ parameter is any arbitrary file name prefix, for example, \verb+test_assembly+. \end{description} \section{Input} \begin{description} \item \emph{FASTA/FASTQ} Minia assembles any type of Illumina reads, given in the FASTA or FASTQ format. Paired or mate-pairs reads are OK, but keep in mind that Minia discards pairing information. \item \emph{Multipe Files} Minia can assemble multiple input files. Just create a text file containing the list of read files, one file name per line, and pass this list as the first parameter of Minia (instead of a FASTA/FASTQ file). Therefore the parameter \verb+input_file+ can be either (i) the read file itself (FASTA/FASTQ/compressed), or (ii) a file containing a list of file names. \item \emph{line format} In FASTA files, each read can be split into multiple lines, whereas in FASTQ, each read sequence must be in a single line. \item \emph{gzip compression} Minia can direclty read files compressed with gzip. Compressed files should end with '.gz'. Input files of different types can be mixed (i.e. gzipped or not, in FASTA or FASTQ) \end{description} \section{Output} The output of Minia is a set of contigs in the FASTA format, in the file \verb+[prefix].contigs.fa+. \section{Memory usage} We estimate that the memory usage of Minia is roughly $2$ GB of RAM per gigabases in the target genome to assemble. It is independent of the coverage of the input dataset, provided that the \verb!min_abundance! parameter is correctly set. For example, a human genome was assembled in $5.7$ GB of RAM. This was using the original data structure; the current implementation relies on Cascading Bloom filters and should use $\approx 1-2$ GB less memory. A better estimation of the memory usage can be found in the Appendix. \section{Disk usage} Minia writes large temporary files during the k-mer counting phase. These files are written in the working directory when you launched Minia. For better performance, run Minia on a local hard drive. \section{Larger $k$-mer lengths} Minia supports arbitrary large $k$-mer lengths. To compile Minia for $k$-mer lengths up to, say, 100, type: \begin{verbatim} make clean && make k=100 \end{verbatim} \section{Appendixes} The rest of this manual describes the data structure used by Minia. The first text is from an original research article published at WABI 2012. The second text is an improvement made and implemented in Minia by other authors, published at WABI 2013. \includepdf[pages=-]{../paper/wabi12.pdf} \includepdf[pages=-]{../paper/cascading-wabi13.pdf} \end{document} discoSnp/minia/LargeInt.h0000644000000000000000000000234512062133074014313 0ustar rootroot/* * arbitrary-precision integer library * very limited: only does what minia needs (but not what minia deserves) */ #ifndef LargeInt_h #define LargeInt_h #include #include template class LargeInt { public: uint64_t array[precision]; LargeInt(const uint64_t &); LargeInt(); // overloading LargeInt operator+(const LargeInt &) const; LargeInt operator-(const LargeInt &) const; LargeInt operator*(const int &) const; LargeInt operator/(const uint32_t &) const; uint32_t operator%(const uint32_t &) const; LargeInt operator^(const LargeInt &) const; LargeInt operator&(const LargeInt &) const; LargeInt operator~() const; LargeInt operator<<(const int &) const; LargeInt operator>>(const int &) const; bool operator!=(const LargeInt &) const; bool operator==(const LargeInt &) const; bool operator<(const LargeInt &) const; bool operator<=(const LargeInt &) const; // custom uint64_t toInt() const; #ifdef _LP64 __uint128_t toInt128() const; #endif // c++ fun fact: // "const" will ban the function from being anything which can attempt to alter any member variables in the object. }; #endif discoSnp/minia/Hash16.cpp0000644000000000000000000002354312070777506014213 0ustar rootroot// // Hash16.cpp // // Created by Guillaume Rizk on 19/02/12. // #include #include #include #include // for max #include "Hash16.h" using namespace::std; Hash16::Hash16() { //empty default constructor nb_elem = 0; } //tai is 2^tai_Hash16 //max is 32 Hash16::Hash16(int tai_Hash16) { if(tai_Hash16>32){ fprintf(stderr,"max size for this hash is 2^32, resuming with max value \n"); tai_Hash16=32; } nb_elem = 0; tai = (1LL << tai_Hash16); mask = tai-1 ; datah = (cell_ptr_t *) malloc( tai * sizeof(cell_ptr_t)); //create hashtable memset(datah,0, tai * sizeof(cell_ptr_t)); // fprintf(stderr,"sizeof hashtable %lli MB\n",tai * sizeof(cell_ptr_t)/1024/1024); storage = new Pool; } Hash16::~Hash16() { free(datah); delete storage; } //if graine already here, overwrite old value void Hash16::insert(hash_elem graine, int value) { unsigned int clef ; cell * cell_ptr, *newcell_ptr; cell_ptr_t newcell_internal_ptr; clef = (unsigned int) (hashcode(graine) & mask); cell_ptr = storage->internal_ptr_to_cell_pointer(datah[clef]); while(cell_ptr != NULL && cell_ptr->graine != graine) { cell_ptr = storage->internal_ptr_to_cell_pointer(cell_ptr->suiv); } if (cell_ptr==NULL) //graine non trouvee , insertion au debut { newcell_internal_ptr = storage->allocate_cell(); newcell_ptr = storage->internal_ptr_to_cell_pointer(newcell_internal_ptr); newcell_ptr->val=value; newcell_ptr->graine=graine; newcell_ptr->suiv=datah[clef]; datah[clef] = newcell_internal_ptr; nb_elem++; } else cell_ptr->val=value; // graine trouvee } //add graine, and count how many times it was added //return 1 if graine first time seen int Hash16::add(hash_elem graine) { unsigned int clef ; cell * cell_ptr, *newcell_ptr; cell_ptr_t newcell_internal_ptr; clef = (unsigned int) hashcode(graine) & mask; cell_ptr = storage->internal_ptr_to_cell_pointer(datah[clef]); while(cell_ptr != NULL && cell_ptr->graine != graine) { cell_ptr = storage->internal_ptr_to_cell_pointer(cell_ptr->suiv); } if (cell_ptr==NULL) //graine non trouvee , insertion au debut { newcell_internal_ptr = storage->allocate_cell(); newcell_ptr = storage->internal_ptr_to_cell_pointer(newcell_internal_ptr); newcell_ptr->val=1; newcell_ptr->graine=graine; newcell_ptr->suiv=datah[clef]; datah[clef] = newcell_internal_ptr; nb_elem++; return 1; } else { (cell_ptr->val)++; // graine trouvee return 0; } } int Hash16::has_key( hash_elem graine) { return get(graine,NULL); } int Hash16::get( hash_elem graine, int * val) { unsigned int clef ; cell * cell_ptr; clef = (unsigned int) hashcode(graine) & mask; cell_ptr = storage->internal_ptr_to_cell_pointer(datah[clef]); while(cell_ptr != NULL && cell_ptr->graine != graine) { cell_ptr = storage->internal_ptr_to_cell_pointer(cell_ptr->suiv); } if (cell_ptr==NULL) { return 0; } else { if (val != NULL) *val = cell_ptr->val; return 1; } } int Hash16::remove( hash_elem graine, int * val) { unsigned int clef ; cell* cell_ptr; cell_ptr_t * cellprec_ptr; clef = (unsigned int) hashcode(graine) & mask; cell_ptr = storage->internal_ptr_to_cell_pointer(datah[clef]); cellprec_ptr = & (datah[clef]); while(cell_ptr != NULL && cell_ptr->graine != graine) { cellprec_ptr = & (cell_ptr->suiv); cell_ptr = storage->internal_ptr_to_cell_pointer(cell_ptr->suiv); } if (cell_ptr==NULL) { if (val != NULL) *val = 0; return 0; } else { if (val != NULL) *val = cell_ptr->val; //delete the cell : *cellprec_ptr = cell_ptr->suiv ; return 1; } } // (note: Hash16 uses 32 bits hashes) #ifdef _largeint inline uint64_t Hash16::hashcode(LargeInt elem) { // hash = XOR_of_series[hash(i-th chunk iof 64 bits)] uint64_t result = 0, chunk, mask = ~0; LargeInt intermediate = elem; int i; for (i=0;i> 64; result ^= hashcode(chunk); } return result; } #endif #ifdef _ttmath inline uint64_t Hash16::hashcode(ttmath::UInt elem) { // hash = XOR_of_series[hash(i-th chunk iof 64 bits)] uint64_t result = 0, to_hash; ttmath::UInt intermediate = elem; uint32_t mask=~0, chunk; int i; for (i=0;i>= 32; (intermediate & mask).ToInt(chunk); to_hash |= ((uint64_t)chunk) << 32 ; intermediate >>= 32; result ^= hashcode(to_hash); } return result; } #endif #ifdef _LP64 inline unsigned int Hash16::hashcode( __uint128_t elem ) { // hashcode(uint128) = ( hashcode(upper 64 bits) xor hashcode(lower 64 bits)) & mask return (hashcode((uint64_t)(elem>>64)) ^ hashcode((uint64_t)(elem&((((__uint128_t)1)<<64)-1)))); } #endif inline unsigned int Hash16::hashcode( uint64_t elem ) { uint64_t code = elem; code = code ^ (code >> 14); //supp code = (~code) + (code << 18); code = code ^ (code >> 31); code = code * 21; code = code ^ (code >> 11); code = code + (code << 6); code = code ^ (code >> 22); return ((unsigned int) code ); } void Hash16::empty_all() { storage->empty_all(); nb_elem=0; memset(datah,0, tai * sizeof(cell_ptr_t)); } // call start_iterator to reinit the iterator, then do a while(next_iterator()) {..} to traverse every cell void Hash16::start_iterator() { iterator.cell_index = -1; iterator.cell_ptr = NULL; iterator.cell_internal_ptr = 0; } // returns true as long as the iterator contains a valid cell bool Hash16::next_iterator() { while (1) { // if the current cell is empty, search datah for the next non-empty one if (iterator.cell_internal_ptr == 0) { while (iterator.cell_internal_ptr == 0) { iterator.cell_index++; if ((unsigned int )iterator.cell_index==tai) return false; iterator.cell_internal_ptr = datah[iterator.cell_index]; } } else // if the current cell is non-empty, go to the next cell { iterator.cell_internal_ptr = iterator.cell_ptr->suiv; if (iterator.cell_internal_ptr == 0) continue; // if the next cell is empty, proceed to the "current cell is empty" case } // at this point we either gave up (return false) or have a non-empty cell iterator.cell_ptr = storage->internal_ptr_to_cell_pointer(iterator.cell_internal_ptr); break; } return true; } //file should already be opened for writing void Hash16::dump(FILE * count_file) { cell * cell_ptr; start_iterator(); while (next_iterator()) { cell_ptr = iterator.cell_ptr; fwrite(&cell_ptr->graine, sizeof(cell_ptr->graine), 1, count_file); fwrite(&cell_ptr->val, sizeof(cell_ptr->val), 1, count_file); } } int64_t Hash16::getsolids(Bloom* bloom_to_insert, BinaryBank* solids, int nks) { cell * cell_ptr; start_iterator(); int64_t nso=0; while (next_iterator()) { cell_ptr = iterator.cell_ptr; if(cell_ptr->val>=nks) { nso++; solids->write_element(&cell_ptr->graine); if (bloom_to_insert != NULL) bloom_to_insert->add(cell_ptr->graine); } } return nso; } //print stats of elem having their value >=nks int Hash16::printstat(int nks, bool print_collisions) { fprintf(stderr,"\n----------------------Stat Hash Table ---------------------\n"); long long NbKmersolid = 0; int ma=0,mi=99999,cpt=0; uint64_t i; int maxclef=0; cell * cell_ptr; cell_ptr_t cell_internal_ptr; int distrib_colli[512]; long long nb_cell=0; for (i=0;i<512;i++){distrib_colli[i]=0;} for (i=0; iinternal_ptr_to_cell_pointer(cell_internal_ptr); cpt=0; while(cell_internal_ptr!=0 ) { nb_cell++; cpt++; if(cell_ptr->val >= nks) NbKmersolid++; cell_internal_ptr = cell_ptr->suiv; cell_ptr = storage->internal_ptr_to_cell_pointer(cell_internal_ptr); } if(cpt>ma) {ma=cpt;maxclef=i;} ma = max(ma,cpt); mi = min(mi,cpt); distrib_colli[cpt]++; } fprintf(stderr,"taille hashtable %llu\n",(unsigned long long)tai); fprintf(stderr,"kmer solid/total : %lli / %lli %g %% (%lli elem < %i) \n",(long long)NbKmersolid, (long long)nb_cell, 100*(float)NbKmersolid /nb_cell,(long long)(nb_cell-NbKmersolid),nks); fprintf(stderr,"max collisions = %i pour clef %i nb_elem total %lli reparties sur %llu clefs %g elem/clef \n",ma,maxclef,nb_cell,(unsigned long long)(tai-distrib_colli[0]), (float)nb_cell/(float)(tai-distrib_colli[0])); if(print_collisions) for (i=0; i<10; i++) { fprintf(stderr," %9llucollisions : %9i \n",(unsigned long long)i,(distrib_colli[i])); } return NbKmersolid; } discoSnp/minia/rvalues.h0000644000000000000000000000573212157603772014306 0ustar rootrootstatic const double rvalues[129][2] = { { 0.00000, 5.29625 }, { 0.00000, 0.00000 }, { 0.00000, 0.00000 }, { 0.00000, 0.00000 }, { 0.00000, 0.00000 }, { 5.64856, 5.49117 }, { 5.85164, 5.52333 }, { 6.02772, 5.55385 }, { 6.18398, 5.58291 }, { 6.32492, 5.61065 }, { 6.45362, 5.63721 }, { 6.57225, 5.66268 }, { 6.68244, 5.68717 }, { 6.78544, 5.71075 }, { 6.88221, 5.73350 }, { 6.97353, 5.75548 }, { 7.06004, 5.77674 }, { 7.14227, 5.79733 }, { 7.22066, 5.81730 }, { 7.29558, 5.83669 }, { 7.36734, 5.85553 }, { 7.43623, 5.87386 }, { 7.50248, 5.89171 }, { 7.56630, 5.90910 }, { 7.62788, 5.92605 }, { 7.68737, 5.94260 }, { 7.74494, 5.95876 }, { 7.80069, 5.97455 }, { 7.85477, 5.98999 }, { 7.90726, 6.00510 }, { 7.95826, 6.01989 }, { 8.00786, 6.03437 }, { 8.05615, 6.04856 }, { 8.10319, 6.06247 }, { 8.14904, 6.07611 }, { 8.19378, 6.08950 }, { 8.23745, 6.10264 }, { 8.28012, 6.11555 }, { 8.32181, 6.12822 }, { 8.36260, 6.14068 }, { 8.40250, 6.15293 }, { 8.44157, 6.16497 }, { 8.47983, 6.17682 }, { 8.51733, 6.18848 }, { 8.55409, 6.19995 }, { 8.59015, 6.21125 }, { 8.62553, 6.22238 }, { 8.66025, 6.23334 }, { 8.69435, 6.24413 }, { 8.72784, 6.25478 }, { 8.76075, 6.26527 }, { 8.79310, 6.27562 }, { 8.82490, 6.28582 }, { 8.85619, 6.29589 }, { 8.88697, 6.30582 }, { 8.91725, 6.31562 }, { 8.94707, 6.32530 }, { 8.97643, 6.33485 }, { 9.00534, 6.34428 }, { 9.03383, 6.35360 }, { 9.06189, 6.36280 }, { 9.08956, 6.37189 }, { 9.11683, 6.38088 }, { 9.14372, 6.38975 }, { 9.17024, 6.39853 }, { 9.19640, 6.40721 }, { 9.22221, 6.41578 }, { 9.24768, 6.42427 }, { 9.27282, 6.43265 }, { 9.29764, 6.44095 }, { 9.32214, 6.44916 }, { 9.34634, 6.45728 }, { 9.37024, 6.46532 }, { 9.39385, 6.47328 }, { 9.41717, 6.48115 }, { 9.44023, 6.48894 }, { 9.46301, 6.49666 }, { 9.48552, 6.50430 }, { 9.50778, 6.51186 }, { 9.52979, 6.51935 }, { 9.55156, 6.52677 }, { 9.57308, 6.53412 }, { 9.59437, 6.54140 }, { 9.61543, 6.54861 }, { 9.63627, 6.55576 }, { 9.65688, 6.56284 }, { 9.67729, 6.56986 }, { 9.69748, 6.57682 }, { 9.71747, 6.58371 }, { 9.73725, 6.59055 }, { 9.75684, 6.59732 }, { 9.77624, 6.60404 }, { 9.79544, 6.61070 }, { 9.81446, 6.61731 }, { 9.83330, 6.62386 }, { 9.85196, 6.63035 }, { 9.87045, 6.63680 }, { 9.88876, 6.64319 }, { 9.90691, 6.64953 }, { 9.92489, 6.65582 }, { 9.94271, 6.66206 }, { 9.96037, 6.66825 }, { 9.97787, 6.67439 }, { 9.99522, 6.68049 }, { 10.01241, 6.68654 }, { 10.02946, 6.69254 }, { 10.04637, 6.69850 }, { 10.06313, 6.70441 }, { 10.07975, 6.71029 }, { 10.09623, 6.71611 }, { 10.11258, 6.72190 }, { 10.12879, 6.72764 }, { 10.14488, 6.73335 }, { 10.16083, 6.73901 }, { 10.17665, 6.74463 }, { 10.19235, 6.75022 }, { 10.20793, 6.75577 }, { 10.22339, 6.76127 }, { 10.23873, 6.76674 }, { 10.25394, 6.77218 }, { 10.26905, 6.77757 }, { 10.28404, 6.78293 }, { 10.29892, 6.78826 }, { 10.31369, 6.79355 }, { 10.32835, 6.79881 }, { 10.34290, 6.80403 }, { 10.35735, 6.80922 }, { 10.37169, 6.81437 }, { 10.38593, 6.81950 } }; discoSnp/minia/ttmath/0000755000000000000000000000000012232437326013740 5ustar rootrootdiscoSnp/minia/ttmath/ttmathmisc.h0000644000000000000000000001062512062133074016264 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2010, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathmisc #define headerfilettmathmisc /*! \file ttmathmisc.h \brief some helpful functions */ #include namespace ttmath { /*! some helpful functions */ class Misc { public: /* * * AssignString(result, str) * result = str * */ /*! result = str */ static void AssignString(std::string & result, const char * str) { result = str; } #ifndef TTMATH_DONT_USE_WCHAR /*! result = str */ static void AssignString(std::wstring & result, const char * str) { result.clear(); for( ; *str ; ++str ) result += *str; } /*! result = str */ static void AssignString(std::wstring & result, const std::string & str) { return AssignString(result, str.c_str()); } /*! result = str */ static void AssignString(std::string & result, const wchar_t * str) { result.clear(); for( ; *str ; ++str ) result += static_cast(*str); } /*! result = str */ static void AssignString(std::string & result, const std::wstring & str) { return AssignString(result, str.c_str()); } #endif /* * * AddString(result, str) * result += str * */ /*! result += str */ static void AddString(std::string & result, const char * str) { result += str; } #ifndef TTMATH_DONT_USE_WCHAR /*! result += str */ static void AddString(std::wstring & result, const char * str) { for( ; *str ; ++str ) result += *str; } #endif /* this method omits any white characters from the string char_type is char or wchar_t */ template static void SkipWhiteCharacters(const char_type * & c) { // 13 is at the end in a DOS text file (\r\n) while( (*c==' ' ) || (*c=='\t') || (*c==13 ) || (*c=='\n') ) ++c; } /*! this static method converts one character into its value for example: 1 -> 1 8 -> 8 A -> 10 f -> 15 this method don't check whether c is correct or not */ static uint CharToDigit(uint c) { if(c>='0' && c<='9') return c-'0'; if(c>='a' && c<='z') return c-'a'+10; return c-'A'+10; } /*! this method changes a character 'c' into its value (if there can't be a correct value it returns -1) for example: c=2, base=10 -> function returns 2 c=A, base=10 -> function returns -1 c=A, base=16 -> function returns 10 */ static sint CharToDigit(uint c, uint base) { if( c>='0' && c<='9' ) c=c-'0'; else if( c>='a' && c<='z' ) c=c-'a'+10; else if( c>='A' && c<='Z' ) c=c-'A'+10; else return -1; if( c >= base ) return -1; return sint(c); } /*! this method converts a digit into a char digit should be from <0,F> (we don't have to get a base) for example: 1 -> 1 8 -> 8 10 -> A 15 -> F */ static uint DigitToChar(uint digit) { if( digit < 10 ) return digit + '0'; return digit - 10 + 'A'; } }; // struct Misc } #endif discoSnp/minia/ttmath/ttmathuint_x86.h0000644000000000000000000007174112062133074017023 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2009, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathuint_x86 #define headerfilettmathuint_x86 #ifndef TTMATH_NOASM #ifdef TTMATH_PLATFORM32 /*! \file ttmathuint_x86.h \brief template class UInt with assembler code for 32bit x86 processors this file is included at the end of ttmathuint.h */ /*! \brief a namespace for the TTMath library */ namespace ttmath { /*! returning the string represents the currect type of the library we have following types: asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) asm_gcc_32 - with asm code designed for GCC (32 bits) asm_vc_64 - with asm for VC (64 bit) asm_gcc_64 - with asm for GCC (64 bit) no_asm_32 - pure C++ version (32 bit) - without any asm code no_asm_64 - pure C++ version (64 bit) - without any asm code */ template const char * UInt::LibTypeStr() { #ifndef __GNUC__ static const char info[] = "asm_vc_32"; #endif #ifdef __GNUC__ static const char info[] = "asm_gcc_32"; #endif return info; } /*! returning the currect type of the library */ template LibTypeCode UInt::LibType() { #ifndef __GNUC__ LibTypeCode info = asm_vc_32; #endif #ifdef __GNUC__ LibTypeCode info = asm_gcc_32; #endif return info; } /*! * * basic mathematic functions * */ /*! adding ss2 to the this and adding carry if it's defined (this = this + ss2 + c) c must be zero or one (might be a bigger value than 1) function returns carry (1) (if it has been) */ template uint UInt::Add(const UInt & ss2, uint c) { uint b = value_size; uint * p1 = table; uint * p2 = const_cast(ss2.table); // we don't have to use TTMATH_REFERENCE_ASSERT here // this algorithm doesn't require it #ifndef __GNUC__ // this part might be compiled with for example visual c __asm { push eax push ebx push ecx push edx push esi mov ecx,[b] mov ebx,[p1] mov esi,[p2] xor edx,edx // edx=0 mov eax,[c] neg eax // CF=1 if rax!=0 , CF=0 if rax==0 ttmath_loop: mov eax,[esi+edx*4] adc [ebx+edx*4],eax inc edx dec ecx jnz ttmath_loop adc ecx, ecx mov [c], ecx pop esi pop edx pop ecx pop ebx pop eax } #endif #ifdef __GNUC__ uint dummy, dummy2; // this part should be compiled with gcc __asm__ __volatile__( "xorl %%edx, %%edx \n" "negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "1: \n" "movl (%%esi,%%edx,4), %%eax \n" "adcl %%eax, (%%ebx,%%edx,4) \n" "incl %%edx \n" "decl %%ecx \n" "jnz 1b \n" "adc %%ecx, %%ecx \n" : "=c" (c), "=a" (dummy), "=d" (dummy2) : "0" (b), "1" (c), "b" (p1), "S" (p2) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::Add", c) return c; } /*! adding one word (at a specific position) and returning a carry (if it has been) e.g. if we've got (value_size=3): table[0] = 10; table[1] = 30; table[2] = 5; and we call: AddInt(2,1) then it'll be: table[0] = 10; table[1] = 30 + 2; table[2] = 5; of course if there was a carry from table[2] it would be returned */ template uint UInt::AddInt(uint value, uint index) { uint b = value_size; uint * p1 = table; uint c; TTMATH_ASSERT( index < value_size ) #ifndef __GNUC__ __asm { push eax push ebx push ecx push edx mov ecx, [b] sub ecx, [index] mov edx, [index] mov ebx, [p1] mov eax, [value] ttmath_loop: add [ebx+edx*4], eax jnc ttmath_end mov eax, 1 inc edx dec ecx jnz ttmath_loop ttmath_end: setc al movzx edx, al mov [c], edx pop edx pop ecx pop ebx pop eax } #endif #ifdef __GNUC__ uint dummy, dummy2; __asm__ __volatile__( "subl %%edx, %%ecx \n" "1: \n" "addl %%eax, (%%ebx,%%edx,4) \n" "jnc 2f \n" "movl $1, %%eax \n" "incl %%edx \n" "decl %%ecx \n" "jnz 1b \n" "2: \n" "setc %%al \n" "movzx %%al, %%edx \n" : "=d" (c), "=a" (dummy), "=c" (dummy2) : "0" (index), "1" (value), "2" (b), "b" (p1) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::AddInt", c) return c; } /*! adding only two unsigned words to the existing value and these words begin on the 'index' position (it's used in the multiplication algorithm 2) index should be equal or smaller than value_size-2 (index <= value_size-2) x1 - lower word, x2 - higher word for example if we've got value_size equal 4 and: table[0] = 3 table[1] = 4 table[2] = 5 table[3] = 6 then let x1 = 10 x2 = 20 and index = 1 the result of this method will be: table[0] = 3 table[1] = 4 + x1 = 14 table[2] = 5 + x2 = 25 table[3] = 6 and no carry at the end of table[3] (of course if there was a carry in table[2](5+20) then this carry would be passed to the table[3] etc.) */ template uint UInt::AddTwoInts(uint x2, uint x1, uint index) { uint b = value_size; uint * p1 = table; uint c; TTMATH_ASSERT( index < value_size - 1 ) #ifndef __GNUC__ __asm { push eax push ebx push ecx push edx mov ecx, [b] sub ecx, [index] mov ebx, [p1] mov edx, [index] mov eax, [x1] add [ebx+edx*4], eax inc edx dec ecx mov eax, [x2] ttmath_loop: adc [ebx+edx*4], eax jnc ttmath_end mov eax, 0 inc edx dec ecx jnz ttmath_loop ttmath_end: setc al movzx edx, al mov [c], edx pop edx pop ecx pop ebx pop eax } #endif #ifdef __GNUC__ uint dummy, dummy2; __asm__ __volatile__( "subl %%edx, %%ecx \n" "addl %%esi, (%%ebx,%%edx,4) \n" "incl %%edx \n" "decl %%ecx \n" "1: \n" "adcl %%eax, (%%ebx,%%edx,4) \n" "jnc 2f \n" "mov $0, %%eax \n" "incl %%edx \n" "decl %%ecx \n" "jnz 1b \n" "2: \n" "setc %%al \n" "movzx %%al, %%eax \n" : "=a" (c), "=c" (dummy), "=d" (dummy2) : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::AddTwoInts", c) return c; } /*! this static method addes one vector to the other 'ss1' is larger in size or equal to 'ss2' ss1 points to the first (larger) vector ss2 points to the second vector ss1_size - size of the ss1 (and size of the result too) ss2_size - size of the ss2 result - is the result vector (which has size the same as ss1: ss1_size) Example: ss1_size is 5, ss2_size is 3 ss1: ss2: result (output): 5 1 5+1 4 3 4+3 2 7 2+7 6 6 9 9 of course the carry is propagated and will be returned from the last item (this method is used by the Karatsuba multiplication algorithm) */ template uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) { TTMATH_ASSERT( ss1_size >= ss2_size ) uint rest = ss1_size - ss2_size; uint c; #ifndef __GNUC__ // this part might be compiled with for example visual c __asm { pushad mov ecx, [ss2_size] xor edx, edx // edx = 0, cf = 0 mov esi, [ss1] mov ebx, [ss2] mov edi, [result] ttmath_loop: mov eax, [esi+edx*4] adc eax, [ebx+edx*4] mov [edi+edx*4], eax inc edx dec ecx jnz ttmath_loop adc ecx, ecx // ecx has the cf state mov ebx, [rest] or ebx, ebx jz ttmath_end xor ebx, ebx // ebx = 0 neg ecx // setting cf from ecx mov ecx, [rest] // ecx is != 0 ttmath_loop2: mov eax, [esi+edx*4] adc eax, ebx mov [edi+edx*4], eax inc edx dec ecx jnz ttmath_loop2 adc ecx, ecx ttmath_end: mov [c], ecx popad } #endif #ifdef __GNUC__ // this part should be compiled with gcc uint dummy1, dummy2, dummy3; __asm__ __volatile__( "push %%edx \n" "xor %%edx, %%edx \n" // edx = 0, cf = 0 "1: \n" "mov (%%esi,%%edx,4), %%eax \n" "adc (%%ebx,%%edx,4), %%eax \n" "mov %%eax, (%%edi,%%edx,4) \n" "inc %%edx \n" "dec %%ecx \n" "jnz 1b \n" "adc %%ecx, %%ecx \n" // ecx has the cf state "pop %%eax \n" // eax = rest "or %%eax, %%eax \n" "jz 3f \n" "xor %%ebx, %%ebx \n" // ebx = 0 "neg %%ecx \n" // setting cf from ecx "mov %%eax, %%ecx \n" // ecx=rest and is != 0 "2: \n" "mov (%%esi, %%edx, 4), %%eax \n" "adc %%ebx, %%eax \n" "mov %%eax, (%%edi, %%edx, 4) \n" "inc %%edx \n" "dec %%ecx \n" "jnz 2b \n" "adc %%ecx, %%ecx \n" "3: \n" : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) : "cc", "memory" ); #endif TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) return c; } /*! subtracting ss2 from the 'this' and subtracting carry if it has been defined (this = this - ss2 - c) c must be zero or one (might be a bigger value than 1) function returns carry (1) (if it has been) */ template uint UInt::Sub(const UInt & ss2, uint c) { uint b = value_size; uint * p1 = table; uint * p2 = const_cast(ss2.table); // we don't have to use TTMATH_REFERENCE_ASSERT here // this algorithm doesn't require it #ifndef __GNUC__ __asm { push eax push ebx push ecx push edx push esi mov ecx,[b] mov ebx,[p1] mov esi,[p2] xor edx,edx // edx=0 mov eax,[c] neg eax // CF=1 if rax!=0 , CF=0 if rax==0 ttmath_loop: mov eax,[esi+edx*4] sbb [ebx+edx*4],eax inc edx dec ecx jnz ttmath_loop adc ecx, ecx mov [c], ecx pop esi pop edx pop ecx pop ebx pop eax } #endif #ifdef __GNUC__ uint dummy, dummy2; __asm__ __volatile__( "xorl %%edx, %%edx \n" "negl %%eax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "1: \n" "movl (%%esi,%%edx,4), %%eax \n" "sbbl %%eax, (%%ebx,%%edx,4) \n" "incl %%edx \n" "decl %%ecx \n" "jnz 1b \n" "adc %%ecx, %%ecx \n" : "=c" (c), "=a" (dummy), "=d" (dummy2) : "0" (b), "1" (c), "b" (p1), "S" (p2) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::Sub", c) return c; } /*! this method subtracts one word (at a specific position) and returns a carry (if it was) e.g. if we've got (value_size=3): table[0] = 10; table[1] = 30; table[2] = 5; and we call: SubInt(2,1) then it'll be: table[0] = 10; table[1] = 30 - 2; table[2] = 5; of course if there was a carry from table[2] it would be returned */ template uint UInt::SubInt(uint value, uint index) { uint b = value_size; uint * p1 = table; uint c; TTMATH_ASSERT( index < value_size ) #ifndef __GNUC__ __asm { push eax push ebx push ecx push edx mov ecx, [b] sub ecx, [index] mov edx, [index] mov ebx, [p1] mov eax, [value] ttmath_loop: sub [ebx+edx*4], eax jnc ttmath_end mov eax, 1 inc edx dec ecx jnz ttmath_loop ttmath_end: setc al movzx edx, al mov [c], edx pop edx pop ecx pop ebx pop eax } #endif #ifdef __GNUC__ uint dummy, dummy2; __asm__ __volatile__( "subl %%edx, %%ecx \n" "1: \n" "subl %%eax, (%%ebx,%%edx,4) \n" "jnc 2f \n" "movl $1, %%eax \n" "incl %%edx \n" "decl %%ecx \n" "jnz 1b \n" "2: \n" "setc %%al \n" "movzx %%al, %%edx \n" : "=d" (c), "=a" (dummy), "=c" (dummy2) : "0" (index), "1" (value), "2" (b), "b" (p1) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::SubInt", c) return c; } /*! this static method subtractes one vector from the other 'ss1' is larger in size or equal to 'ss2' ss1 points to the first (larger) vector ss2 points to the second vector ss1_size - size of the ss1 (and size of the result too) ss2_size - size of the ss2 result - is the result vector (which has size the same as ss1: ss1_size) Example: ss1_size is 5, ss2_size is 3 ss1: ss2: result (output): 5 1 5-1 4 3 4-3 2 7 2-7 6 6-1 (the borrow from previous item) 9 9 return (carry): 0 of course the carry (borrow) is propagated and will be returned from the last item (this method is used by the Karatsuba multiplication algorithm) */ template uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) { TTMATH_ASSERT( ss1_size >= ss2_size ) uint rest = ss1_size - ss2_size; uint c; #ifndef __GNUC__ // this part might be compiled with for example visual c /* the asm code is nearly the same as in AddVector only two instructions 'adc' are changed to 'sbb' */ __asm { pushad mov ecx, [ss2_size] xor edx, edx // edx = 0, cf = 0 mov esi, [ss1] mov ebx, [ss2] mov edi, [result] ttmath_loop: mov eax, [esi+edx*4] sbb eax, [ebx+edx*4] mov [edi+edx*4], eax inc edx dec ecx jnz ttmath_loop adc ecx, ecx // ecx has the cf state mov ebx, [rest] or ebx, ebx jz ttmath_end xor ebx, ebx // ebx = 0 neg ecx // setting cf from ecx mov ecx, [rest] // ecx is != 0 ttmath_loop2: mov eax, [esi+edx*4] sbb eax, ebx mov [edi+edx*4], eax inc edx dec ecx jnz ttmath_loop2 adc ecx, ecx ttmath_end: mov [c], ecx popad } #endif #ifdef __GNUC__ // this part should be compiled with gcc uint dummy1, dummy2, dummy3; __asm__ __volatile__( "push %%edx \n" "xor %%edx, %%edx \n" // edx = 0, cf = 0 "1: \n" "mov (%%esi,%%edx,4), %%eax \n" "sbb (%%ebx,%%edx,4), %%eax \n" "mov %%eax, (%%edi,%%edx,4) \n" "inc %%edx \n" "dec %%ecx \n" "jnz 1b \n" "adc %%ecx, %%ecx \n" // ecx has the cf state "pop %%eax \n" // eax = rest "or %%eax, %%eax \n" "jz 3f \n" "xor %%ebx, %%ebx \n" // ebx = 0 "neg %%ecx \n" // setting cf from ecx "mov %%eax, %%ecx \n" // ecx=rest and is != 0 "2: \n" "mov (%%esi, %%edx, 4), %%eax \n" "sbb %%ebx, %%eax \n" "mov %%eax, (%%edi, %%edx, 4) \n" "inc %%edx \n" "dec %%ecx \n" "jnz 2b \n" "adc %%ecx, %%ecx \n" "3: \n" : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) : "cc", "memory" ); #endif TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) return c; } /*! this method moves all bits into the left hand side return value <- this <- c the lowest *bit* will be held the 'c' and the state of one additional bit (on the left hand side) will be returned for example: let this is 001010000 after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 */ template uint UInt::Rcl2_one(uint c) { uint b = value_size; uint * p1 = table; #ifndef __GNUC__ __asm { push ebx push ecx push edx mov ebx, [p1] xor edx, edx mov ecx, [c] neg ecx mov ecx, [b] ttmath_loop: rcl dword ptr [ebx+edx*4], 1 inc edx dec ecx jnz ttmath_loop adc ecx, ecx mov [c], ecx pop edx pop ecx pop ebx } #endif #ifdef __GNUC__ uint dummy, dummy2; __asm__ __volatile__( "xorl %%edx, %%edx \n" // edx=0 "negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0 "1: \n" "rcll $1, (%%ebx, %%edx, 4) \n" "incl %%edx \n" "decl %%ecx \n" "jnz 1b \n" "adcl %%ecx, %%ecx \n" : "=c" (c), "=a" (dummy), "=d" (dummy2) : "0" (b), "1" (c), "b" (p1) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::Rcl2_one", c) return c; } /*! this method moves all bits into the right hand side c -> this -> return value the highest *bit* will be held the 'c' and the state of one additional bit (on the right hand side) will be returned for example: let this is 000000010 after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 */ template uint UInt::Rcr2_one(uint c) { uint b = value_size; uint * p1 = table; #ifndef __GNUC__ __asm { push ebx push ecx mov ebx, [p1] mov ecx, [c] neg ecx mov ecx, [b] ttmath_loop: rcr dword ptr [ebx+ecx*4-4], 1 dec ecx jnz ttmath_loop adc ecx, ecx mov [c], ecx pop ecx pop ebx } #endif #ifdef __GNUC__ uint dummy; __asm__ __volatile__( "negl %%eax \n" // CF=1 if eax!=0 , CF=0 if eax==0 "1: \n" "rcrl $1, -4(%%ebx, %%ecx, 4) \n" "decl %%ecx \n" "jnz 1b \n" "adcl %%ecx, %%ecx \n" : "=c" (c), "=a" (dummy) : "0" (b), "1" (c), "b" (p1) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::Rcr2_one", c) return c; } #ifdef _MSC_VER #pragma warning (disable : 4731) //warning C4731: frame pointer register 'ebp' modified by inline assembly code #endif /*! this method moves all bits into the left hand side return value <- this <- c the lowest *bits* will be held the 'c' and the state of one additional bit (on the left hand side) will be returned for example: let this is 001010000 after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 */ template uint UInt::Rcl2(uint bits, uint c) { TTMATH_ASSERT( bits>0 && bits edx -> cf) (cl times) "movl %%edx, %%ebp \n" // ebp = edx = mask "movl %%esi, %%ecx \n" "xorl %%edx, %%edx \n" "movl %%edx, %%esi \n" "orl %%eax, %%eax \n" "cmovnz %%ebp, %%esi \n" // if(c) esi=mask else esi=0 "1: \n" "roll %%cl, (%%ebx,%%edx,4) \n" "movl (%%ebx,%%edx,4), %%eax \n" "andl %%ebp, %%eax \n" "xorl %%eax, (%%ebx,%%edx,4) \n" "orl %%esi, (%%ebx,%%edx,4) \n" "movl %%eax, %%esi \n" "incl %%edx \n" "decl %%edi \n" "jnz 1b \n" "and $1, %%eax \n" "pop %%ebp \n" : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3) : "0" (c), "1" (b), "b" (p1), "c" (bits) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::Rcl2", c) return c; } /*! this method moves all bits into the right hand side C -> this -> return value the highest *bits* will be held the 'c' and the state of one additional bit (on the right hand side) will be returned for example: let this is 000000010 after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 */ template uint UInt::Rcr2(uint bits, uint c) { TTMATH_ASSERT( bits>0 && bits sint UInt::FindLeadingBitInWord(uint x) { sint result; #ifndef __GNUC__ __asm { push eax push edx mov edx,-1 bsr eax,[x] cmovz eax,edx mov [result], eax pop edx pop eax } #endif #ifdef __GNUC__ uint dummy; __asm__ ( "movl $-1, %1 \n" "bsrl %2, %0 \n" "cmovz %1, %0 \n" : "=r" (result), "=&r" (dummy) : "r" (x) : "cc" ); #endif return result; } /* this method returns the number of the smallest set bit in one 32-bit word if the 'x' is zero this method returns '-1' */ template sint UInt::FindLowestBitInWord(uint x) { sint result; #ifndef __GNUC__ __asm { push eax push edx mov edx,-1 bsf eax,[x] cmovz eax,edx mov [result], eax pop edx pop eax } #endif #ifdef __GNUC__ uint dummy; __asm__ ( "movl $-1, %1 \n" "bsfl %2, %0 \n" "cmovz %1, %0 \n" : "=r" (result), "=&r" (dummy) : "r" (x) : "cc" ); #endif return result; } /*! this method sets a special bit in the 'value' and returns the last state of the bit (zero or one) bit is from <0,31> e.g. uint x = 100; uint bit = SetBitInWord(x, 3); now: x = 108 and bit = 0 */ template uint UInt::SetBitInWord(uint & value, uint bit) { TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) uint old_bit; uint v = value; #ifndef __GNUC__ __asm { push ebx push eax mov eax, [v] mov ebx, [bit] bts eax, ebx mov [v], eax setc bl movzx ebx, bl mov [old_bit], ebx pop eax pop ebx } #endif #ifdef __GNUC__ __asm__ ( "btsl %%ebx, %%eax \n" "setc %%bl \n" "movzx %%bl, %%ebx \n" : "=a" (v), "=b" (old_bit) : "0" (v), "1" (bit) : "cc" ); #endif value = v; return old_bit; } /*! multiplication: result_high:result_low = a * b result_high - higher word of the result result_low - lower word of the result this methos never returns a carry this method is used in the second version of the multiplication algorithms */ template void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) { /* we must use these temporary variables in order to inform the compilator that value pointed with result1 and result2 has changed this has no effect in visual studio but it's useful when using gcc and options like -Ox */ uint result1_; uint result2_; #ifndef __GNUC__ __asm { push eax push edx mov eax, [a] mul dword ptr [b] mov [result2_], edx mov [result1_], eax pop edx pop eax } #endif #ifdef __GNUC__ __asm__ ( "mull %%edx \n" : "=a" (result1_), "=d" (result2_) : "0" (a), "1" (b) : "cc" ); #endif *result_low = result1_; *result_high = result2_; } /*! * * Division * * */ /*! this method calculates 64bits word a:b / 32bits c (a higher, b lower word) r = a:b / c and rest - remainder * * WARNING: * if r (one word) is too small for the result or c is equal zero * there'll be a hardware interruption (0) * and probably the end of your program * */ template void UInt::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest) { uint r_; uint rest_; /* these variables have similar meaning like those in the multiplication algorithm MulTwoWords */ TTMATH_ASSERT( c != 0 ) #ifndef __GNUC__ __asm { push eax push edx mov edx, [a] mov eax, [b] div dword ptr [c] mov [r_], eax mov [rest_], edx pop edx pop eax } #endif #ifdef __GNUC__ __asm__ ( "divl %%ecx \n" : "=a" (r_), "=d" (rest_) : "0" (b), "1" (a), "c" (c) : "cc" ); #endif *r = r_; *rest = rest_; } } //namespace #endif //ifdef TTMATH_PLATFORM32 #endif //ifndef TTMATH_NOASM #endif discoSnp/minia/ttmath/ttmathuint_noasm.h0000644000000000000000000005221512062133074017506 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2010, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathuint_noasm #define headerfilettmathuint_noasm #ifdef TTMATH_NOASM /*! \file ttmathuint_noasm.h \brief template class UInt with methods without any assembler code this file is included at the end of ttmathuint.h */ namespace ttmath { /*! returning the string represents the currect type of the library we have following types: asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) asm_gcc_32 - with asm code designed for GCC (32 bits) asm_vc_64 - with asm for VC (64 bit) asm_gcc_64 - with asm for GCC (64 bit) no_asm_32 - pure C++ version (32 bit) - without any asm code no_asm_64 - pure C++ version (64 bit) - without any asm code */ template const char * UInt::LibTypeStr() { #ifdef TTMATH_PLATFORM32 static const char info[] = "no_asm_32"; #endif #ifdef TTMATH_PLATFORM64 static const char info[] = "no_asm_64"; #endif return info; } /*! returning the currect type of the library */ template LibTypeCode UInt::LibType() { #ifdef TTMATH_PLATFORM32 LibTypeCode info = no_asm_32; #endif #ifdef TTMATH_PLATFORM64 LibTypeCode info = no_asm_64; #endif return info; } /*! this method adds two words together returns carry this method is created only when TTMATH_NOASM macro is defined */ template uint UInt::AddTwoWords(uint a, uint b, uint carry, uint * result) { uint temp; if( carry == 0 ) { temp = a + b; if( temp < a ) carry = 1; } else { carry = 1; temp = a + b + carry; if( temp > a ) // !(temp<=a) carry = 0; } *result = temp; return carry; } /*! this method adding ss2 to the this and adding carry if it's defined (this = this + ss2 + c) c must be zero or one (might be a bigger value than 1) function returns carry (1) (if it was) */ template uint UInt::Add(const UInt & ss2, uint c) { uint i; for(i=0 ; i uint UInt::AddInt(uint value, uint index) { uint i, c; TTMATH_ASSERT( index < value_size ) c = AddTwoWords(table[index], value, 0, &table[index]); for(i=index+1 ; i uint UInt::AddTwoInts(uint x2, uint x1, uint index) { uint i, c; TTMATH_ASSERT( index < value_size - 1 ) c = AddTwoWords(table[index], x1, 0, &table[index]); c = AddTwoWords(table[index+1], x2, c, &table[index+1]); for(i=index+2 ; i uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) { uint i, c = 0; TTMATH_ASSERT( ss1_size >= ss2_size ) for(i=0 ; i uint UInt::SubTwoWords(uint a, uint b, uint carry, uint * result) { if( carry == 0 ) { *result = a - b; if( a < b ) carry = 1; } else { carry = 1; *result = a - b - carry; if( a > b ) // !(a <= b ) carry = 0; } return carry; } /*! this method's subtracting ss2 from the 'this' and subtracting carry if it has been defined (this = this - ss2 - c) c must be zero or one (might be a bigger value than 1) function returns carry (1) (if it was) */ template uint UInt::Sub(const UInt & ss2, uint c) { uint i; for(i=0 ; i uint UInt::SubInt(uint value, uint index) { uint i, c; TTMATH_ASSERT( index < value_size ) c = SubTwoWords(table[index], value, 0, &table[index]); for(i=index+1 ; i uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) { uint i, c = 0; TTMATH_ASSERT( ss1_size >= ss2_size ) for(i=0 ; i uint UInt::Rcl2_one(uint c) { uint i, new_c; if( c != 0 ) c = 1; for(i=0 ; i this -> return value the highest *bit* will be held the 'c' and the state of one additional bit (on the right hand side) will be returned for example: let this is 000000010 after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 */ template uint UInt::Rcr2_one(uint c) { sint i; // signed i uint new_c; if( c != 0 ) c = TTMATH_UINT_HIGHEST_BIT; for(i=sint(value_size)-1 ; i>=0 ; --i) { new_c = (table[i] & 1) ? TTMATH_UINT_HIGHEST_BIT : 0; table[i] = (table[i] >> 1) | c; c = new_c; } c = (c != 0)? 1 : 0; TTMATH_LOGC("UInt::Rcr2_one", c) return c; } /*! this method moves all bits into the left hand side return value <- this <- c the lowest *bits* will be held the 'c' and the state of one additional bit (on the left hand side) will be returned for example: let this is 001010000 after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 */ template uint UInt::Rcl2(uint bits, uint c) { TTMATH_ASSERT( bits>0 && bits> move; for(i=0 ; i> move; table[i] = (table[i] << bits) | c; c = new_c; } TTMATH_LOGC("UInt::Rcl2", (c & 1)) return (c & 1); } /*! this method moves all bits into the right hand side C -> this -> return value the highest *bits* will be held the 'c' and the state of one additional bit (on the right hand side) will be returned for example: let this is 000000010 after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 */ template uint UInt::Rcr2(uint bits, uint c) { TTMATH_ASSERT( bits>0 && bits=0 ; --i) { new_c = table[i] << move; table[i] = (table[i] >> bits) | c; c = new_c; } c = (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; TTMATH_LOGC("UInt::Rcr2", c) return c; } /*! this method returns the number of the highest set bit in x if the 'x' is zero this method returns '-1' */ template sint UInt::FindLeadingBitInWord(uint x) { if( x == 0 ) return -1; uint bit = TTMATH_BITS_PER_UINT - 1; while( (x & TTMATH_UINT_HIGHEST_BIT) == 0 ) { x = x << 1; --bit; } return bit; } /*! this method returns the number of the highest set bit in x if the 'x' is zero this method returns '-1' */ template sint UInt::FindLowestBitInWord(uint x) { if( x == 0 ) return -1; uint bit = 0; while( (x & 1) == 0 ) { x = x >> 1; ++bit; } return bit; } /*! this method sets a special bit in the 'value' and returns the last state of the bit (zero or one) bit is from <0,TTMATH_BITS_PER_UINT-1> e.g. uint x = 100; uint bit = SetBitInWord(x, 3); now: x = 108 and bit = 0 */ template uint UInt::SetBitInWord(uint & value, uint bit) { TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) uint mask = 1; if( bit > 0 ) mask = mask << bit; uint last = value & mask; value = value | mask; return (last != 0) ? 1 : 0; } /*! * * Multiplication * * */ /*! multiplication: result_high:result_low = a * b result_high - higher word of the result result_low - lower word of the result this methos never returns a carry this method is used in the second version of the multiplication algorithms */ template void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) { #ifdef TTMATH_PLATFORM32 /* on 32bit platforms we have defined 'unsigned long long int' type known as 'ulint' in ttmath namespace this type has 64 bits, then we're using only one multiplication: 32bit * 32bit = 64bit */ union uint_ { struct { uint low; // 32 bits uint high; // 32 bits } u_; ulint u; // 64 bits } res; res.u = ulint(a) * ulint(b); // multiply two 32bit words, the result has 64 bits *result_high = res.u_.high; *result_low = res.u_.low; #else /* 64 bits platforms we don't have a native type which has 128 bits then we're splitting 'a' and 'b' to 4 parts (high and low halves) and using 4 multiplications (with additions and carry correctness) */ uint_ a_; uint_ b_; uint_ res_high1, res_high2; uint_ res_low1, res_low2; a_.u = a; b_.u = b; /* the multiplication is as follows (schoolbook algorithm with O(n^2) ): 32 bits 32 bits +--------------------------------+ | a_.u_.high | a_.u_.low | +--------------------------------+ | b_.u_.high | b_.u_.low | +--------------------------------+--------------------------------+ | res_high1.u | res_low1.u | +--------------------------------+--------------------------------+ | res_high2.u | res_low2.u | +--------------------------------+--------------------------------+ 64 bits 64 bits */ uint_ temp; res_low1.u = uint(b_.u_.low) * uint(a_.u_.low); temp.u = uint(res_low1.u_.high) + uint(b_.u_.low) * uint(a_.u_.high); res_low1.u_.high = temp.u_.low; res_high1.u_.low = temp.u_.high; res_high1.u_.high = 0; res_low2.u_.low = 0; temp.u = uint(b_.u_.high) * uint(a_.u_.low); res_low2.u_.high = temp.u_.low; res_high2.u = uint(b_.u_.high) * uint(a_.u_.high) + uint(temp.u_.high); uint c = AddTwoWords(res_low1.u, res_low2.u, 0, &res_low2.u); AddTwoWords(res_high1.u, res_high2.u, c, &res_high2.u); // there is no carry from here *result_high = res_high2.u; *result_low = res_low2.u; #endif } /*! * * Division * * */ /*! this method calculates 64bits word a:b / 32bits c (a higher, b lower word) r = a:b / c and rest - remainder * * WARNING: * the c has to be suitably large for the result being keeped in one word, * if c is equal zero there'll be a hardware interruption (0) * and probably the end of your program * */ template void UInt::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest) { // (a < c ) for the result to be one word TTMATH_ASSERT( c != 0 && a < c ) #ifdef TTMATH_PLATFORM32 union { struct { uint low; // 32 bits uint high; // 32 bits } u_; ulint u; // 64 bits } ab; ab.u_.high = a; ab.u_.low = b; *r = uint(ab.u / c); *rest = uint(ab.u % c); #else uint_ c_; c_.u = c; if( a == 0 ) { *r = b / c; *rest = b % c; } else if( c_.u_.high == 0 ) { // higher half of 'c' is zero // then higher half of 'a' is zero too (look at the asserts at the beginning - 'a' is smaller than 'c') uint_ a_, b_, res_, temp1, temp2; a_.u = a; b_.u = b; temp1.u_.high = a_.u_.low; temp1.u_.low = b_.u_.high; res_.u_.high = (unsigned int)(temp1.u / c); temp2.u_.high = (unsigned int)(temp1.u % c); temp2.u_.low = b_.u_.low; res_.u_.low = (unsigned int)(temp2.u / c); *rest = temp2.u % c; *r = res_.u; } else { return DivTwoWords2(a, b, c, r, rest); } #endif } #ifdef TTMATH_PLATFORM64 /*! this method is available only on 64bit platforms the same algorithm like the third division algorithm in ttmathuint.h but now with the radix=2^32 */ template void UInt::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest) { // a is not zero // c_.u_.high is not zero uint_ a_, b_, c_, u_, q_; unsigned int u3; // 32 bit a_.u = a; b_.u = b; c_.u = c; // normalizing uint d = DivTwoWordsNormalize(a_, b_, c_); // loop from j=1 to j=0 // the first step (for j=2) is skipped because our result is only in one word, // (first 'q' were 0 and nothing would be changed) u_.u_.high = a_.u_.high; u_.u_.low = a_.u_.low; u3 = b_.u_.high; q_.u_.high = DivTwoWordsCalculate(u_, u3, c_); MultiplySubtract(u_, u3, q_.u_.high, c_); u_.u_.high = u_.u_.low; u_.u_.low = u3; u3 = b_.u_.low; q_.u_.low = DivTwoWordsCalculate(u_, u3, c_); MultiplySubtract(u_, u3, q_.u_.low, c_); *r = q_.u; // unnormalizing for the remainder u_.u_.high = u_.u_.low; u_.u_.low = u3; *rest = DivTwoWordsUnnormalize(u_.u, d); } template uint UInt::DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_) { uint d = 0; for( ; (c_.u & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d ) { c_.u = c_.u << 1; uint bc = b_.u & TTMATH_UINT_HIGHEST_BIT; // carry from 'b' b_.u = b_.u << 1; a_.u = a_.u << 1; // carry bits from 'a' are simply skipped if( bc ) a_.u = a_.u | 1; } return d; } template uint UInt::DivTwoWordsUnnormalize(uint u, uint d) { if( d == 0 ) return u; u = u >> d; return u; } template unsigned int UInt::DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_) { bool next_test; uint_ qp_, rp_, temp_; qp_.u = u_.u / uint(v_.u_.high); rp_.u = u_.u % uint(v_.u_.high); TTMATH_ASSERT( qp_.u_.high==0 || qp_.u_.high==1 ) do { bool decrease = false; if( qp_.u_.high == 1 ) decrease = true; else { temp_.u_.high = rp_.u_.low; temp_.u_.low = u3; if( qp_.u * uint(v_.u_.low) > temp_.u ) decrease = true; } next_test = false; if( decrease ) { --qp_.u; rp_.u += v_.u_.high; if( rp_.u_.high == 0 ) next_test = true; } } while( next_test ); return qp_.u_.low; } template void UInt::MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_) { uint_ temp_; uint res_high; uint res_low; MulTwoWords(v_.u, q, &res_high, &res_low); uint_ sub_res_high_; uint_ sub_res_low_; temp_.u_.high = u_.u_.low; temp_.u_.low = u3; uint c = SubTwoWords(temp_.u, res_low, 0, &sub_res_low_.u); temp_.u_.high = 0; temp_.u_.low = u_.u_.high; c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u); if( c ) { --q; c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u); AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u); } u_.u_.high = sub_res_high_.u_.low; u_.u_.low = sub_res_low_.u_.high; u3 = sub_res_low_.u_.low; } #endif // #ifdef TTMATH_PLATFORM64 } //namespace #endif //ifdef TTMATH_NOASM #endif discoSnp/minia/ttmath/ttmathobjects.h0000644000000000000000000004223412062133074016763 0ustar rootroot/* * This file is a part of TTMath Mathematical Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2010, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathobject #define headerfilettmathobject /*! \file ttmathobjects.h \brief Mathematic functions. */ #include #include #include #include #include "ttmathtypes.h" #include "ttmathmisc.h" namespace ttmath { /*! objects of this class are used with the mathematical parser they hold variables or functions defined by a user each object has its own table in which we're keeping variables or functions */ class Objects { public: /*! one item (variable or function) 'items' will be on the table */ struct Item { // name of a variable of a function // internally we store variables and funcions as std::string (not std::wstring even when wide characters are used) std::string value; // number of parameters required by the function // (if there's a variable this 'param' is ignored) int param; Item() {} Item(const std::string & v, int p) : value(v), param(p) {} }; // 'Table' is the type of our table typedef std::map Table; typedef Table::iterator Iterator; typedef Table::const_iterator CIterator; /*! this method returns true if a character 'c' is a character which can be in a name if 'can_be_digit' is true that means when the 'c' is a digit this method returns true otherwise it returns false */ static bool CorrectCharacter(int c, bool can_be_digit) { if( (c>='a' && c<='z') || (c>='A' && c<='Z') ) return true; if( can_be_digit && ((c>='0' && c<='9') || c=='_') ) return true; return false; } /*! this method returns true if the name can be as a name of an object */ template static bool IsNameCorrect(const string_type & name) { if( name.empty() ) return false; if( !CorrectCharacter(name[0], false) ) return false; typename string_type::const_iterator i = name.begin(); for(++i ; i!=name.end() ; ++i) if( !CorrectCharacter(*i, true) ) return false; return true; } /*! this method returns true if such an object is defined (name exists) */ bool IsDefined(const std::string & name) { Iterator i = table.find(name); if( i != table.end() ) // we have this object in our table return true; return false; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method returns true if such an object is defined (name exists) */ bool IsDefined(const std::wstring & name) { // we should check whether the name (in wide characters) are correct // before calling AssignString() function if( !IsNameCorrect(name) ) return false; Misc::AssignString(str_tmp1, name); return IsDefined(str_tmp1); } #endif /*! this method adds one object (variable of function) into the table */ ErrorCode Add(const std::string & name, const std::string & value, int param = 0) { if( !IsNameCorrect(name) ) return err_incorrect_name; Iterator i = table.find(name); if( i != table.end() ) // we have this object in our table return err_object_exists; table.insert( std::make_pair(name, Item(value, param)) ); return err_ok; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method adds one object (variable of function) into the table */ ErrorCode Add(const std::wstring & name, const std::wstring & value, int param = 0) { // we should check whether the name (in wide characters) are correct // before calling AssignString() function if( !IsNameCorrect(name) ) return err_incorrect_name; Misc::AssignString(str_tmp1, name); Misc::AssignString(str_tmp2, value); return Add(str_tmp1, str_tmp2, param); } #endif /*! this method returns 'true' if the table is empty */ bool Empty() const { return table.empty(); } /*! this method clears the table */ void Clear() { return table.clear(); } /*! this method returns 'const_iterator' on the first item on the table */ CIterator Begin() const { return table.begin(); } /*! this method returns 'const_iterator' pointing at the space after last item (returns table.end()) */ CIterator End() const { return table.end(); } /*! this method changes the value and the number of parameters for a specific object */ ErrorCode EditValue(const std::string & name, const std::string & value, int param = 0) { if( !IsNameCorrect(name) ) return err_incorrect_name; Iterator i = table.find(name); if( i == table.end() ) return err_unknown_object; i->second.value = value; i->second.param = param; return err_ok; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method changes the value and the number of parameters for a specific object */ ErrorCode EditValue(const std::wstring & name, const std::wstring & value, int param = 0) { // we should check whether the name (in wide characters) are correct // before calling AssignString() function if( !IsNameCorrect(name) ) return err_incorrect_name; Misc::AssignString(str_tmp1, name); Misc::AssignString(str_tmp2, value); return EditValue(str_tmp1, str_tmp2, param); } #endif /*! this method changes the name of a specific object */ ErrorCode EditName(const std::string & old_name, const std::string & new_name) { if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) return err_incorrect_name; Iterator old_i = table.find(old_name); if( old_i == table.end() ) return err_unknown_object; if( old_name == new_name ) // the new name is the same as the old one // we treat it as a normal situation return err_ok; ErrorCode err = Add(new_name, old_i->second.value, old_i->second.param); if( err == err_ok ) { old_i = table.find(old_name); TTMATH_ASSERT( old_i != table.end() ) table.erase(old_i); } return err; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method changes the name of a specific object */ ErrorCode EditName(const std::wstring & old_name, const std::wstring & new_name) { // we should check whether the name (in wide characters) are correct // before calling AssignString() function if( !IsNameCorrect(old_name) || !IsNameCorrect(new_name) ) return err_incorrect_name; Misc::AssignString(str_tmp1, old_name); Misc::AssignString(str_tmp2, new_name); return EditName(str_tmp1, str_tmp2); } #endif /*! this method deletes an object */ ErrorCode Delete(const std::string & name) { if( !IsNameCorrect(name) ) return err_incorrect_name; Iterator i = table.find(name); if( i == table.end() ) return err_unknown_object; table.erase( i ); return err_ok; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method deletes an object */ ErrorCode Delete(const std::wstring & name) { // we should check whether the name (in wide characters) are correct // before calling AssignString() function if( !IsNameCorrect(name) ) return err_incorrect_name; Misc::AssignString(str_tmp1, name); return Delete(str_tmp1); } #endif /*! this method gets the value of a specific object */ ErrorCode GetValue(const std::string & name, std::string & value) const { if( !IsNameCorrect(name) ) return err_incorrect_name; CIterator i = table.find(name); if( i == table.end() ) { value.clear(); return err_unknown_object; } value = i->second.value; return err_ok; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method gets the value of a specific object */ ErrorCode GetValue(const std::wstring & name, std::wstring & value) { // we should check whether the name (in wide characters) are correct // before calling AssignString() function if( !IsNameCorrect(name) ) return err_incorrect_name; Misc::AssignString(str_tmp1, name); ErrorCode err = GetValue(str_tmp1, str_tmp2); Misc::AssignString(value, str_tmp2); return err; } #endif /*! this method gets the value of a specific object (this version is used for not copying the whole string) */ ErrorCode GetValue(const std::string & name, const char ** value) const { if( !IsNameCorrect(name) ) return err_incorrect_name; CIterator i = table.find(name); if( i == table.end() ) { *value = 0; return err_unknown_object; } *value = i->second.value.c_str(); return err_ok; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method gets the value of a specific object (this version is used for not copying the whole string) */ ErrorCode GetValue(const std::wstring & name, const char ** value) { // we should check whether the name (in wide characters) are correct // before calling AssignString() function if( !IsNameCorrect(name) ) return err_incorrect_name; Misc::AssignString(str_tmp1, name); return GetValue(str_tmp1, value); } #endif /*! this method gets the value and the number of parameters of a specific object */ ErrorCode GetValueAndParam(const std::string & name, std::string & value, int * param) const { if( !IsNameCorrect(name) ) return err_incorrect_name; CIterator i = table.find(name); if( i == table.end() ) { value.empty(); *param = 0; return err_unknown_object; } value = i->second.value; *param = i->second.param; return err_ok; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method gets the value and the number of parameters of a specific object */ ErrorCode GetValueAndParam(const std::wstring & name, std::wstring & value, int * param) { // we should check whether the name (in wide characters) are correct // before calling AssignString() function if( !IsNameCorrect(name) ) return err_incorrect_name; Misc::AssignString(str_tmp1, name); ErrorCode err = GetValueAndParam(str_tmp1, str_tmp2, param); Misc::AssignString(value, str_tmp2); return err; } #endif /*! this method sets the value and the number of parameters of a specific object (this version is used for not copying the whole string) */ ErrorCode GetValueAndParam(const std::string & name, const char ** value, int * param) const { if( !IsNameCorrect(name) ) return err_incorrect_name; CIterator i = table.find(name); if( i == table.end() ) { *value = 0; *param = 0; return err_unknown_object; } *value = i->second.value.c_str(); *param = i->second.param; return err_ok; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method sets the value and the number of parameters of a specific object (this version is used for not copying the whole string but in fact we make one copying during AssignString()) */ ErrorCode GetValueAndParam(const std::wstring & name, const char ** value, int * param) { // we should check whether the name (in wide characters) are correct // before calling AssignString() function if( !IsNameCorrect(name) ) return err_incorrect_name; Misc::AssignString(str_tmp1, name); return GetValueAndParam(str_tmp1, value, param); } #endif /*! this method returns a pointer into the table */ Table * GetTable() { return &table; } private: Table table; std::string str_tmp1, str_tmp2; }; // end of class Objects /*! objects of the class History are used to keep values in functions which take a lot of time during calculating, for instance in the function Factorial(x) it means that when we're calculating e.g. Factorial(1000) and the Factorial finds that we have calculated it before, the value (result) is taken from the history */ template class History { /*! one item in the History's object holds a key, a value for the key and a corresponding error code */ struct Item { ValueType key, value; ErrorCode err; }; /*! we use std::list for simply deleting the first item but because we're searching through the whole container (in the method Get) the container should not be too big (linear time of searching) */ typedef std::list buffer_type; buffer_type buffer; typename buffer_type::size_type buffer_max_size; public: /*! default constructor default max size of the History's container is 15 items */ History() { buffer_max_size = 15; } /*! a constructor which takes another value of the max size of the History's container */ History(typename buffer_type::size_type new_size) { buffer_max_size = new_size; } /*! this method adds one item into the History if the size of the container is greater than buffer_max_size the first item will be removed */ void Add(const ValueType & key, const ValueType & value, ErrorCode err) { Item item; item.key = key; item.value = value; item.err = err; buffer.insert( buffer.end(), item ); if( buffer.size() > buffer_max_size ) buffer.erase(buffer.begin()); } /*! this method checks whether we have an item which has the key equal 'key' if there's such item the method sets the 'value' and the 'err' and returns true otherwise it returns false and 'value' and 'err' remain unchanged */ bool Get(const ValueType & key, ValueType & value, ErrorCode & err) { typename buffer_type::iterator i = buffer.begin(); for( ; i != buffer.end() ; ++i ) { if( i->key == key ) { value = i->value; err = i->err; return true; } } return false; } /*! this methods deletes an item we assume that there is only one item with the 'key' (this methods removes the first one) */ bool Remove(const ValueType & key) { typename buffer_type::iterator i = buffer.begin(); for( ; i != buffer.end() ; ++i ) { if( i->key == key ) { buffer.erase(i); return true; } } return false; } }; // end of class History /*! this is an auxiliary class used when calculating Gamma() or Factorial() in multithreaded environment you can provide an object of this class to the Gamma() or Factorial() function, e.g; typedef Big<1, 3> MyBig; MyBig x = 123456; CGamma cgamma; std::cout << Gamma(x, cgamma); each thread should have its own CGamma<> object in a single-thread environment a CGamma<> object is a static variable in a second version of Gamma() and you don't have to explicitly use it, e.g. typedef Big<1, 3> MyBig; MyBig x = 123456; std::cout << Gamma(x); */ template struct CGamma { /*! this table holds factorials 1 1 2 6 24 120 720 ....... */ std::vector fact; /*! this table holds Bernoulli numbers 1 -0.5 0.166666666666666666666666667 0 -0.0333333333333333333333333333 0 0.0238095238095238095238095238 0 -0.0333333333333333333333333333 0 0.075757575757575757575757576 ..... */ std::vector bern; /*! here we store some calculated values (this is for speeding up, if the next argument of Gamma() or Factorial() is in the 'history' then the result we are not calculating but simply return from the 'history' object) */ History history; /*! this method prepares some coefficients: factorials and Bernoulli numbers stored in 'fact' and 'bern' objects how many values should be depends on the size of the mantissa - if the mantissa is larger then we must calculate more values for a mantissa which consists of 256 bits (8 words on a 32bit platform) we have to calculate about 30 values (the size of fact and bern will be 30), and for a 2048 bits mantissa we have to calculate 306 coefficients you don't have to call this method, these coefficients will be automatically calculated when they are needed you must note that calculating these coefficients is a little time-consuming operation, (especially when the mantissa is large) and first call to Gamma() or Factorial() can take more time than next calls, and in the end this is the point when InitAll() comes in handy: you can call this method somewhere at the beginning of your program */ void InitAll(); // definition is in ttmath.h }; } // namespace #endif discoSnp/minia/ttmath/ttmathuint_x86_64.h0000644000000000000000000006000312062133074017321 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2010, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathuint_x86_64 #define headerfilettmathuint_x86_64 #ifndef TTMATH_NOASM #ifdef TTMATH_PLATFORM64 /*! \file ttmathuint_x86_64.h \brief template class UInt with assembler code for 64bit x86_64 processors this file is included at the end of ttmathuint.h */ #ifndef __GNUC__ #include #endif namespace ttmath { #ifndef __GNUC__ extern "C" { uint __fastcall ttmath_adc_x64(uint* p1, const uint* p2, uint nSize, uint c); uint __fastcall ttmath_addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); uint __fastcall ttmath_addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2); uint __fastcall ttmath_addvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); uint __fastcall ttmath_sbb_x64(uint* p1, const uint* p2, uint nSize, uint c); uint __fastcall ttmath_subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue); uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); uint __fastcall ttmath_rcl_x64(uint* p1, uint nSize, uint nLowestBit); uint __fastcall ttmath_rcr_x64(uint* p1, uint nSize, uint nLowestBit); uint __fastcall ttmath_div_x64(uint* pnValHi, uint* pnValLo, uint nDiv); uint __fastcall ttmath_rcl2_x64(uint* p1, uint nSize, uint nBits, uint c); uint __fastcall ttmath_rcr2_x64(uint* p1, uint nSize, uint nBits, uint c); }; #endif /*! returning the string represents the currect type of the library we have following types: asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) asm_gcc_32 - with asm code designed for GCC (32 bits) asm_vc_64 - with asm for VC (64 bit) asm_gcc_64 - with asm for GCC (64 bit) no_asm_32 - pure C++ version (32 bit) - without any asm code no_asm_64 - pure C++ version (64 bit) - without any asm code */ template const char * UInt::LibTypeStr() { #ifndef __GNUC__ static const char info[] = "asm_vc_64"; #endif #ifdef __GNUC__ static const char info[] = "asm_gcc_64"; #endif return info; } /*! returning the currect type of the library */ template LibTypeCode UInt::LibType() { #ifndef __GNUC__ LibTypeCode info = asm_vc_64; #endif #ifdef __GNUC__ LibTypeCode info = asm_gcc_64; #endif return info; } /*! * * basic mathematic functions * */ /*! this method adding ss2 to the this and adding carry if it's defined (this = this + ss2 + c) ***this method is created only on a 64bit platform*** c must be zero or one (might be a bigger value than 1) function returns carry (1) (if it was) */ template uint UInt::Add(const UInt & ss2, uint c) { uint b = value_size; uint * p1 = table; const uint * p2 = ss2.table; // we don't have to use TTMATH_REFERENCE_ASSERT here // this algorithm doesn't require it #ifndef __GNUC__ c = ttmath_adc_x64(p1,p2,b,c); #endif #ifdef __GNUC__ uint dummy, dummy2; /* this part should be compiled with gcc */ __asm__ __volatile__( "xorq %%rdx, %%rdx \n" "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "1: \n" "movq (%%rsi,%%rdx,8), %%rax \n" "adcq %%rax, (%%rbx,%%rdx,8) \n" "incq %%rdx \n" "decq %%rcx \n" "jnz 1b \n" "adcq %%rcx, %%rcx \n" : "=c" (c), "=a" (dummy), "=d" (dummy2) : "0" (b), "1" (c), "b" (p1), "S" (p2) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::Add", c) return c; } /*! this method adds one word (at a specific position) and returns a carry (if it was) ***this method is created only on a 64bit platform*** if we've got (value_size=3): table[0] = 10; table[1] = 30; table[2] = 5; and we call: AddInt(2,1) then it'll be: table[0] = 10; table[1] = 30 + 2; table[2] = 5; of course if there was a carry from table[2] it would be returned */ template uint UInt::AddInt(uint value, uint index) { uint b = value_size; uint * p1 = table; uint c; TTMATH_ASSERT( index < value_size ) #ifndef __GNUC__ c = ttmath_addindexed_x64(p1,b,index,value); #endif #ifdef __GNUC__ uint dummy, dummy2; __asm__ __volatile__( "subq %%rdx, %%rcx \n" "1: \n" "addq %%rax, (%%rbx,%%rdx,8) \n" "jnc 2f \n" "movq $1, %%rax \n" "incq %%rdx \n" "decq %%rcx \n" "jnz 1b \n" "2: \n" "setc %%al \n" "movzx %%al, %%rdx \n" : "=d" (c), "=a" (dummy), "=c" (dummy2) : "0" (index), "1" (value), "2" (b), "b" (p1) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::AddInt", c) return c; } /*! this method adds only two unsigned words to the existing value and these words begin on the 'index' position (it's used in the multiplication algorithm 2) ***this method is created only on a 64bit platform*** index should be equal or smaller than value_size-2 (index <= value_size-2) x1 - lower word, x2 - higher word for example if we've got value_size equal 4 and: table[0] = 3 table[1] = 4 table[2] = 5 table[3] = 6 then let x1 = 10 x2 = 20 and index = 1 the result of this method will be: table[0] = 3 table[1] = 4 + x1 = 14 table[2] = 5 + x2 = 25 table[3] = 6 and no carry at the end of table[3] (of course if there was a carry in table[2](5+20) then this carry would be passed to the table[3] etc.) */ template uint UInt::AddTwoInts(uint x2, uint x1, uint index) { uint b = value_size; uint * p1 = table; uint c; TTMATH_ASSERT( index < value_size - 1 ) #ifndef __GNUC__ c = ttmath_addindexed2_x64(p1,b,index,x1,x2); #endif #ifdef __GNUC__ uint dummy, dummy2; __asm__ __volatile__( "subq %%rdx, %%rcx \n" "addq %%rsi, (%%rbx,%%rdx,8) \n" "incq %%rdx \n" "decq %%rcx \n" "1: \n" "adcq %%rax, (%%rbx,%%rdx,8) \n" "jnc 2f \n" "mov $0, %%rax \n" "incq %%rdx \n" "decq %%rcx \n" "jnz 1b \n" "2: \n" "setc %%al \n" "movzx %%al, %%rax \n" : "=a" (c), "=c" (dummy), "=d" (dummy2) : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::AddTwoInts", c) return c; } /*! this static method addes one vector to the other 'ss1' is larger in size or equal to 'ss2' ss1 points to the first (larger) vector ss2 points to the second vector ss1_size - size of the ss1 (and size of the result too) ss2_size - size of the ss2 result - is the result vector (which has size the same as ss1: ss1_size) Example: ss1_size is 5, ss2_size is 3 ss1: ss2: result (output): 5 1 5+1 4 3 4+3 2 7 2+7 6 6 9 9 of course the carry is propagated and will be returned from the last item (this method is used by the Karatsuba multiplication algorithm) */ template uint UInt::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) { TTMATH_ASSERT( ss1_size >= ss2_size ) uint c; #ifndef __GNUC__ c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result); #endif #ifdef __GNUC__ uint dummy1, dummy2, dummy3; uint rest = ss1_size - ss2_size; // this part should be compiled with gcc __asm__ __volatile__( "mov %%rdx, %%r8 \n" "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0 "1: \n" "mov (%%rsi,%%rdx,8), %%rax \n" "adc (%%rbx,%%rdx,8), %%rax \n" "mov %%rax, (%%rdi,%%rdx,8) \n" "inc %%rdx \n" "dec %%rcx \n" "jnz 1b \n" "adc %%rcx, %%rcx \n" // rcx has the cf state "or %%r8, %%r8 \n" "jz 3f \n" "xor %%rbx, %%rbx \n" // ebx = 0 "neg %%rcx \n" // setting cf from rcx "mov %%r8, %%rcx \n" // rcx=rest and is != 0 "2: \n" "mov (%%rsi, %%rdx, 8), %%rax \n" "adc %%rbx, %%rax \n" "mov %%rax, (%%rdi, %%rdx, 8) \n" "inc %%rdx \n" "dec %%rcx \n" "jnz 2b \n" "adc %%rcx, %%rcx \n" "3: \n" : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) : "%r8", "cc", "memory" ); #endif TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) return c; } /*! this method's subtracting ss2 from the 'this' and subtracting carry if it has been defined (this = this - ss2 - c) ***this method is created only on a 64bit platform*** c must be zero or one (might be a bigger value than 1) function returns carry (1) (if it was) */ template uint UInt::Sub(const UInt & ss2, uint c) { uint b = value_size; uint * p1 = table; const uint * p2 = ss2.table; // we don't have to use TTMATH_REFERENCE_ASSERT here // this algorithm doesn't require it #ifndef __GNUC__ c = ttmath_sbb_x64(p1,p2,b,c); #endif #ifdef __GNUC__ uint dummy, dummy2; __asm__ __volatile__( "xorq %%rdx, %%rdx \n" "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "1: \n" "movq (%%rsi,%%rdx,8), %%rax \n" "sbbq %%rax, (%%rbx,%%rdx,8) \n" "incq %%rdx \n" "decq %%rcx \n" "jnz 1b \n" "adcq %%rcx, %%rcx \n" : "=c" (c), "=a" (dummy), "=d" (dummy2) : "0" (b), "1" (c), "b" (p1), "S" (p2) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::Sub", c) return c; } /*! this method subtracts one word (at a specific position) and returns a carry (if it was) ***this method is created only on a 64bit platform*** if we've got (value_size=3): table[0] = 10; table[1] = 30; table[2] = 5; and we call: SubInt(2,1) then it'll be: table[0] = 10; table[1] = 30 - 2; table[2] = 5; of course if there was a carry from table[2] it would be returned */ template uint UInt::SubInt(uint value, uint index) { uint b = value_size; uint * p1 = table; uint c; TTMATH_ASSERT( index < value_size ) #ifndef __GNUC__ c = ttmath_subindexed_x64(p1,b,index,value); #endif #ifdef __GNUC__ uint dummy, dummy2; __asm__ __volatile__( "subq %%rdx, %%rcx \n" "1: \n" "subq %%rax, (%%rbx,%%rdx,8) \n" "jnc 2f \n" "movq $1, %%rax \n" "incq %%rdx \n" "decq %%rcx \n" "jnz 1b \n" "2: \n" "setc %%al \n" "movzx %%al, %%rdx \n" : "=d" (c), "=a" (dummy), "=c" (dummy2) : "0" (index), "1" (value), "2" (b), "b" (p1) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::SubInt", c) return c; } /*! this static method subtractes one vector from the other 'ss1' is larger in size or equal to 'ss2' ss1 points to the first (larger) vector ss2 points to the second vector ss1_size - size of the ss1 (and size of the result too) ss2_size - size of the ss2 result - is the result vector (which has size the same as ss1: ss1_size) Example: ss1_size is 5, ss2_size is 3 ss1: ss2: result (output): 5 1 5-1 4 3 4-3 2 7 2-7 6 6-1 (the borrow from previous item) 9 9 return (carry): 0 of course the carry (borrow) is propagated and will be returned from the last item (this method is used by the Karatsuba multiplication algorithm) */ template uint UInt::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) { TTMATH_ASSERT( ss1_size >= ss2_size ) uint c; #ifndef __GNUC__ c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result); #endif #ifdef __GNUC__ // the asm code is nearly the same as in AddVector // only two instructions 'adc' are changed to 'sbb' uint dummy1, dummy2, dummy3; uint rest = ss1_size - ss2_size; __asm__ __volatile__( "mov %%rdx, %%r8 \n" "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0 "1: \n" "mov (%%rsi,%%rdx,8), %%rax \n" "sbb (%%rbx,%%rdx,8), %%rax \n" "mov %%rax, (%%rdi,%%rdx,8) \n" "inc %%rdx \n" "dec %%rcx \n" "jnz 1b \n" "adc %%rcx, %%rcx \n" // rcx has the cf state "or %%r8, %%r8 \n" "jz 3f \n" "xor %%rbx, %%rbx \n" // ebx = 0 "neg %%rcx \n" // setting cf from rcx "mov %%r8, %%rcx \n" // rcx=rest and is != 0 "2: \n" "mov (%%rsi, %%rdx, 8), %%rax \n" "sbb %%rbx, %%rax \n" "mov %%rax, (%%rdi, %%rdx, 8) \n" "inc %%rdx \n" "dec %%rcx \n" "jnz 2b \n" "adc %%rcx, %%rcx \n" "3: \n" : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3) : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result) : "%r8", "cc", "memory" ); #endif TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) return c; } /*! this method moves all bits into the left hand side return value <- this <- c the lowest *bit* will be held the 'c' and the state of one additional bit (on the left hand side) will be returned for example: let this is 001010000 after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 ***this method is created only on a 64bit platform*** */ template uint UInt::Rcl2_one(uint c) { sint b = value_size; uint * p1 = table; #ifndef __GNUC__ c = ttmath_rcl_x64(p1,b,c); #endif #ifdef __GNUC__ uint dummy, dummy2; __asm__ __volatile__( "xorq %%rdx, %%rdx \n" // rdx=0 "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "1: \n" "rclq $1, (%%rbx, %%rdx, 8) \n" "incq %%rdx \n" "decq %%rcx \n" "jnz 1b \n" "adcq %%rcx, %%rcx \n" : "=c" (c), "=a" (dummy), "=d" (dummy2) : "0" (b), "1" (c), "b" (p1) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::Rcl2_one", c) return c; } /*! this method moves all bits into the right hand side c -> this -> return value the highest *bit* will be held the 'c' and the state of one additional bit (on the right hand side) will be returned for example: let this is 000000010 after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 ***this method is created only on a 64bit platform*** */ template uint UInt::Rcr2_one(uint c) { sint b = value_size; uint * p1 = table; #ifndef __GNUC__ c = ttmath_rcr_x64(p1,b,c); #endif #ifdef __GNUC__ uint dummy; __asm__ __volatile__( "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0 "1: \n" "rcrq $1, -8(%%rbx, %%rcx, 8) \n" "decq %%rcx \n" "jnz 1b \n" "adcq %%rcx, %%rcx \n" : "=c" (c), "=a" (dummy) : "0" (b), "1" (c), "b" (p1) : "cc", "memory" ); #endif TTMATH_LOGC("UInt::Rcr2_one", c) return c; } /*! this method moves all bits into the left hand side return value <- this <- c the lowest *bits* will be held the 'c' and the state of one additional bit (on the left hand side) will be returned for example: let this is 001010000 after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 ***this method is created only on a 64bit platform*** */ template uint UInt::Rcl2(uint bits, uint c) { TTMATH_ASSERT( bits>0 && bits this -> return value the highest *bits* will be held the 'c' and the state of one additional bit (on the right hand side) will be returned for example: let this is 000000010 after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 ***this method is created only on a 64bit platform*** */ template uint UInt::Rcr2(uint bits, uint c) { TTMATH_ASSERT( bits>0 && bits sint UInt::FindLeadingBitInWord(uint x) { sint result; #ifndef __GNUC__ unsigned long nIndex = 0; if( _BitScanReverse64(&nIndex,x) == 0 ) result = -1; else result = nIndex; #endif #ifdef __GNUC__ uint dummy; __asm__ ( "movq $-1, %1 \n" "bsrq %2, %0 \n" "cmovz %1, %0 \n" : "=r" (result), "=&r" (dummy) : "r" (x) : "cc" ); #endif return result; } /* this method returns the number of the highest set bit in one 64-bit word if the 'x' is zero this method returns '-1' ***this method is created only on a 64bit platform*** */ template sint UInt::FindLowestBitInWord(uint x) { sint result; #ifndef __GNUC__ unsigned long nIndex = 0; if( _BitScanForward64(&nIndex,x) == 0 ) result = -1; else result = nIndex; #endif #ifdef __GNUC__ uint dummy; __asm__ ( "movq $-1, %1 \n" "bsfq %2, %0 \n" "cmovz %1, %0 \n" : "=r" (result), "=&r" (dummy) : "r" (x) : "cc" ); #endif return result; } /*! this method sets a special bit in the 'value' and returns the last state of the bit (zero or one) ***this method is created only on a 64bit platform*** bit is from <0,63> e.g. uint x = 100; uint bit = SetBitInWord(x, 3); now: x = 108 and bit = 0 */ template uint UInt::SetBitInWord(uint & value, uint bit) { TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) uint old_bit; uint v = value; #ifndef __GNUC__ old_bit = _bittestandset64((__int64*)&value,bit) != 0; #endif #ifdef __GNUC__ __asm__ ( "btsq %%rbx, %%rax \n" "setc %%bl \n" "movzx %%bl, %%rbx \n" : "=a" (v), "=b" (old_bit) : "0" (v), "1" (bit) : "cc" ); #endif value = v; return old_bit; } /*! * * Multiplication * * */ /*! multiplication: result_high:result_low = a * b result_high - higher word of the result result_low - lower word of the result this methos never returns a carry this method is used in the second version of the multiplication algorithms ***this method is created only on a 64bit platform*** */ template void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) { /* we must use these temporary variables in order to inform the compilator that value pointed with result1 and result2 has changed this has no effect in visual studio but it's usefull when using gcc and options like -O */ uint result1_; uint result2_; #ifndef __GNUC__ result1_ = _umul128(a,b,&result2_); #endif #ifdef __GNUC__ __asm__ ( "mulq %%rdx \n" : "=a" (result1_), "=d" (result2_) : "0" (a), "1" (b) : "cc" ); #endif *result_low = result1_; *result_high = result2_; } /*! * * Division * * */ /*! this method calculates 64bits word a:b / 32bits c (a higher, b lower word) r = a:b / c and rest - remainder ***this method is created only on a 64bit platform*** * * WARNING: * if r (one word) is too small for the result or c is equal zero * there'll be a hardware interruption (0) * and probably the end of your program * */ template void UInt::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest) { uint r_; uint rest_; /* these variables have similar meaning like those in the multiplication algorithm MulTwoWords */ TTMATH_ASSERT( c != 0 ) #ifndef __GNUC__ ttmath_div_x64(&a,&b,c); r_ = a; rest_ = b; #endif #ifdef __GNUC__ __asm__ ( "divq %%rcx \n" : "=a" (r_), "=d" (rest_) : "d" (a), "a" (b), "c" (c) : "cc" ); #endif *r = r_; *rest = rest_; } } //namespace #endif //ifdef TTMATH_PLATFORM64 #endif //ifndef TTMATH_NOASM #endif discoSnp/minia/ttmath/ttmathint.h0000644000000000000000000010532612062133074016126 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2010, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathint #define headerfilettmathint /*! \file ttmathint.h \brief template class Int */ #include "ttmathuint.h" namespace ttmath { /*! \brief Int implements a big integer value with a sign value_size - how many bytes specify our value on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits value_size = 1,2,3,4,5,6.... */ template class Int : public UInt { public: /*! this method sets the max value which this class can hold (all bits will be one besides the last one) */ void SetMax() { UInt::SetMax(); UInt::table[value_size-1] = ~ TTMATH_UINT_HIGHEST_BIT; } /*! this method sets the min value which this class can hold (all bits will be zero besides the last one which is one) */ void SetMin() { UInt::SetZero(); UInt::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT; } /*! this method sets -1 as the value (-1 is equal the max value in an unsigned type) */ void SetSignOne() { UInt::SetMax(); } /*! we change the sign of the value if it isn't possible to change the sign this method returns 1 else return 0 and changing the sign */ uint ChangeSign() { /* if the value is equal that one which has been returned from SetMin (only the highest bit is set) that means we can't change sign because the value is too big (bigger about one) e.g. when value_size = 1 and value is -2147483648 we can't change it to the 2147483648 because the max value which can be held is 2147483647 we don't change the value and we're using this fact somewhere in some methods (if we look on our value without the sign we get the correct value eg. -2147483648 in Int<1> will be 2147483648 on the UInt<1> type) */ if( UInt::IsOnlyTheHighestBitSet() ) return 1; UInt temp(*this); UInt::SetZero(); UInt::Sub(temp); return 0; } /*! this method sets the sign e.g. 1 -> -1 -2 -> -2 from a positive value we make a negative value, if the value is negative we do nothing */ void SetSign() { if( IsSign() ) return; ChangeSign(); } /*! this method returns true if there's the sign (the highest bit will be converted to the bool) */ bool IsSign() const { return UInt::IsTheHighestBitSet(); } /*! it sets an absolute value it can return carry (1) (look on ChangeSign() for details) */ uint Abs() { if( !IsSign() ) return 0; return ChangeSign(); } /*! * * basic mathematic functions * */ private: uint CorrectCarryAfterAdding(bool p1_is_sign, bool p2_is_sign) { if( !p1_is_sign && !p2_is_sign ) { if( UInt::IsTheHighestBitSet() ) return 1; } if( p1_is_sign && p2_is_sign ) { if( ! UInt::IsTheHighestBitSet() ) return 1; } return 0; } public: /*! this method adds two value with a sign and returns a carry we're using methods from the base class because values are stored with U2 we must only make the carry correction this = p1(=this) + p2 when p1>=0 i p2>=0 carry is set when the highest bit of value is set when p1<0 i p2<0 carry is set when the highest bit of value is clear when p1>=0 i p2<0 carry will never be set when p1<0 i p2>=0 carry will never be set */ uint Add(const Int & ss2) { bool p1_is_sign = IsSign(); bool p2_is_sign = ss2.IsSign(); UInt::Add(ss2); return CorrectCarryAfterAdding(p1_is_sign, p2_is_sign); } /*! this method adds one *unsigned* word (at a specific position) and returns a carry (if it was) look at a description in UInt<>::AddInt(...) */ uint AddInt(uint value, uint index = 0) { bool p1_is_sign = IsSign(); UInt::AddInt(value, index); return CorrectCarryAfterAdding(p1_is_sign, false); } /*! this method adds two *unsigned* words to the existing value and these words begin on the 'index' position index should be equal or smaller than value_size-2 (index <= value_size-2) x1 - lower word, x2 - higher word look at a description in UInt<>::AddTwoInts(...) */ uint AddTwoInts(uint x2, uint x1, uint index) { bool p1_is_sign = IsSign(); UInt::AddTwoInts(x2, x1, index); return CorrectCarryAfterAdding(p1_is_sign, false); } private: uint CorrectCarryAfterSubtracting(bool p1_is_sign, bool p2_is_sign) { if( !p1_is_sign && p2_is_sign ) { if( UInt::IsTheHighestBitSet() ) return 1; } if( p1_is_sign && !p2_is_sign ) { if( ! UInt::IsTheHighestBitSet() ) return 1; } return 0; } public: /*! this method subtracts two values with a sign we don't use the previous Add because the method ChangeSign can sometimes return carry this = p1(=this) - p2 when p1>=0 i p2>=0 carry will never be set when p1<0 i p2<0 carry will never be set when p1>=0 i p2<0 carry is set when the highest bit of value is set when p1<0 i p2>=0 carry is set when the highest bit of value is clear */ uint Sub(const Int & ss2) { bool p1_is_sign = IsSign(); bool p2_is_sign = ss2.IsSign(); UInt::Sub(ss2); return CorrectCarryAfterSubtracting(p1_is_sign, p2_is_sign); } /*! this method subtracts one *unsigned* word (at a specific position) and returns a carry (if it was) */ uint SubInt(uint value, uint index = 0) { bool p1_is_sign = IsSign(); UInt::SubInt(value, index); return CorrectCarryAfterSubtracting(p1_is_sign, false); } /*! this method adds one to the value and returns carry */ uint AddOne() { bool p1_is_sign = IsSign(); UInt::AddOne(); return CorrectCarryAfterAdding(p1_is_sign, false); } /*! this method subtracts one from the value and returns carry */ uint SubOne() { bool p1_is_sign = IsSign(); UInt::SubOne(); return CorrectCarryAfterSubtracting(p1_is_sign, false); } private: uint CheckMinCarry(bool ss1_is_sign, bool ss2_is_sign) { /* we have to examine the sign of the result now but if the result is with the sign then: 1. if the signs were the same that means the result is too big (the result must be without a sign) 2. if the signs were different that means if the result is different from that one which has been returned from SetMin() that is carry (result too big) but if the result is equal SetMin() there'll be ok (and the next SetSign will has no effect because the value is actually negative -- look at description of that case in ChangeSign()) */ if( IsSign() ) { if( ss1_is_sign != ss2_is_sign ) { /* there can be one case where signs are different and the result will be equal the value from SetMin() (only the highest bit is set) (this situation is ok) */ if( !UInt::IsOnlyTheHighestBitSet() ) return 1; } else { // signs were the same return 1; } } return 0; } public: /*! multiplication: this = this * ss2 it can return a carry */ uint MulInt(sint ss2) { bool ss1_is_sign, ss2_is_sign; uint c; ss1_is_sign = IsSign(); /* we don't have to check the carry from Abs (values will be correct because next we're using the method MulInt from the base class UInt which is without a sign) */ Abs(); if( ss2 < 0 ) { ss2 = -ss2; ss2_is_sign = true; } else { ss2_is_sign = false; } c = UInt::MulInt((uint)ss2); c += CheckMinCarry(ss1_is_sign, ss2_is_sign); if( ss1_is_sign != ss2_is_sign ) SetSign(); return c; } /*! multiplication this = this * ss2 it returns carry if the result is too big (we're using the method from the base class but we have to make one correction in account of signs) */ uint Mul(Int ss2) { bool ss1_is_sign, ss2_is_sign; uint c; ss1_is_sign = IsSign(); ss2_is_sign = ss2.IsSign(); /* we don't have to check the carry from Abs (values will be correct because next we're using the method Mul from the base class UInt which is without a sign) */ Abs(); ss2.Abs(); c = UInt::Mul(ss2); c += CheckMinCarry(ss1_is_sign, ss2_is_sign); if( ss1_is_sign != ss2_is_sign ) SetSign(); return c; } /*! division this = this / ss2 returned values: 0 - ok 1 - division by zero for example: (result means 'this') 20 / 3 --> result: 6 remainder: 2 -20 / 3 --> result: -6 remainder: -2 20 / -3 --> result: -6 remainder: 2 -20 / -3 --> result: 6 remainder: -2 in other words: this(old) = ss2 * this(new)(result) + remainder */ uint Div(Int ss2, Int * remainder = 0) { bool ss1_is_sign, ss2_is_sign; ss1_is_sign = IsSign(); ss2_is_sign = ss2.IsSign(); /* we don't have to test the carry from Abs as well as in Mul */ Abs(); ss2.Abs(); uint c = UInt::Div(ss2, remainder); if( ss1_is_sign != ss2_is_sign ) SetSign(); if( ss1_is_sign && remainder ) remainder->SetSign(); return c; } uint Div(const Int & ss2, Int & remainder) { return Div(ss2, &remainder); } /*! division this = this / ss2 (ss2 is int) returned values: 0 - ok 1 - division by zero for example: (result means 'this') 20 / 3 --> result: 6 remainder: 2 -20 / 3 --> result: -6 remainder: -2 20 / -3 --> result: -6 remainder: 2 -20 / -3 --> result: 6 remainder: -2 in other words: this(old) = ss2 * this(new)(result) + remainder */ uint DivInt(sint ss2, sint * remainder = 0) { bool ss1_is_sign, ss2_is_sign; ss1_is_sign = IsSign(); /* we don't have to test the carry from Abs as well as in Mul */ Abs(); if( ss2 < 0 ) { ss2 = -ss2; ss2_is_sign = true; } else { ss2_is_sign = false; } uint rem; uint c = UInt::DivInt((uint)ss2, &rem); if( ss1_is_sign != ss2_is_sign ) SetSign(); if( remainder ) { if( ss1_is_sign ) *remainder = -sint(rem); else *remainder = sint(rem); } return c; } uint DivInt(sint ss2, sint & remainder) { return DivInt(ss2, &remainder); } private: /*! power this = this ^ pow this can be negative pow is >= 0 */ uint Pow2(const Int & pow) { bool was_sign = IsSign(); uint c = 0; if( was_sign ) c += Abs(); uint c_temp = UInt::Pow(pow); if( c_temp > 0 ) return c_temp; // c_temp can be: 0, 1 or 2 if( was_sign && (pow.table[0] & 1) == 1 ) // negative value to the power of odd number is negative c += ChangeSign(); return (c==0)? 0 : 1; } public: /*! power this = this ^ pow return values: 0 - ok 1 - carry 2 - incorrect arguments 0^0 or 0^(-something) */ uint Pow(Int pow) { if( !pow.IsSign() ) return Pow2(pow); if( UInt::IsZero() ) // if 'pow' is negative then // 'this' must be different from zero return 2; if( pow.ChangeSign() ) return 1; Int t(*this); uint c_temp = t.Pow2(pow); if( c_temp > 0 ) return c_temp; UInt::SetOne(); if( Div(t) ) return 1; return 0; } /*! * * convertion methods * */ private: /*! an auxiliary method for converting both from UInt and Int */ template uint FromUIntOrInt(const UInt & p, bool UInt_type) { uint min_size = (value_size < argument_size)? value_size : argument_size; uint i; for(i=0 ; i::table[i] = p.table[i]; if( value_size > argument_size ) { uint fill; if( UInt_type ) fill = 0; else fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)? TTMATH_UINT_MAX_VALUE : 0; // 'this' is longer than 'p' for( ; i::table[i] = fill; } else { uint test = (UInt::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)? TTMATH_UINT_MAX_VALUE : 0; if( UInt_type && test!=0 ) return 1; for( ; i type into this class this operation has mainly sense if the value from p can be held in this type it returns a carry if the value 'p' is too big */ template uint FromInt(const Int & p) { return FromUIntOrInt(p, false); } /*! this method converts the sint type into this class */ uint FromInt(sint value) { uint fill = ( value<0 ) ? TTMATH_UINT_MAX_VALUE : 0; for(uint i=1 ; i::table[i] = fill; UInt::table[0] = uint(value); // there'll never be a carry here return 0; } /*! this method converts UInt into this class */ template uint FromUInt(const UInt & p) { return FromUIntOrInt(p, true); } /*! this method converts UInt into this class */ template uint FromInt(const UInt & p) { return FromUIntOrInt(p, true); } /*! this method converts the uint type into this class */ uint FromUInt(uint value) { for(uint i=1 ; i::table[i] = 0; UInt::table[0] = value; // there can be a carry here when the size of this value is equal one word // and the 'value' has the highest bit set if( value_size==1 && (value & TTMATH_UINT_HIGHEST_BIT)!=0 ) return 1; return 0; } /*! this method converts the uint type into this class */ uint FromInt(uint value) { return FromUInt(value); } /*! the default assignment operator */ Int & operator=(const Int & p) { FromInt(p); return *this; } /*! this operator converts an Int type to this class it doesn't return a carry */ template Int & operator=(const Int & p) { FromInt(p); return *this; } /*! this method converts the sint type to this class */ Int & operator=(sint i) { FromInt(i); return *this; } /*! a constructor for converting the uint to this class */ Int(sint i) { FromInt(i); } /*! a copy constructor */ Int(const Int & u) { FromInt(u); } /*! a constructor for copying from another types */ template Int(const Int & u) { // look that 'size' we still set as 'value_size' and not as u.value_size FromInt(u); } /*! this operator converts an UInt type to this class it doesn't return a carry */ template Int & operator=(const UInt & p) { FromUInt(p); return *this; } /*! this method converts the Uint type to this class */ Int & operator=(uint i) { FromUInt(i); return *this; } /*! a constructor for converting the uint to this class */ Int(uint i) { FromUInt(i); } /*! a constructor for copying from another types */ template Int(const UInt & u) { // look that 'size' we still set as 'value_size' and not as u.value_size FromUInt(u); } #ifdef TTMATH_PLATFORM32 /*! this method converts unsigned 64 bit int type to this class ***this method is created only on a 32bit platform*** */ uint FromUInt(ulint n) { uint c = UInt::FromUInt(n); if( c ) return 1; if( value_size == 1 ) return ((UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1; if( value_size == 2 ) return ((UInt::table[1] & TTMATH_UINT_HIGHEST_BIT) == 0) ? 0 : 1; return 0; } /*! this method converts unsigned 64 bit int type to this class ***this method is created only on a 32bit platform*** */ uint FromInt(ulint n) { return FromUInt(n); } /*! this method converts signed 64 bit int type to this class ***this method is created only on a 32bit platform*** */ uint FromInt(slint n) { uint mask = (n < 0) ? TTMATH_UINT_MAX_VALUE : 0; UInt::table[0] = (uint)(ulint)n; if( value_size == 1 ) { if( uint(ulint(n) >> 32) != mask ) return 1; return ((UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1; } UInt::table[1] = (uint)(ulint(n) >> 32); for(uint i=2 ; i::table[i] = mask; return 0; } /*! this operator converts unsigned 64 bit int type to this class ***this operator is created only on a 32bit platform*** */ Int & operator=(ulint n) { FromUInt(n); return *this; } /*! a constructor for converting unsigned 64 bit int to this class ***this constructor is created only on a 32bit platform*** */ Int(ulint n) { FromUInt(n); } /*! this operator converts signed 64 bit int type to this class ***this operator is created only on a 32bit platform*** */ Int & operator=(slint n) { FromInt(n); return *this; } /*! a constructor for converting signed 64 bit int to this class ***this constructor is created only on a 32bit platform*** */ Int(slint n) { FromInt(n); } #endif #ifdef TTMATH_PLATFORM64 /*! this method converts 32 bit unsigned int type to this class ***this operator is created only on a 64bit platform*** */ uint FromUInt(unsigned int i) { return FromUInt(uint(i)); } /*! this method converts 32 bit unsigned int type to this class ***this operator is created only on a 64bit platform*** */ uint FromInt(unsigned int i) { return FromUInt(i); } /*! this method converts 32 bit signed int type to this class ***this operator is created only on a 64bit platform*** */ uint FromInt(signed int i) { return FromInt(sint(i)); } /*! this method converts 32 bit unsigned int type to this class ***this operator is created only on a 64bit platform*** */ Int & operator=(unsigned int i) { FromUInt(i); return *this; } /*! a constructor for converting 32 bit unsigned int to this class ***this constructor is created only on a 64bit platform*** */ Int(unsigned int i) { FromUInt(i); } /*! this operator converts 32 bit signed int type to this class ***this operator is created only on a 64bit platform*** */ Int & operator=(signed int i) { FromInt(i); return *this; } /*! a constructor for converting 32 bit signed int to this class ***this constructor is created only on a 64bit platform*** */ Int(signed int i) { FromInt(i); } #endif /*! a constructor for converting string to this class (with the base=10) */ Int(const char * s) { FromString(s); } /*! a constructor for converting a string to this class (with the base=10) */ Int(const std::string & s) { FromString( s.c_str() ); } #ifndef TTMATH_DONT_USE_WCHAR /*! a constructor for converting string to this class (with the base=10) */ Int(const wchar_t * s) { FromString(s); } /*! a constructor for converting a string to this class (with the base=10) */ Int(const std::wstring & s) { FromString( s.c_str() ); } #endif /*! a default constructor we don't clear table etc. */ Int() { } /*! the destructor */ ~Int() { } /*! this method returns the lowest value from table with a sign we must be sure when we using this method whether the value will hold in an sint type or not (the rest value from table must be zero or -1) */ sint ToInt() const { return sint( UInt::table[0] ); } /*! this method converts the value to uint type can return a carry if the value is too long to store it in uint type */ uint ToUInt(uint & result) const { uint c = UInt::ToUInt(result); if( value_size == 1 ) return (result & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; return c; } /*! this method converts the value to uint type can return a carry if the value is too long to store it in uint type */ uint ToInt(uint & result) const { return ToUInt(result); } /*! this method converts the value to sint type can return a carry if the value is too long to store it in sint type */ uint ToInt(sint & result) const { result = sint( UInt::table[0] ); uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; if( (result & TTMATH_UINT_HIGHEST_BIT) != (mask & TTMATH_UINT_HIGHEST_BIT) ) return 1; for(uint i=1 ; i::table[i] != mask ) return 1; return 0; } #ifdef TTMATH_PLATFORM32 /*! this method converts the value to ulint type (64 bit unsigned integer) can return a carry if the value is too long to store it in ulint type *** this method is created only on a 32 bit platform *** */ uint ToUInt(ulint & result) const { uint c = UInt::ToUInt(result); if( value_size == 1 ) return (UInt::table[0] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; if( value_size == 2 ) return (UInt::table[1] & TTMATH_UINT_HIGHEST_BIT) == 0 ? 0 : 1; return c; } /*! this method converts the value to ulint type (64 bit unsigned integer) can return a carry if the value is too long to store it in ulint type *** this method is created only on a 32 bit platform *** */ uint ToInt(ulint & result) const { return ToUInt(result); } /*! this method converts the value to slint type (64 bit signed integer) can return a carry if the value is too long to store it in slint type *** this method is created only on a 32 bit platform *** */ uint ToInt(slint & result) const { if( value_size == 1 ) { result = slint(sint(UInt::table[0])); } else { uint low = UInt::table[0]; uint high = UInt::table[1]; result = low; result |= (ulint(high) << TTMATH_BITS_PER_UINT); uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; if( (high & TTMATH_UINT_HIGHEST_BIT) != (mask & TTMATH_UINT_HIGHEST_BIT) ) return 1; for(uint i=2 ; i::table[i] != mask ) return 1; } return 0; } #endif #ifdef TTMATH_PLATFORM64 /*! this method converts the value to a 32 bit unsigned integer can return a carry if the value is too long to store it in this type *** this method is created only on a 64 bit platform *** */ uint ToUInt(unsigned int & result) const { uint c = UInt::ToUInt(result); if( c || IsSign() ) return 1; return 0; } /*! this method converts the value to a 32 bit unsigned integer can return a carry if the value is too long to store it in this type *** this method is created only on a 64 bit platform *** */ uint ToInt(unsigned int & result) const { return ToUInt(result); } /*! this method converts the value to a 32 bit signed integer can return a carry if the value is too long to store it in this type *** this method is created only on a 64 bit platform *** */ uint ToInt(int & result) const { uint first = UInt::table[0]; result = int(first); uint mask = IsSign() ? TTMATH_UINT_MAX_VALUE : 0; if( (first >> 31) != (mask >> 31) ) return 1; for(uint i=1 ; i::table[i] != mask ) return 1; return 0; } #endif private: /*! an auxiliary method for converting to a string */ template void ToStringBase(string_type & result, uint b = 10) const { if( IsSign() ) { Int temp(*this); temp.Abs(); temp.UInt::ToString(result, b); result.insert(result.begin(), '-'); } else { UInt::ToString(result, b); } } public: /*! this method converts the value to a string with a base equal 'b' */ void ToString(std::string & result, uint b = 10) const { return ToStringBase(result, b); } /*! this method converts the value to a string with a base equal 'b' */ std::string ToString(uint b = 10) const { std::string result; ToStringBase(result, b); return result; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method converts the value to a string with a base equal 'b' */ void ToString(std::wstring & result, uint b = 10) const { return ToStringBase(result, b); } /*! this method converts the value to a string with a base equal 'b' */ std::wstring ToWString(uint b = 10) const { std::wstring result; ToStringBase(result, b); return result; } #endif private: /*! an auxiliary method for converting from a string */ template uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) { bool is_sign = false; Misc::SkipWhiteCharacters(s); if( *s == '-' ) { is_sign = true; Misc::SkipWhiteCharacters(++s); } else if( *s == '+' ) { Misc::SkipWhiteCharacters(++s); } if( UInt::FromString(s,b,after_source,value_read) ) return 1; if( is_sign ) { Int mmin; mmin.SetMin(); /* the reference to mmin will be automatically converted to the reference to UInt type (this value can be equal mmin -- look at a description in ChangeSign()) */ if( UInt::operator>( mmin ) ) return 1; /* if the value is equal mmin the method ChangeSign() does nothing (only returns 1 but we ignore it) */ ChangeSign(); } else { Int mmax; mmax.SetMax(); if( UInt::operator>( mmax ) ) return 1; } return 0; } public: /*! this method converts a string into its value it returns carry=1 if the value will be too big or an incorrect base 'b' is given string is ended with a non-digit value, for example: "-12" will be translated to -12 as well as: "- 12foo" will be translated to -12 too existing first white characters will be ommited (between '-' and a first digit can be white characters too) after_source (if exists) is pointing at the end of the parsed string value_read (if exists) tells whether something has actually been read (at least one digit) */ uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) { return FromStringBase(s, b, after_source, value_read); } /*! this method converts a string into its value */ uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) { return FromStringBase(s, b, after_source, value_read); } /*! this method converts a string into its value it returns carry=1 if the value will be too big or an incorrect base 'b' is given */ uint FromString(const std::string & s, uint b = 10) { return FromString( s.c_str(), b ); } /*! this operator converts a string into its value (with base = 10) */ Int & operator=(const char * s) { FromString(s); return *this; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method converts a string into its value it returns carry=1 if the value will be too big or an incorrect base 'b' is given */ uint FromString(const std::wstring & s, uint b = 10) { return FromString( s.c_str(), b ); } /*! this operator converts a string into its value (with base = 10) */ Int & operator=(const wchar_t * s) { FromString(s); return *this; } /*! this operator converts a string into its value (with base = 10) */ Int & operator=(const std::wstring & s) { FromString( s.c_str() ); return *this; } #endif /*! this operator converts a string into its value (with base = 10) */ Int & operator=(const std::string & s) { FromString( s.c_str() ); return *this; } /*! * * methods for comparing * * */ bool operator==(const Int & l) const { return UInt::operator==(l); } bool operator!=(const Int & l) const { return UInt::operator!=(l); } bool operator<(const Int & l) const { sint i=value_size-1; sint a1 = sint(UInt::table[i]); sint a2 = sint(l.table[i]); if( a1 != a2 ) return a1 < a2; for(--i ; i>=0 ; --i) { if( UInt::table[i] != l.table[i] ) // comparison as unsigned int return UInt::table[i] < l.table[i]; } // they're equal return false; } bool operator>(const Int & l) const { sint i=value_size-1; sint a1 = sint(UInt::table[i]); sint a2 = sint(l.table[i]); if( a1 != a2 ) return a1 > a2; for(--i ; i>=0 ; --i) { if( UInt::table[i] != l.table[i] ) // comparison as unsigned int return UInt::table[i] > l.table[i]; } // they're equal return false; } bool operator<=(const Int & l) const { sint i=value_size-1; sint a1 = sint(UInt::table[i]); sint a2 = sint(l.table[i]); if( a1 != a2 ) return a1 < a2; for(--i ; i>=0 ; --i) { if( UInt::table[i] != l.table[i] ) // comparison as unsigned int return UInt::table[i] < l.table[i]; } // they're equal return true; } bool operator>=(const Int & l) const { sint i=value_size-1; sint a1 = sint(UInt::table[i]); sint a2 = sint(l.table[i]); if( a1 != a2 ) return a1 > a2; for(--i ; i>=0 ; --i) { if( UInt::table[i] != l.table[i] ) // comparison as unsigned int return UInt::table[i] > l.table[i]; } // they're equal return true; } /*! * * standard mathematical operators * */ /*! an operator for changing the sign it's not changing 'this' but the changed value will be returned */ Int operator-() const { Int temp(*this); temp.ChangeSign(); return temp; } Int operator-(const Int & p2) const { Int temp(*this); temp.Sub(p2); return temp; } Int & operator-=(const Int & p2) { Sub(p2); return *this; } Int operator+(const Int & p2) const { Int temp(*this); temp.Add(p2); return temp; } Int & operator+=(const Int & p2) { Add(p2); return *this; } Int operator*(const Int & p2) const { Int temp(*this); temp.Mul(p2); return temp; } Int & operator*=(const Int & p2) { Mul(p2); return *this; } Int operator/(const Int & p2) const { Int temp(*this); temp.Div(p2); return temp; } Int & operator/=(const Int & p2) { Div(p2); return *this; } Int operator%(const Int & p2) const { Int temp(*this); Int remainder; temp.Div(p2, remainder); return remainder; } Int & operator%=(const Int & p2) { Int remainder; Div(p2, remainder); operator=(remainder); return *this; } /*! Prefix operator e.g. ++variable */ UInt & operator++() { AddOne(); return *this; } /*! Postfix operator e.g. variable++ */ UInt operator++(int) { UInt temp( *this ); AddOne(); return temp; } UInt & operator--() { SubOne(); return *this; } UInt operator--(int) { UInt temp( *this ); SubOne(); return temp; } /*! * * input/output operators for standard streams * */ private: /*! an auxiliary method for outputing to standard streams */ template static ostream_type & OutputToStream(ostream_type & s, const Int & l) { string_type ss; l.ToString(ss); s << ss; return s; } public: /*! output to standard streams */ friend std::ostream & operator<<(std::ostream & s, const Int & l) { return OutputToStream(s, l); } #ifndef TTMATH_DONT_USE_WCHAR /*! output to standard streams */ friend std::wostream & operator<<(std::wostream & s, const Int & l) { return OutputToStream(s, l); } #endif private: /*! an auxiliary method for converting from a string */ template static istream_type & InputFromStream(istream_type & s, Int & l) { string_type ss; // char or wchar_t for operator>> char_type z; // operator>> omits white characters if they're set for ommiting s >> z; if( z=='-' || z=='+' ) { ss += z; s >> z; // we're reading a next character (white characters can be ommited) } // we're reading only digits (base=10) while( s.good() && Misc::CharToDigit(z, 10)>=0 ) { ss += z; z = static_cast(s.get()); } // we're leaving the last readed character // (it's not belonging to the value) s.unget(); l.FromString(ss); return s; } public: /*! input from standard streams */ friend std::istream & operator>>(std::istream & s, Int & l) { return InputFromStream(s, l); } #ifndef TTMATH_DONT_USE_WCHAR /*! input from standard streams */ friend std::wistream & operator>>(std::wistream & s, Int & l) { return InputFromStream(s, l); } #endif }; } // namespace #endif discoSnp/minia/ttmath/ttmathuint_x86_64_msvc.asm0000644000000000000000000002360012062133074020704 0ustar rootroot; ; This file is a part of TTMath Bignum Library ; and is distributed under the (new) BSD licence. ; Author: Christian Kaiser ; ; ; Copyright (c) 2009, Christian Kaiser ; 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 Christian Kaiser nor the names of contributors to this ; project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. ; ; ; compile with debug info: ml64.exe /c /Zd /Zi ttmathuint_x86_64_msvc.asm ; compile without debug info: ml64.exe /c ttmathuint_x86_64_msvc.asm ; this creates ttmathuint_x86_64_msvc.obj file which can be linked with your program ; PUBLIC ttmath_adc_x64 PUBLIC ttmath_addindexed_x64 PUBLIC ttmath_addindexed2_x64 PUBLIC ttmath_addvector_x64 PUBLIC ttmath_sbb_x64 PUBLIC ttmath_subindexed_x64 PUBLIC ttmath_subvector_x64 PUBLIC ttmath_rcl_x64 PUBLIC ttmath_rcr_x64 PUBLIC ttmath_rcl2_x64 PUBLIC ttmath_rcr2_x64 PUBLIC ttmath_div_x64 ; ; Microsoft x86_64 convention: http://msdn.microsoft.com/en-us/library/9b372w95.aspx ; ; "rax, rcx, rdx, r8-r11 are volatile." ; "rbx, rbp, rdi, rsi, r12-r15 are nonvolatile." ; .CODE ALIGN 8 ;---------------------------------------- ttmath_adc_x64 PROC ; rcx = p1 ; rdx = p2 ; r8 = nSize ; r9 = nCarry xor rax, rax xor r11, r11 sub rax, r9 ; sets CARRY if r9 != 0 ALIGN 16 loop1: mov rax,qword ptr [rdx + r11 * 8] adc qword ptr [rcx + r11 * 8], rax lea r11, [r11+1] dec r8 jnz loop1 setc al movzx rax, al ret ttmath_adc_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ttmath_addindexed_x64 PROC ; rcx = p1 ; rdx = nSize ; r8 = nPos ; r9 = nValue xor rax, rax ; rax = result sub rdx, r8 ; rdx = remaining count of uints add qword ptr [rcx + r8 * 8], r9 jc next1 ret next1: mov r9, 1 ALIGN 16 loop1: dec rdx jz done_with_cy lea r8, [r8+1] add qword ptr [rcx + r8 * 8], r9 jc loop1 ret done_with_cy: lea rax, [rax+1] ; rax = 1 ret ttmath_addindexed_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ttmath_addindexed2_x64 PROC ; rcx = p1 (pointer) ; rdx = b (value size) ; r8 = nPos ; r9 = nValue1 ; [esp+0x28] = nValue2 xor rax, rax ; return value mov r11, rcx ; table sub rdx, r8 ; rdx = remaining count of uints mov r10, [esp+028h] ; r10 = nValue2 add qword ptr [r11 + r8 * 8], r9 lea r8, [r8+1] lea rdx, [rdx-1] adc qword ptr [r11 + r8 * 8], r10 jc next ret ALIGN 16 loop1: lea r8, [r8+1] add qword ptr [r11 + r8 * 8], 1 jc next ret next: dec rdx ; does not modify CY too... jnz loop1 lea rax, [rax+1] ret ttmath_addindexed2_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ttmath_addvector_x64 PROC ; rcx = ss1 ; rdx = ss2 ; r8 = ss1_size ; r9 = ss2_size ; [esp+0x28] = result mov r10, [esp+028h] sub r8, r9 xor r11, r11 ; r11=0, cf=0 ALIGN 16 loop1: mov rax, qword ptr [rcx + r11 * 8] adc rax, qword ptr [rdx + r11 * 8] mov qword ptr [r10 + r11 * 8], rax inc r11 dec r9 jnz loop1 adc r9, r9 ; r9 has the cf state or r8, r8 jz done neg r9 ; setting cf from r9 mov r9, 0 ; don't use xor here (cf is used) loop2: mov rax, qword ptr [rcx + r11 * 8] adc rax, r9 mov qword ptr [r10 + r11 * 8], rax inc r11 dec r8 jnz loop2 adc r8, r8 mov rax, r8 ret done: mov rax, r9 ret ttmath_addvector_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ttmath_sbb_x64 PROC ; rcx = p1 ; rdx = p2 ; r8 = nCount ; r9 = nCarry xor rax, rax xor r11, r11 sub rax, r9 ; sets CARRY if r9 != 0 ALIGN 16 loop1: mov rax,qword ptr [rdx + r11 * 8] sbb qword ptr [rcx + r11 * 8], rax lea r11, [r11+1] dec r8 jnz loop1 setc al movzx rax, al ret ttmath_sbb_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ttmath_subindexed_x64 PROC ; rcx = p1 ; rdx = nSize ; r8 = nPos ; r9 = nValue sub rdx, r8 ; rdx = remaining count of uints ALIGN 16 loop1: sub qword ptr [rcx + r8 * 8], r9 jnc done lea r8, [r8+1] mov r9, 1 dec rdx jnz loop1 mov rax, 1 ret done: xor rax, rax ret ttmath_subindexed_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ; the same asm code as in addvector_x64 only two instructions 'adc' changed to 'sbb' ttmath_subvector_x64 PROC ; rcx = ss1 ; rdx = ss2 ; r8 = ss1_size ; r9 = ss2_size ; [esp+0x28] = result mov r10, [esp+028h] sub r8, r9 xor r11, r11 ; r11=0, cf=0 ALIGN 16 loop1: mov rax, qword ptr [rcx + r11 * 8] sbb rax, qword ptr [rdx + r11 * 8] mov qword ptr [r10 + r11 * 8], rax inc r11 dec r9 jnz loop1 adc r9, r9 ; r9 has the cf state or r8, r8 jz done neg r9 ; setting cf from r9 mov r9, 0 ; don't use xor here (cf is used) loop2: mov rax, qword ptr [rcx + r11 * 8] sbb rax, r9 mov qword ptr [r10 + r11 * 8], rax inc r11 dec r8 jnz loop2 adc r8, r8 mov rax, r8 ret done: mov rax, r9 ret ttmath_subvector_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ttmath_rcl_x64 PROC ; rcx = p1 ; rdx = b ; r8 = nLowestBit mov r11, rcx ; table xor r10, r10 neg r8 ; CY set if r8 <> 0 ALIGN 16 loop1: rcl qword ptr [r11 + r10 * 8], 1 lea r10, [r10+1] dec rdx jnz loop1 setc al movzx rax, al ret ttmath_rcl_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ttmath_rcr_x64 PROC ; rcx = p1 ; rdx = nSize ; r8 = nLowestBit xor r10, r10 neg r8 ; CY set if r8 <> 0 ALIGN 16 loop1: rcr qword ptr -8[rcx + rdx * 8], 1 dec rdx jnz loop1 setc al movzx rax, al ret ttmath_rcr_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ttmath_div_x64 PROC ; rcx = &Hi ; rdx = &Lo ; r8 = nDiv mov r11, rcx mov r10, rdx mov rdx, qword ptr [r11] mov rax, qword ptr [r10] div r8 mov qword ptr [r10], rdx ; remainder mov qword ptr [r11], rax ; value ret ttmath_div_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ttmath_rcl2_x64 PROC ; rcx = p1 ; rdx = nSize ; r8 = bits ; r9 = c push rbx mov r10, rcx ; r10 = p1 xor rax, rax mov rcx, 64 sub rcx, r8 mov r11, -1 shr r11, cl ; r11 = mask mov rcx, r8 ; rcx = count of bits mov rbx, rax ; rbx = old value = 0 or r9, r9 cmovnz rbx, r11 ; if (c) then old value = mask mov r9, rax ; r9 = index (0..nSize-1) ALIGN 16 loop1: rol qword ptr [r10+r9*8], cl mov rax, qword ptr [r10+r9*8] and rax, r11 xor qword ptr [r10+r9*8], rax or qword ptr [r10+r9*8], rbx mov rbx, rax lea r9, [r9+1] dec rdx jnz loop1 and rax, 1 pop rbx ret ttmath_rcl2_x64 ENDP ;---------------------------------------- ALIGN 8 ;---------------------------------------- ttmath_rcr2_x64 PROC ; rcx = p1 ; rdx = nSize ; r8 = bits ; r9 = c push rbx mov r10, rcx ; r10 = p1 xor rax, rax mov rcx, 64 sub rcx, r8 mov r11, -1 shl r11, cl ; r11 = mask mov rcx, r8 ; rcx = count of bits mov rbx, rax ; rbx = old value = 0 or r9, r9 cmovnz rbx, r11 ; if (c) then old value = mask mov r9, rdx ; r9 = index (0..nSize-1) lea r9, [r9-1] ALIGN 16 loop1: ror qword ptr [r10+r9*8], cl mov rax, qword ptr [r10+r9*8] and rax, r11 xor qword ptr [r10+r9*8], rax or qword ptr [r10+r9*8], rbx mov rbx, rax lea r9, [r9-1] dec rdx jnz loop1 rol rax, 1 and rax, 1 pop rbx ret ttmath_rcr2_x64 ENDP END discoSnp/minia/ttmath/ttmathparser.h0000644000000000000000000016267612062133074016643 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2010, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathparser #define headerfilettmathparser /*! \file ttmathparser.h \brief A mathematical parser */ #include #include #include #include #include "ttmath.h" #include "ttmathobjects.h" #include "ttmathmisc.h" namespace ttmath { /*! \brief Mathematical parser let x will be an input string meaning an expression for converting: x = [+|-]Value[operator[+|-]Value][operator[+|-]Value]... where: an operator can be: ^ (pow) (the heighest priority) * (mul) (or multiplication without an operator -- short mul) / (div) (* and / have the same priority) + (add) - (sub) (+ and - have the same priority) < (lower than) > (greater than) <= (lower or equal than) >= (greater or equal than) == (equal) != (not equal) (all above logical operators have the same priority) && (logical and) || (logical or) (the lowest priority) short mul: if the second Value (Var below) is either a variable or function there might not be an operator between them, e.g. "[+|-]Value Var" is treated as "[+|-]Value * Var" and the multiplication has the same priority as a normal multiplication: 4x = 4 * x 2^3m = (2^3)* m 6h^3 = 6 * (h^3) 2sin(pi) = 2 * sin(pi) etc. Value can be: constant e.g. 100, can be preceded by operators for changing the base (radix): [#|&] # - hex & - bin sample: #10 = 16 &10 = 2 variable e.g. pi another expression between brackets e.g (x) function e.g. sin(x) for example a correct input string can be: "1" "2.1234" "2,1234" (they are the same, by default we can either use a comma or a dot) "1 + 2" "(1 + 2) * 3" "pi" "sin(pi)" "(1+2)*(2+3)" "log(2;1234)" there's a semicolon here (not a comma), we use it in functions for separating parameters "1 < 2" (the result will be: 1) "4 < 3" (the result will be: 0) "2+x" (of course if the variable 'x' is defined) "4x+10" "#20+10" = 32 + 10 = 42 "10 ^ -&101" = 10 ^ -5 = 0.00001 "8 * -&10" = 8 * -2 = -16 etc. we can also use a semicolon for separating any 'x' input strings for example: "1+2;4+5" the result will be on the stack as follows: stack[0].value=3 stack[1].value=9 */ template class Parser { private: /*! there are 5 mathematical operators as follows (with their standard priorities): add (+) sub (-) mul (*) div (/) pow (^) and 'shortmul' used when there is no any operators between a first parameter and a variable or function (the 'shortmul' has the same priority as the normal multiplication ) */ class MatOperator { public: enum Type { none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul }; enum Assoc { right, // right-associative non_right // associative or left-associative }; Type GetType() const { return type; } int GetPriority() const { return priority; } Assoc GetAssoc() const { return assoc; } void SetType(Type t) { type = t; assoc = non_right; switch( type ) { case lor: priority = 4; break; case land: priority = 5; break; case eq: case neq: case lt: case gt: case let: case get: priority = 7; break; case add: case sub: priority = 10; break; case mul: case shortmul: case div: priority = 12; break; case pow: priority = 14; assoc = right; break; default: Error( err_internal_error ); break; } } MatOperator(): type(none), priority(0), assoc(non_right) { } private: Type type; int priority; Assoc assoc; }; // end of MatOperator class public: /*! Objects of type 'Item' we are keeping on our stack */ struct Item { enum Type { none, numerical_value, mat_operator, first_bracket, last_bracket, variable, semicolon }; // The kind of type which we're keeping Type type; // if type == numerical_value ValueType value; // if type == mat_operator MatOperator moperator; /* if type == first_bracket if 'function' is set to true it means that the first recognized bracket was the bracket from function in other words we must call a function when we'll find the 'last' bracket */ bool function; // if function is true std::string function_name; /* the sign of value it can be for type==numerical_value or type==first_bracket when it's true it means e.g. that value is equal -value */ bool sign; Item(): type(none), function(false), sign(false) { } }; // end of Item struct /*! stack on which we're keeping the Items at the end of parsing we'll have the result here the result don't have to be one value, it can be more than one if we have used a semicolon in the global space e.g. such input string "1+2;3+4" will generate a result: stack[0].value=3 stack[1].value=7 you should check if the stack is not empty, because if there was a syntax error in the input string then we do not have any results on the stack */ std::vector stack; private: /*! size of the stack when we're starting parsing of the string if it's to small while parsing the stack will be automatically resized */ const int default_stack_size; /*! index of an object in our stack it's pointing on the place behind the last element for example at the beginning of parsing its value is zero */ unsigned int stack_index; /*! code of the last error */ ErrorCode error; /*! pointer to the currently reading char when an error has occured it may be used to count the index of the wrong character */ const char * pstring; /*! the base (radix) of the mathematic system (for example it may be '10') */ int base; /*! the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot 0 - deg 1 - rad (default) 2 - grad */ int deg_rad_grad; /*! a pointer to an object which tell us whether we should stop calculating or not */ const volatile StopCalculating * pstop_calculating; /*! a pointer to the user-defined variables' table */ const Objects * puser_variables; /*! a pointer to the user-defined functions' table */ const Objects * puser_functions; typedef std::map FunctionLocalVariables; /*! a pointer to the local variables of a function */ const FunctionLocalVariables * pfunction_local_variables; /*! a temporary set using during parsing user defined variables */ std::set visited_variables; /*! a temporary set using during parsing user defined functions */ std::set visited_functions; /*! pfunction is the type of pointer to a mathematic function these mathematic functions are private members of this class, they are the wrappers for standard mathematics function 'pstack' is the pointer to the first argument on our stack 'amount_of_arg' tell us how many argument there are in our stack 'result' is the reference for result of function */ typedef void (Parser::*pfunction)(int pstack, int amount_of_arg, ValueType & result); /*! pfunction is the type of pointer to a method which returns value of variable */ typedef void (ValueType::*pfunction_var)(); /*! table of mathematic functions this map consists of: std::string - function's name pfunction - pointer to specific function */ typedef std::map FunctionsTable; FunctionsTable functions_table; /*! table of mathematic operators this map consists of: std::string - operators's name MatOperator::Type - type of the operator */ typedef std::map OperatorsTable; OperatorsTable operators_table; /*! table of mathematic variables this map consists of: std::string - variable's name pfunction_var - pointer to specific function which returns value of variable */ typedef std::map VariablesTable; VariablesTable variables_table; /*! some coefficients used when calculating the gamma (or factorial) function */ CGamma cgamma; /*! temporary object for a whole string when Parse(std::wstring) is used */ std::string wide_to_ansi; /*! group character (used when parsing) default zero (not used) */ int group; /*! characters used as a comma default: '.' and ',' comma2 can be zero (it means it is not used) */ int comma, comma2; /*! an additional character used as a separator between function parameters (semicolon is used always) */ int param_sep; /*! true if something was calculated (at least one mathematical operator was used or a function or a variable) */ bool calculated; /*! we're using this method for reporting an error */ static void Error(ErrorCode code) { throw code; } /*! this method skips the white character from the string it's moving the 'pstring' to the first no-white character */ void SkipWhiteCharacters() { while( (*pstring==' ' ) || (*pstring=='\t') ) ++pstring; } /*! an auxiliary method for RecurrenceParsingVariablesOrFunction(...) */ void RecurrenceParsingVariablesOrFunction_CheckStopCondition(bool variable, const std::string & name) { if( variable ) { if( visited_variables.find(name) != visited_variables.end() ) Error( err_variable_loop ); } else { if( visited_functions.find(name) != visited_functions.end() ) Error( err_functions_loop ); } } /*! an auxiliary method for RecurrenceParsingVariablesOrFunction(...) */ void RecurrenceParsingVariablesOrFunction_AddName(bool variable, const std::string & name) { if( variable ) visited_variables.insert( name ); else visited_functions.insert( name ); } /*! an auxiliary method for RecurrenceParsingVariablesOrFunction(...) */ void RecurrenceParsingVariablesOrFunction_DeleteName(bool variable, const std::string & name) { if( variable ) visited_variables.erase( name ); else visited_functions.erase( name ); } /*! this method returns the value of a variable or function by creating a new instance of the mathematical parser and making the standard parsing algorithm on the given string this method is used only during parsing user defined variables or functions (there can be a recurrence here therefore we're using 'visited_variables' and 'visited_functions' sets to make a stop condition) */ ValueType RecurrenceParsingVariablesOrFunction(bool variable, const std::string & name, const char * new_string, FunctionLocalVariables * local_variables = 0) { RecurrenceParsingVariablesOrFunction_CheckStopCondition(variable, name); RecurrenceParsingVariablesOrFunction_AddName(variable, name); Parser NewParser(*this); ErrorCode err; NewParser.pfunction_local_variables = local_variables; try { err = NewParser.Parse(new_string); } catch(...) { RecurrenceParsingVariablesOrFunction_DeleteName(variable, name); throw; } RecurrenceParsingVariablesOrFunction_DeleteName(variable, name); if( err != err_ok ) Error( err ); if( NewParser.stack.size() != 1 ) Error( err_must_be_only_one_value ); if( NewParser.stack[0].type != Item::numerical_value ) // I think there shouldn't be this error here Error( err_incorrect_value ); return NewParser.stack[0].value; } public: /*! this method returns the user-defined value of a variable */ bool GetValueOfUserDefinedVariable(const std::string & variable_name,ValueType & result) { if( !puser_variables ) return false; const char * string_value; if( puser_variables->GetValue(variable_name, &string_value) != err_ok ) return false; result = RecurrenceParsingVariablesOrFunction(true, variable_name, string_value); calculated = true; return true; } /*! this method returns the value of a local variable of a function */ bool GetValueOfFunctionLocalVariable(const std::string & variable_name, ValueType & result) { if( !pfunction_local_variables ) return false; typename FunctionLocalVariables::const_iterator i = pfunction_local_variables->find(variable_name); if( i == pfunction_local_variables->end() ) return false; result = i->second; return true; } /*! this method returns the value of a variable from variables' table we make an object of type ValueType then call a method which sets the correct value in it and finally we'll return the object */ ValueType GetValueOfVariable(const std::string & variable_name) { ValueType result; if( GetValueOfFunctionLocalVariable(variable_name, result) ) return result; if( GetValueOfUserDefinedVariable(variable_name, result) ) return result; typename std::map::iterator i = variables_table.find(variable_name); if( i == variables_table.end() ) Error( err_unknown_variable ); (result.*(i->second))(); calculated = true; return result; } private: /*! wrappers for mathematic functions 'sindex' is pointing on the first argument on our stack (the second argument has 'sindex+2' because 'sindex+1' is guaranted for the 'semicolon' operator) the third artument has of course 'sindex+4' etc. 'result' will be the result of the function (we're using exceptions here for example when function gets an improper argument) */ /*! used by: sin,cos,tan,cot */ ValueType ConvertAngleToRad(const ValueType & input) { if( deg_rad_grad == 1 ) // rad return input; ValueType result; ErrorCode err; if( deg_rad_grad == 0 ) // deg result = ttmath::DegToRad(input, &err); else // grad result = ttmath::GradToRad(input, &err); if( err != err_ok ) Error( err ); return result; } /*! used by: asin,acos,atan,acot */ ValueType ConvertRadToAngle(const ValueType & input) { if( deg_rad_grad == 1 ) // rad return input; ValueType result; ErrorCode err; if( deg_rad_grad == 0 ) // deg result = ttmath::RadToDeg(input, &err); else // grad result = ttmath::RadToGrad(input, &err); if( err != err_ok ) Error( err ); return result; } void Gamma(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); ErrorCode err; result = ttmath::Gamma(stack[sindex].value, cgamma, &err, pstop_calculating); if(err != err_ok) Error( err ); } /*! factorial result = 1 * 2 * 3 * 4 * .... * x */ void Factorial(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); ErrorCode err; result = ttmath::Factorial(stack[sindex].value, cgamma, &err, pstop_calculating); if(err != err_ok) Error( err ); } void Abs(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); result = ttmath::Abs(stack[sindex].value); } void Sin(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); ErrorCode err; result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value), &err ); if(err != err_ok) Error( err ); } void Cos(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); ErrorCode err; result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value), &err ); if(err != err_ok) Error( err ); } void Tan(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); ErrorCode err; result = ttmath::Tan(ConvertAngleToRad(stack[sindex].value), &err); if(err != err_ok) Error( err ); } void Cot(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); ErrorCode err; result = ttmath::Cot(ConvertAngleToRad(stack[sindex].value), &err); if(err != err_ok) Error( err ); } void Int(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); result = ttmath::SkipFraction(stack[sindex].value); } void Round(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); result = stack[sindex].value; if( result.Round() ) Error( err_overflow ); } void Ln(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); ErrorCode err; result = ttmath::Ln(stack[sindex].value, &err); if(err != err_ok) Error( err ); } void Log(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 2 ) Error( err_improper_amount_of_arguments ); ErrorCode err; result = ttmath::Log(stack[sindex].value, stack[sindex+2].value, &err); if(err != err_ok) Error( err ); } void Exp(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); ErrorCode err; result = ttmath::Exp(stack[sindex].value, &err); if(err != err_ok) Error( err ); } void Max(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args == 0 ) { result.SetMax(); return; } result = stack[sindex].value; for(int i=1 ; i stack[sindex + i*2].value ) result = stack[sindex + i*2].value; } } void ASin(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); ErrorCode err; ValueType temp = ttmath::ASin(stack[sindex].value, &err); if(err != err_ok) Error( err ); result = ConvertRadToAngle(temp); } void ACos(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); ErrorCode err; ValueType temp = ttmath::ACos(stack[sindex].value, &err); if(err != err_ok) Error( err ); result = ConvertRadToAngle(temp); } void ATan(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); result = ConvertRadToAngle(ttmath::ATan(stack[sindex].value)); } void ACot(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); result = ConvertRadToAngle(ttmath::ACot(stack[sindex].value)); } void Sgn(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); result = ttmath::Sgn(stack[sindex].value); } void Mod(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 2 ) Error( err_improper_amount_of_arguments ); if( stack[sindex+2].value.IsZero() ) Error( err_improper_argument ); result = stack[sindex].value; uint c = result.Mod(stack[sindex+2].value); if( c ) Error( err_overflow ); } void If(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 3 ) Error( err_improper_amount_of_arguments ); if( !stack[sindex].value.IsZero() ) result = stack[sindex+2].value; else result = stack[sindex+4].value; } void Or(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args < 2 ) Error( err_improper_amount_of_arguments ); for(int i=0 ; iGetValueAndParam(function_name, &string_value, ¶m) != err_ok ) return false; if( param != amount_of_args ) Error( err_improper_amount_of_arguments ); FunctionLocalVariables local_variables; if( amount_of_args > 0 ) { char buffer[30]; // x = x1 buffer[0] = 'x'; buffer[1] = 0; local_variables.insert( std::make_pair(buffer, stack[sindex].value) ); for(int i=0 ; i*(i->second))(sindex, amount_of_args, stack[sindex-1].value); calculated = true; } /*! inserting a function to the functions' table function_name - name of the function pf - pointer to the function (to the wrapper) */ void InsertFunctionToTable(const char * function_name, pfunction pf) { std::string str; Misc::AssignString(str, function_name); functions_table.insert( std::make_pair(str, pf) ); } /*! inserting a function to the variables' table (this function returns value of variable) variable_name - name of the function pf - pointer to the function */ void InsertVariableToTable(const char * variable_name, pfunction_var pf) { std::string str; Misc::AssignString(str, variable_name); variables_table.insert( std::make_pair(str, pf) ); } /*! this method creates the table of functions */ void CreateFunctionsTable() { InsertFunctionToTable("gamma", &Parser::Gamma); InsertFunctionToTable("factorial", &Parser::Factorial); InsertFunctionToTable("abs", &Parser::Abs); InsertFunctionToTable("sin", &Parser::Sin); InsertFunctionToTable("cos", &Parser::Cos); InsertFunctionToTable("tan", &Parser::Tan); InsertFunctionToTable("tg", &Parser::Tan); InsertFunctionToTable("cot", &Parser::Cot); InsertFunctionToTable("ctg", &Parser::Cot); InsertFunctionToTable("int", &Parser::Int); InsertFunctionToTable("round", &Parser::Round); InsertFunctionToTable("ln", &Parser::Ln); InsertFunctionToTable("log", &Parser::Log); InsertFunctionToTable("exp", &Parser::Exp); InsertFunctionToTable("max", &Parser::Max); InsertFunctionToTable("min", &Parser::Min); InsertFunctionToTable("asin", &Parser::ASin); InsertFunctionToTable("acos", &Parser::ACos); InsertFunctionToTable("atan", &Parser::ATan); InsertFunctionToTable("atg", &Parser::ATan); InsertFunctionToTable("acot", &Parser::ACot); InsertFunctionToTable("actg", &Parser::ACot); InsertFunctionToTable("sgn", &Parser::Sgn); InsertFunctionToTable("mod", &Parser::Mod); InsertFunctionToTable("if", &Parser::If); InsertFunctionToTable("or", &Parser::Or); InsertFunctionToTable("and", &Parser::And); InsertFunctionToTable("not", &Parser::Not); InsertFunctionToTable("degtorad", &Parser::DegToRad); InsertFunctionToTable("radtodeg", &Parser::RadToDeg); InsertFunctionToTable("degtodeg", &Parser::DegToDeg); InsertFunctionToTable("gradtorad", &Parser::GradToRad); InsertFunctionToTable("radtograd", &Parser::RadToGrad); InsertFunctionToTable("degtograd", &Parser::DegToGrad); InsertFunctionToTable("gradtodeg", &Parser::GradToDeg); InsertFunctionToTable("ceil", &Parser::Ceil); InsertFunctionToTable("floor", &Parser::Floor); InsertFunctionToTable("sqrt", &Parser::Sqrt); InsertFunctionToTable("sinh", &Parser::Sinh); InsertFunctionToTable("cosh", &Parser::Cosh); InsertFunctionToTable("tanh", &Parser::Tanh); InsertFunctionToTable("tgh", &Parser::Tanh); InsertFunctionToTable("coth", &Parser::Coth); InsertFunctionToTable("ctgh", &Parser::Coth); InsertFunctionToTable("root", &Parser::Root); InsertFunctionToTable("asinh", &Parser::ASinh); InsertFunctionToTable("acosh", &Parser::ACosh); InsertFunctionToTable("atanh", &Parser::ATanh); InsertFunctionToTable("atgh", &Parser::ATanh); InsertFunctionToTable("acoth", &Parser::ACoth); InsertFunctionToTable("actgh", &Parser::ACoth); InsertFunctionToTable("bitand", &Parser::BitAnd); InsertFunctionToTable("bitor", &Parser::BitOr); InsertFunctionToTable("bitxor", &Parser::BitXor); InsertFunctionToTable("band", &Parser::BitAnd); InsertFunctionToTable("bor", &Parser::BitOr); InsertFunctionToTable("bxor", &Parser::BitXor); InsertFunctionToTable("sum", &Parser::Sum); InsertFunctionToTable("avg", &Parser::Avg); InsertFunctionToTable("frac", &Parser::Frac); } /*! this method creates the table of variables */ void CreateVariablesTable() { InsertVariableToTable("pi", &ValueType::SetPi); InsertVariableToTable("e", &ValueType::SetE); } /*! converting from a big letter to a small one */ int ToLowerCase(int c) { if( c>='A' && c<='Z' ) return c - 'A' + 'a'; return c; } /*! this method read the name of a variable or a function 'result' will be the name of a variable or a function function return 'false' if this name is the name of a variable or function return 'true' if this name is the name of a function what should be returned is tested just by a '(' character that means if there's a '(' character after a name that function returns 'true' */ bool ReadName(std::string & result) { int character; result.erase(); character = *pstring; /* the first letter must be from range 'a' - 'z' or 'A' - 'Z' */ if( ! (( character>='a' && character<='z' ) || ( character>='A' && character<='Z' )) ) Error( err_unknown_character ); do { result += static_cast( character ); character = * ++pstring; } while( (character>='a' && character<='z') || (character>='A' && character<='Z') || (character>='0' && character<='9') || character=='_' ); SkipWhiteCharacters(); /* if there's a character '(' that means this name is a name of a function */ if( *pstring == '(' ) { ++pstring; return true; } return false; } /*! we're checking whether the first character is '-' or '+' if it is we'll return 'true' and if it is equally '-' we'll set the 'sign' member of 'result' */ bool TestSign(Item & result) { SkipWhiteCharacters(); result.sign = false; if( *pstring == '-' || *pstring == '+' ) { if( *pstring == '-' ) result.sign = true; ++pstring; return true; } return false; } /*! we're reading the name of a variable or a function if is there a function we'll return 'true' */ bool ReadVariableOrFunction(Item & result) { std::string name; bool is_it_name_of_function = ReadName(name); if( is_it_name_of_function ) { /* we've read the name of a function */ result.function_name = name; result.type = Item::first_bracket; result.function = true; } else { /* we've read the name of a variable and we're getting its value now */ result.value = GetValueOfVariable( name ); } return is_it_name_of_function; } /*! we're reading a numerical value directly from the string */ void ReadValue(Item & result, int reading_base) { const char * new_stack_pointer; bool value_read; Conv conv; conv.base = reading_base; conv.comma = comma; conv.comma2 = comma2; conv.group = group; uint carry = result.value.FromString(pstring, conv, &new_stack_pointer, &value_read); pstring = new_stack_pointer; if( carry ) Error( err_overflow ); if( !value_read ) Error( err_unknown_character ); } /*! this method returns true if 'character' is a proper first digit for the value (or a comma -- can be first too) */ bool ValueStarts(int character, int base) { if( character == comma ) return true; if( comma2!=0 && character==comma2 ) return true; if( Misc::CharToDigit(character, base) != -1 ) return true; return false; } /*! we're reading the item return values: 0 - all ok, the item is successfully read 1 - the end of the string (the item is not read) 2 - the final bracket ')' */ int ReadValueVariableOrFunction(Item & result) { bool it_was_sign = false; int character; if( TestSign(result) ) // 'result.sign' was set as well it_was_sign = true; SkipWhiteCharacters(); character = ToLowerCase( *pstring ); if( character == 0 ) { if( it_was_sign ) // at the end of the string a character like '-' or '+' has left Error( err_unexpected_end ); // there's the end of the string here return 1; } else if( character == '(' ) { // we've got a normal bracket (not a function) result.type = Item::first_bracket; result.function = false; ++pstring; return 0; } else if( character == ')' ) { // we've got a final bracket // (in this place we can find a final bracket only when there are empty brackets // without any values inside or with a sign '-' or '+' inside) if( it_was_sign ) Error( err_unexpected_final_bracket ); result.type = Item::last_bracket; // we don't increment 'pstring', this final bracket will be read next by the // 'ReadOperatorAndCheckFinalBracket(...)' method return 2; } else if( character == '#' ) { ++pstring; SkipWhiteCharacters(); // after '#' character we do not allow '-' or '+' (can be white characters) if( ValueStarts(*pstring, 16) ) ReadValue( result, 16 ); else Error( err_unknown_character ); } else if( character == '&' ) { ++pstring; SkipWhiteCharacters(); // after '&' character we do not allow '-' or '+' (can be white characters) if( ValueStarts(*pstring, 2) ) ReadValue( result, 2 ); else Error( err_unknown_character ); } else if( ValueStarts(character, base) ) { ReadValue( result, base ); } else if( character>='a' && character<='z' ) { if( ReadVariableOrFunction(result) ) // we've read the name of a function return 0; } else Error( err_unknown_character ); /* we've got a value in the 'result' this value is from a variable or directly from the string */ result.type = Item::numerical_value; if( result.sign ) { result.value.ChangeSign(); result.sign = false; } return 0; } void InsertOperatorToTable(const char * name, typename MatOperator::Type type) { operators_table.insert( std::make_pair(std::string(name), type) ); } /*! this method creates the table of operators */ void CreateMathematicalOperatorsTable() { InsertOperatorToTable("||", MatOperator::lor); InsertOperatorToTable("&&", MatOperator::land); InsertOperatorToTable("!=", MatOperator::neq); InsertOperatorToTable("==", MatOperator::eq); InsertOperatorToTable(">=", MatOperator::get); InsertOperatorToTable("<=", MatOperator::let); InsertOperatorToTable(">", MatOperator::gt); InsertOperatorToTable("<", MatOperator::lt); InsertOperatorToTable("-", MatOperator::sub); InsertOperatorToTable("+", MatOperator::add); InsertOperatorToTable("/", MatOperator::div); InsertOperatorToTable("*", MatOperator::mul); InsertOperatorToTable("^", MatOperator::pow); } /*! returns true if 'str2' is the substring of str1 e.g. true when str1="test" and str2="te" */ bool IsSubstring(const std::string & str1, const std::string & str2) { if( str2.length() > str1.length() ) return false; for(typename std::string::size_type i=0 ; ifirst, oper) ) { oper.erase( --oper.end() ); // we've got mininum one element if( iter_old != operators_table.end() && iter_old->first == oper ) { result.type = Item::mat_operator; result.moperator.SetType( iter_old->second ); break; } Error( err_unknown_operator ); } iter_old = iter_new; } } /*! this method makes a calculation for the percentage operator e.g. 1000-50% = 1000-(1000*0,5) = 500 */ void OperatorPercentage() { if( stack_index < 3 || stack[stack_index-1].type != Item::numerical_value || stack[stack_index-2].type != Item::mat_operator || stack[stack_index-3].type != Item::numerical_value ) Error(err_percent_from); ++pstring; SkipWhiteCharacters(); uint c = 0; c += stack[stack_index-1].value.Div(100); c += stack[stack_index-1].value.Mul(stack[stack_index-3].value); if( c ) Error(err_overflow); } /*! this method reads a mathematic operators or the final bracket or the semicolon operator return values: 0 - ok 1 - the string is finished */ int ReadOperator(Item & result) { SkipWhiteCharacters(); if( *pstring == '%' ) OperatorPercentage(); if( *pstring == 0 ) return 1; else if( *pstring == ')' ) { result.type = Item::last_bracket; ++pstring; } else if( *pstring == ';' || (param_sep!=0 && *pstring==param_sep) ) { result.type = Item::semicolon; ++pstring; } else if( (*pstring>='a' && *pstring<='z') || (*pstring>='A' && *pstring<='Z') ) { // short mul (without any operators) result.type = Item::mat_operator; result.moperator.SetType( MatOperator::shortmul ); } else ReadMathematicalOperator(result); return 0; } /*! this method is making the standard mathematic operation like '-' '+' '*' '/' and '^' the operation is made between 'value1' and 'value2' the result of this operation is stored in the 'value1' */ void MakeStandardMathematicOperation(ValueType & value1, typename MatOperator::Type mat_operator, const ValueType & value2) { uint res; calculated = true; switch( mat_operator ) { case MatOperator::land: (!value1.IsZero() && !value2.IsZero()) ? value1.SetOne() : value1.SetZero(); break; case MatOperator::lor: (!value1.IsZero() || !value2.IsZero()) ? value1.SetOne() : value1.SetZero(); break; case MatOperator::eq: (value1 == value2) ? value1.SetOne() : value1.SetZero(); break; case MatOperator::neq: (value1 != value2) ? value1.SetOne() : value1.SetZero(); break; case MatOperator::lt: (value1 < value2) ? value1.SetOne() : value1.SetZero(); break; case MatOperator::gt: (value1 > value2) ? value1.SetOne() : value1.SetZero(); break; case MatOperator::let: (value1 <= value2) ? value1.SetOne() : value1.SetZero(); break; case MatOperator::get: (value1 >= value2) ? value1.SetOne() : value1.SetZero(); break; case MatOperator::sub: if( value1.Sub(value2) ) Error( err_overflow ); break; case MatOperator::add: if( value1.Add(value2) ) Error( err_overflow ); break; case MatOperator::mul: case MatOperator::shortmul: if( value1.Mul(value2) ) Error( err_overflow ); break; case MatOperator::div: if( value2.IsZero() ) Error( err_division_by_zero ); if( value1.Div(value2) ) Error( err_overflow ); break; case MatOperator::pow: res = value1.Pow( value2 ); if( res == 1 ) Error( err_overflow ); else if( res == 2 ) Error( err_improper_argument ); break; default: /* on the stack left an unknown operator but we had to recognize its before that means there's an error in our algorithm */ Error( err_internal_error ); } } /*! this method is trying to roll the stack up with the operator's priority for example if there are: "1 - 2 +" we can subtract "1-2" and the result store on the place where is '1' and copy the last operator '+', that means there'll be '-1+' on our stack but if there are: "1 - 2 *" we can't roll the stack up because the operator '*' has greater priority than '-' */ void TryRollingUpStackWithOperatorPriority() { while( stack_index>=4 && stack[stack_index-4].type == Item::numerical_value && stack[stack_index-3].type == Item::mat_operator && stack[stack_index-2].type == Item::numerical_value && stack[stack_index-1].type == Item::mat_operator && ( ( // the first operator has greater priority stack[stack_index-3].moperator.GetPriority() > stack[stack_index-1].moperator.GetPriority() ) || ( // or both operators have the same priority and the first operator is not right associative stack[stack_index-3].moperator.GetPriority() == stack[stack_index-1].moperator.GetPriority() && stack[stack_index-3].moperator.GetAssoc() == MatOperator::non_right ) ) ) { MakeStandardMathematicOperation(stack[stack_index-4].value, stack[stack_index-3].moperator.GetType(), stack[stack_index-2].value); /* copying the last operator and setting the stack pointer to the correct value */ stack[stack_index-3] = stack[stack_index-1]; stack_index -= 2; } } /*! this method is trying to roll the stack up without testing any operators for example if there are: "1 - 2" there'll be "-1" on our stack */ void TryRollingUpStack() { while( stack_index >= 3 && stack[stack_index-3].type == Item::numerical_value && stack[stack_index-2].type == Item::mat_operator && stack[stack_index-1].type == Item::numerical_value ) { MakeStandardMathematicOperation( stack[stack_index-3].value, stack[stack_index-2].moperator.GetType(), stack[stack_index-1].value ); stack_index -= 2; } } /*! this method is reading a value or a variable or a function (the normal first bracket as well) and push it into the stack */ int ReadValueVariableOrFunctionAndPushItIntoStack(Item & temp) { int code = ReadValueVariableOrFunction( temp ); if( code == 0 ) { if( stack_index < stack.size() ) stack[stack_index] = temp; else stack.push_back( temp ); ++stack_index; } if( code == 2 ) // there was a final bracket, we didn't push it into the stack // (it'll be read by the 'ReadOperatorAndCheckFinalBracket' method next) code = 0; return code; } /*! this method calculate how many parameters there are on the stack and the index of the first parameter if there aren't any parameters on the stack this method returns 'size' equals zero and 'index' pointing after the first bracket (on non-existend element) */ void HowManyParameters(int & size, int & index) { size = 0; index = stack_index; if( index == 0 ) // we haven't put a first bracket on the stack Error( err_unexpected_final_bracket ); if( stack[index-1].type == Item::first_bracket ) // empty brackets return; for( --index ; index>=1 ; index-=2 ) { if( stack[index].type != Item::numerical_value ) { /* this element must be 'numerical_value', if not that means there's an error in our algorithm */ Error( err_internal_error ); } ++size; if( stack[index-1].type != Item::semicolon ) break; } if( index<1 || stack[index-1].type != Item::first_bracket ) { /* we haven't put a first bracket on the stack */ Error( err_unexpected_final_bracket ); } } /*! this method is being called when the final bracket ')' is being found this method's rolling the stack up, counting how many parameters there are on the stack and if there was a function it's calling the function */ void RollingUpFinalBracket() { int amount_of_parameters; int index; if( stack_index<1 || (stack[stack_index-1].type != Item::numerical_value && stack[stack_index-1].type != Item::first_bracket) ) Error( err_unexpected_final_bracket ); TryRollingUpStack(); HowManyParameters(amount_of_parameters, index); // 'index' will be greater than zero // 'amount_of_parameters' can be zero if( amount_of_parameters==0 && !stack[index-1].function ) Error( err_unexpected_final_bracket ); bool was_sign = stack[index-1].sign; if( stack[index-1].function ) { // the result of a function will be on 'stack[index-1]' // and then at the end we'll set the correct type (numerical value) of this element CallFunction(stack[index-1].function_name, amount_of_parameters, index); } else { /* there was a normal bracket (not a funcion) */ if( amount_of_parameters != 1 ) Error( err_unexpected_semicolon_operator ); /* in the place where is the bracket we put the result */ stack[index-1] = stack[index]; } /* if there was a '-' character before the first bracket we change the sign of the expression */ stack[index-1].sign = false; if( was_sign ) stack[index-1].value.ChangeSign(); stack[index-1].type = Item::numerical_value; /* the pointer of the stack will be pointing on the next (non-existing now) element */ stack_index = index; } /*! this method is putting the operator on the stack */ void PushOperatorIntoStack(Item & temp) { if( stack_index < stack.size() ) stack[stack_index] = temp; else stack.push_back( temp ); ++stack_index; } /*! this method is reading a operator and if it's a final bracket it's calling RollingUpFinalBracket() and reading a operator again */ int ReadOperatorAndCheckFinalBracket(Item & temp) { do { if( ReadOperator(temp) == 1 ) { /* the string is finished */ return 1; } if( temp.type == Item::last_bracket ) RollingUpFinalBracket(); } while( temp.type == Item::last_bracket ); return 0; } /*! we check wheter there are only numerical value's or 'semicolon' operators on the stack */ void CheckIntegrityOfStack() { for(unsigned int i=0 ; iWasStopSignal() ) Error( err_interrupt ); result_code = ReadValueVariableOrFunctionAndPushItIntoStack( item ); if( result_code == 0 ) { if( item.type == Item::first_bracket ) continue; result_code = ReadOperatorAndCheckFinalBracket( item ); } if( result_code==1 || item.type==Item::semicolon ) { /* the string is finished or the 'semicolon' operator has appeared */ if( stack_index == 0 ) Error( err_nothing_has_read ); TryRollingUpStack(); if( result_code == 1 ) { CheckIntegrityOfStack(); return; } } PushOperatorIntoStack( item ); TryRollingUpStackWithOperatorPriority(); } } /*! this method is called at the end of the parsing process on our stack we can have another value than 'numerical_values' for example when someone use the operator ';' in the global scope or there was an error during parsing and the parser hasn't finished its job if there was an error the stack is cleaned up now otherwise we resize stack and leave on it only 'numerical_value' items */ void NormalizeStack() { if( error!=err_ok || stack_index==0 ) { stack.clear(); return; } /* 'stack_index' tell us how many elements there are on the stack, we must resize the stack now because 'stack_index' is using only for parsing and stack has more (or equal) elements than value of 'stack_index' */ stack.resize( stack_index ); for(uint i=stack_index-1 ; i!=uint(-1) ; --i) { if( stack[i].type != Item::numerical_value ) stack.erase( stack.begin() + i ); } } public: /*! the default constructor */ Parser(): default_stack_size(100) { pstop_calculating = 0; puser_variables = 0; puser_functions = 0; pfunction_local_variables = 0; base = 10; deg_rad_grad = 1; error = err_ok; group = 0; comma = '.'; comma2 = ','; param_sep = 0; CreateFunctionsTable(); CreateVariablesTable(); CreateMathematicalOperatorsTable(); } /*! the assignment operator */ Parser & operator=(const Parser & p) { pstop_calculating = p.pstop_calculating; puser_variables = p.puser_variables; puser_functions = p.puser_functions; pfunction_local_variables = 0; base = p.base; deg_rad_grad = p.deg_rad_grad; error = p.error; group = p.group; comma = p.comma; comma2 = p.comma2; param_sep = p.param_sep; /* we don't have to call 'CreateFunctionsTable()' etc. we can only copy these tables */ functions_table = p.functions_table; variables_table = p.variables_table; operators_table = p.operators_table; visited_variables = p.visited_variables; visited_functions = p.visited_functions; return *this; } /*! the copying constructor */ Parser(const Parser & p): default_stack_size(p.default_stack_size) { operator=(p); } /*! the new base of mathematic system default is 10 */ void SetBase(int b) { if( b>=2 && b<=16 ) base = b; } /*! the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot 0 - deg 1 - rad (default) 2 - grad */ void SetDegRadGrad(int angle) { if( angle >= 0 || angle <= 2 ) deg_rad_grad = angle; } /*! this method sets a pointer to the object which tell us whether we should stop calculations */ void SetStopObject(const volatile StopCalculating * ps) { pstop_calculating = ps; } /*! this method sets the new table of user-defined variables if you don't want any other variables just put zero value into the 'puser_variables' variable (you can have only one table at the same time) */ void SetVariables(const Objects * pv) { puser_variables = pv; } /*! this method sets the new table of user-defined functions if you don't want any other functions just put zero value into the 'puser_functions' variable (you can have only one table at the same time) */ void SetFunctions(const Objects * pf) { puser_functions = pf; } /*! setting the group character default zero (not used) */ void SetGroup(int g) { group = g; } /*! setting the main comma operator and the additional comma operator the additional operator can be zero (which means it is not used) default are: '.' and ',' */ void SetComma(int c, int c2 = 0) { comma = c; comma2 = c2; } /*! setting an additional character which is used as a parameters separator the main parameters separator is a semicolon (is used always) this character is used also as a global separator */ void SetParamSep(int s) { param_sep = s; } /*! the main method using for parsing string */ ErrorCode Parse(const char * str) { stack_index = 0; pstring = str; error = err_ok; calculated = false; stack.resize( default_stack_size ); try { Parse(); } catch(ErrorCode c) { error = c; calculated = false; } NormalizeStack(); return error; } /*! the main method using for parsing string */ ErrorCode Parse(const std::string & str) { return Parse(str.c_str()); } #ifndef TTMATH_DONT_USE_WCHAR /*! the main method using for parsing string */ ErrorCode Parse(const wchar_t * str) { Misc::AssignString(wide_to_ansi, str); return Parse(wide_to_ansi.c_str()); // !! wide_to_ansi clearing can be added here } /*! the main method using for parsing string */ ErrorCode Parse(const std::wstring & str) { return Parse(str.c_str()); } #endif /*! this method returns true is something was calculated (at least one mathematical operator was used or a function or variable) e.g. true if the string to Parse() looked like this: "1+1" "2*3" "sin(5)" if the string was e.g. "678" the result is false */ bool Calculated() { return calculated; } }; } // namespace #endif discoSnp/minia/ttmath/ttmathtypes.h0000644000000000000000000004003712062133074016475 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2010, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathtypes #define headerfilettmathtypes /*! \file ttmathtypes.h \brief constants used in the library As our library is written in header files (templates) we cannot use constants like 'const int' etc. because we should have some source files *.cpp to define this variables. Only what we can have are constants defined by #define preprocessor macros. All macros are preceded by TTMATH_ prefix */ #include #include #include #ifndef _MSC_VER #include // for uint64_t and int64_t on a 32 bit platform #endif /*! the version of the library TTMATH_PRERELEASE_VER is either zero or one zero means that this is the release version of the library (one means something like beta) */ #define TTMATH_MAJOR_VER 0 #define TTMATH_MINOR_VER 9 #define TTMATH_REVISION_VER 2 #define TTMATH_PRERELEASE_VER 0 /*! you can define a platform explicitly by defining either TTMATH_PLATFORM32 or TTMATH_PLATFORM64 macro */ #if !defined TTMATH_PLATFORM32 && !defined TTMATH_PLATFORM64 #if !defined _M_X64 && !defined __x86_64__ /* other platforms than x86 and amd64 are not recognized at the moment so you should set TTMATH_PLATFORMxx manually */ // we're using a 32bit platform #define TTMATH_PLATFORM32 #else // we're using a 64bit platform #define TTMATH_PLATFORM64 #endif #endif /*! asm version of the library is available by default only for: x86 and amd64 platforms and for Microsoft Visual and GCC compilers but you can force using asm version (the same asm as for Microsoft Visual) by defining TTMATH_FORCEASM macro you have to be sure that your compiler accept such an asm format */ #ifndef TTMATH_FORCEASM #if !defined __i386__ && !defined _X86_ && !defined _M_IX86 && !defined __x86_64__ && !defined _M_X64 /*! x86 architecture: __i386__ defined by GNU C _X86_ defined by MinGW32 _M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++ amd64 architecture: __x86_64__ defined by GNU C and Sun Studio _M_X64 defined by Visual Studio asm version is available only for x86 or amd64 platforms */ #define TTMATH_NOASM #endif #if !defined _MSC_VER && !defined __GNUC__ /*! another compilers than MS VC or GCC by default use no asm version */ #define TTMATH_NOASM #endif #endif namespace ttmath { #ifdef TTMATH_PLATFORM32 /*! on 32bit platforms one word (uint, sint) will be equal 32bits */ typedef unsigned int uint; typedef signed int sint; /*! on 32 bit platform ulint and slint will be equal 64 bits */ #ifdef _MSC_VER // long long on MS Windows (Visual and GCC mingw compilers) have 64 bits // stdint.h is not available on Visual Studio prior to VS 2010 version typedef unsigned long long int ulint; typedef signed long long int slint; #else // we do not use 'long' here because there is a difference in unix and windows // environments: in unix 'long' has 64 bits but in windows it has only 32 bits typedef uint64_t ulint; typedef int64_t slint; #endif /*! how many bits there are in the uint type */ #define TTMATH_BITS_PER_UINT 32u /*! the mask for the highest bit in the unsigned 32bit word (2^31) */ #define TTMATH_UINT_HIGHEST_BIT 2147483648u /*! the max value of the unsigned 32bit word (2^32 - 1) (all bits equal one) */ #define TTMATH_UINT_MAX_VALUE 4294967295u /*! the number of words (32bit words on 32bit platform) which are kept in built-in variables for a Big<> type (these variables are defined in ttmathbig.h) */ #define TTMATH_BUILTIN_VARIABLES_SIZE 256u /*! this macro returns the number of machine words capable to hold min_bits bits e.g. TTMATH_BITS(128) returns 4 */ #define TTMATH_BITS(min_bits) ((min_bits-1)/32 + 1) #else /*! on 64bit platforms one word (uint, sint) will be equal 64bits */ #ifdef _MSC_VER /* in VC 'long' type has 32 bits, __int64 is VC extension */ typedef unsigned __int64 uint; typedef signed __int64 sint; #else typedef unsigned long uint; typedef signed long sint; #endif /*! on 64bit platforms we do not define ulint and slint */ /*! how many bits there are in the uint type */ #define TTMATH_BITS_PER_UINT 64ul /*! the mask for the highest bit in the unsigned 64bit word (2^63) */ #define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul /*! the max value of the unsigned 64bit word (2^64 - 1) (all bits equal one) */ #define TTMATH_UINT_MAX_VALUE 18446744073709551615ul /*! the number of words (64bit words on 64bit platforms) which are kept in built-in variables for a Big<> type (these variables are defined in ttmathbig.h) */ #define TTMATH_BUILTIN_VARIABLES_SIZE 128ul /*! this macro returns the number of machine words capable to hold min_bits bits e.g. TTMATH_BITS(128) returns 2 */ #define TTMATH_BITS(min_bits) ((min_bits-1)/64 + 1) #endif } #if defined(TTMATH_MULTITHREADS) && !defined(TTMATH_MULTITHREADS_NOSYNC) #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) #if defined(_WIN32) #define TTMATH_WIN32_THREADS #elif defined(unix) || defined(__unix__) || defined(__unix) #define TTMATH_POSIX_THREADS #endif #endif #endif /*! this variable defines how many iterations are performed during some kind of calculating when we're making any long formulas (for example Taylor series) it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc. note! there'll not be so many iterations, iterations are stopped when there is no sense to continue calculating (for example when the result still remains unchanged after adding next series and we know that the next series are smaller than previous ones) */ #define TTMATH_ARITHMETIC_MAX_LOOP 10000 /*! this is a limit when calculating Karatsuba multiplication if the size of a vector is smaller than TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE the Karatsuba algorithm will use standard schoolbook multiplication */ #ifdef TTMATH_DEBUG_LOG // if TTMATH_DEBUG_LOG is defined then we should use the same size regardless of the compiler #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 #else #ifdef __GNUC__ #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 3 #else #define TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE 5 #endif #endif /*! this is a special value used when calculating the Gamma(x) function if x is greater than this value then the Gamma(x) will be calculated using some kind of series don't use smaller values than about 100 */ #define TTMATH_GAMMA_BOUNDARY 2000 namespace ttmath { /*! lib type codes: asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) asm_gcc_32 - with asm code designed for GCC (32 bits) asm_vc_64 - with asm for VC (64 bit) asm_gcc_64 - with asm for GCC (64 bit) no_asm_32 - pure C++ version (32 bit) - without any asm code no_asm_64 - pure C++ version (64 bit) - without any asm code */ enum LibTypeCode { asm_vc_32 = 0, asm_gcc_32, asm_vc_64, asm_gcc_64, no_asm_32, no_asm_64 }; /*! error codes */ enum ErrorCode { err_ok = 0, err_nothing_has_read, err_unknown_character, err_unexpected_final_bracket, err_stack_not_clear, err_unknown_variable, err_division_by_zero, err_interrupt, err_overflow, err_unknown_function, err_unknown_operator, err_unexpected_semicolon_operator, err_improper_amount_of_arguments, err_improper_argument, err_unexpected_end, err_internal_error, err_incorrect_name, err_incorrect_value, err_variable_exists, err_variable_loop, err_functions_loop, err_must_be_only_one_value, err_object_exists, err_unknown_object, err_still_calculating, err_in_short_form_used_function, err_percent_from }; /*! this struct is used when converting to/from a string /temporarily only in Big::ToString() and Big::FromString()/ */ struct Conv { /*! base (radix) on which the value will be shown (or read) default: 10 */ uint base; /*! used only in Big::ToString() if true the value will be always shown in the scientific mode, e.g: 123e+30 default: false */ bool scient; /*! used only in Big::ToString() if scient is false then the value will be printed in the scientific mode only if the exponent is greater than scien_from default: 15 */ sint scient_from; /*! if 'base_round' is true and 'base' is different from 2, 4, 8, or 16 and the result value is not an integer then we make an additional rounding (after converting the last digit from the result is skipped) default: true e.g. Conv c; c.base_round = false; Big<1, 1> a = "0.1"; // decimal input std::cout << a.ToString(c) << std::endl; // the result is: 0.099999999 */ bool base_round; /*! used only in Big::ToString() tells how many digits after comma are possible default: -1 which means all digits are printed set it to zero if you want integer value only for example when the value is: 12.345678 and 'round' is 4 then the result will be 12.3457 (the last digit was rounded) */ sint round; /*! if true that not mattered digits in the mantissa will be cut off (zero characters at the end -- after the comma operator) e.g. 1234,78000 will be: 1234,78 default: true */ bool trim_zeroes; /*! the main comma operator (used when reading and writing) default is a dot '.' */ uint comma; /*! additional comma operator (used only when reading) if you don't want it just set it to zero default is a comma ',' this allowes you to convert from a value: 123.45 as well as from 123,45 */ uint comma2; /*! it sets the character which is used for grouping if group=' ' then: 1234,56789 will be printed as: 1 234,567 89 if you don't want grouping just set it to zero (which is default) */ uint group; /*! */ uint group_exp; // not implemented yet Conv() { // default values base = 10; scient = false; scient_from = 15; base_round = true; round = -1; trim_zeroes = true; comma = '.'; comma2 = ','; group = 0; group_exp = 0; } }; /*! this simple class can be used in multithreading model (you can write your own class derived from this one) for example: in some functions like Factorial() /at the moment only Factorial/ you can give a pointer to the 'stop object', if the method WasStopSignal() of this object returns true that means we should break the calculating and return */ class StopCalculating { public: virtual bool WasStopSignal() const volatile { return false; } virtual ~StopCalculating(){} }; /*! a small class which is useful when compiling with gcc object of this type holds the name and the line of a file in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used */ class ExceptionInfo { const char * file; int line; public: ExceptionInfo() : file(0), line(0) {} ExceptionInfo(const char * f, int l) : file(f), line(l) {} std::string Where() const { if( !file ) return "unknown"; std::ostringstream result; result << file << ":" << line; return result.str(); } }; /*! A small class used for reporting 'reference' errors In the library is used macro TTMATH_REFERENCE_ASSERT which can throw an exception of this type ** from version 0.9.2 this macro is removed from all methods in public interface so you don't have to worry about it ** If you compile with gcc you can get a small benefit from using method Where() (it returns std::string) with the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT was used) */ class ReferenceError : public std::logic_error, public ExceptionInfo { public: ReferenceError() : std::logic_error("reference error") { } ReferenceError(const char * f, int l) : std::logic_error("reference error"), ExceptionInfo(f,l) { } std::string Where() const { return ExceptionInfo::Where(); } }; /*! a small class used for reporting errors in the library is used macro TTMATH_ASSERT which (if the condition in it is false) throw an exception of this type if you compile with gcc you can get a small benefit from using method Where() (it returns std::string) with the name and the line of a file where the macro TTMATH_ASSERT was used) */ class RuntimeError : public std::runtime_error, public ExceptionInfo { public: RuntimeError() : std::runtime_error("internal error") { } RuntimeError(const char * f, int l) : std::runtime_error("internal error"), ExceptionInfo(f,l) { } std::string Where() const { return ExceptionInfo::Where(); } }; /*! TTMATH_DEBUG this macro enables further testing during writing your code you don't have to define it in a release mode if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT are set as well and these macros can throw an exception if a condition in it is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT) TTMATH_DEBUG is set automatically if DEBUG or _DEBUG are defined */ #if defined DEBUG || defined _DEBUG #define TTMATH_DEBUG #endif #ifdef TTMATH_DEBUG #if defined(__FILE__) && defined(__LINE__) #define TTMATH_REFERENCE_ASSERT(expression) \ if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__); #define TTMATH_ASSERT(expression) \ if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__); #else #define TTMATH_REFERENCE_ASSERT(expression) \ if( &(expression) == this ) throw ReferenceError(); #define TTMATH_ASSERT(expression) \ if( !(expression) ) throw RuntimeError(); #endif #else #define TTMATH_REFERENCE_ASSERT(expression) #define TTMATH_ASSERT(expression) #endif #ifdef TTMATH_DEBUG_LOG #define TTMATH_LOG(msg) PrintLog(msg, std::cout); #define TTMATH_LOGC(msg, carry) PrintLog(msg, carry, std::cout); #define TTMATH_VECTOR_LOG(msg, vector, len) PrintVectorLog(msg, std::cout, vector, len); #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) PrintVectorLog(msg, carry, std::cout, vector, len); #else #define TTMATH_LOG(msg) #define TTMATH_LOGC(msg, carry) #define TTMATH_VECTOR_LOG(msg, vector, len) #define TTMATH_VECTOR_LOGC(msg, carry, vector, len) #endif } // namespace #endif discoSnp/minia/ttmath/ttmathuint.h0000644000000000000000000022462012062133074016312 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2010, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathuint #define headerfilettmathuint /*! \file ttmathuint.h \brief template class UInt */ #include #include #include "ttmathtypes.h" #include "ttmathmisc.h" /*! \brief a namespace for the TTMath library */ namespace ttmath { /*! \brief UInt implements a big integer value without a sign value_size - how many bytes specify our value on 32bit platforms: value_size=1 -> 4 bytes -> 32 bits on 64bit platforms: value_size=1 -> 8 bytes -> 64 bits value_size = 1,2,3,4,5,6.... */ template class UInt { public: /*! buffer for the integer value table[0] - the lowest word of the value */ uint table[value_size]; /*! some methods used for debugging purposes */ /*! this method is only for debugging purposes or when we want to make a table of a variable (constant) in ttmathbig.h it prints the table in a nice form of several columns */ template void PrintTable(ostream_type & output) const { // how many columns there'll be const int columns = 8; int c = 1; for(int i=value_size-1 ; i>=0 ; --i) { output << "0x" << std::setfill('0'); #ifdef TTMATH_PLATFORM32 output << std::setw(8); #else output << std::setw(16); #endif output << std::hex << table[i]; if( i>0 ) { output << ", "; if( ++c > columns ) { output << std::endl; c = 1; } } } output << std::dec << std::endl; } /*! this method is used when macro TTMATH_DEBUG_LOG is defined */ template static void PrintVectorLog(const char_type * msg, ostream_type & output, const uint * vector, uint vector_len) { output << msg << std::endl; for(uint i=0 ; i static void PrintVectorLog(const char_type * msg, uint carry, ostream_type & output, const uint * vector, uint vector_len) { PrintVectorLog(msg, output, vector, vector_len); output << " carry: " << carry << std::endl; } /*! this method is used when macro TTMATH_DEBUG_LOG is defined */ template void PrintLog(const char_type * msg, ostream_type & output) const { PrintVectorLog(msg, output, table, value_size); } /*! this method is used when macro TTMATH_DEBUG_LOG is defined */ template void PrintLog(const char_type * msg, uint carry, ostream_type & output) const { PrintVectorLog(msg, output, table, value_size); output << " carry: " << carry << std::endl; } /*! this method returns the size of the table */ uint Size() const { return value_size; } /*! this method sets zero */ void SetZero() { // in the future here can be 'memset' for(uint i=0 ; i & ss2) { for(uint i=0 ; i=0 && temp_table_index=0 ; --i) table[i] = 0; TTMATH_LOG("UInt::SetFromTable") } #endif #ifdef TTMATH_PLATFORM64 /*! this method copies the value stored in an another table (warning: first values in temp_table are the highest words -- it's different from our table) ***this method is created only on a 64bit platform*** we copy as many words as it is possible if temp_table_len is bigger than value_size we'll try to round the lowest word from table depending on the last not used bit in temp_table (this rounding isn't a perfect rounding -- look at the description below) and if temp_table_len is smaller than value_size we'll clear the rest words in the table warning: we're using 'temp_table' as a pointer at 32bit words */ void SetFromTable(const unsigned int * temp_table, uint temp_table_len) { uint temp_table_index = 0; sint i; // 'i' with a sign for(i=value_size-1 ; i>=0 && temp_table_index= 0 ; --i) table[i] = 0; TTMATH_LOG("UInt::SetFromTable") } #endif /*! * * basic mathematic functions * */ /*! this method adds one to the existing value */ uint AddOne() { return AddInt(1); } /*! this method subtracts one from the existing value */ uint SubOne() { return SubInt(1); } private: /*! an auxiliary method for moving bits into the left hand side this method moves only words */ void RclMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c) { rest_bits = bits % TTMATH_BITS_PER_UINT; uint all_words = bits / TTMATH_BITS_PER_UINT; uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0; if( all_words >= value_size ) { if( all_words == value_size && rest_bits == 0 ) last_c = table[0] & 1; // else: last_c is default set to 0 // clearing for(uint i = 0 ; i 0 ) { // 0 < all_words < value_size sint first, second; last_c = table[value_size - all_words] & 1; // all_words is greater than 0 // copying the first part of the value for(first = value_size-1, second=first-all_words ; second>=0 ; --first, --second) table[first] = table[second]; // setting the rest to 'c' for( ; first>=0 ; --first ) table[first] = mask; } TTMATH_LOG("UInt::RclMoveAllWords") } public: /*! moving all bits into the left side 'bits' times return value <- this <- C bits is from a range of <0, man * TTMATH_BITS_PER_UINT> or it can be even bigger then all bits will be set to 'c' the value c will be set into the lowest bits and the method returns state of the last moved bit */ uint Rcl(uint bits, uint c=0) { uint last_c = 0; uint rest_bits = bits; if( bits == 0 ) return 0; if( bits >= TTMATH_BITS_PER_UINT ) RclMoveAllWords(rest_bits, last_c, bits, c); if( rest_bits == 0 ) { TTMATH_LOG("UInt::Rcl") return last_c; } // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now if( rest_bits == 1 ) { last_c = Rcl2_one(c); } else if( rest_bits == 2 ) { // performance tests showed that for rest_bits==2 it's better to use Rcl2_one twice instead of Rcl2(2,c) Rcl2_one(c); last_c = Rcl2_one(c); } else { last_c = Rcl2(rest_bits, c); } TTMATH_LOGC("UInt::Rcl", last_c) return last_c; } private: /*! an auxiliary method for moving bits into the right hand side this method moves only words */ void RcrMoveAllWords(uint & rest_bits, uint & last_c, uint bits, uint c) { rest_bits = bits % TTMATH_BITS_PER_UINT; uint all_words = bits / TTMATH_BITS_PER_UINT; uint mask = ( c ) ? TTMATH_UINT_MAX_VALUE : 0; if( all_words >= value_size ) { if( all_words == value_size && rest_bits == 0 ) last_c = (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // else: last_c is default set to 0 // clearing for(uint i = 0 ; i 0 ) { // 0 < all_words < value_size uint first, second; last_c = (table[all_words - 1] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; // all_words is > 0 // copying the first part of the value for(first=0, second=all_words ; second this -> return value bits is from a range of <0, man * TTMATH_BITS_PER_UINT> or it can be even bigger then all bits will be set to 'c' the value c will be set into the highest bits and the method returns state of the last moved bit */ uint Rcr(uint bits, uint c=0) { uint last_c = 0; uint rest_bits = bits; if( bits == 0 ) return 0; if( bits >= TTMATH_BITS_PER_UINT ) RcrMoveAllWords(rest_bits, last_c, bits, c); if( rest_bits == 0 ) { TTMATH_LOG("UInt::Rcr") return last_c; } // rest_bits is from 1 to TTMATH_BITS_PER_UINT-1 now if( rest_bits == 1 ) { last_c = Rcr2_one(c); } else if( rest_bits == 2 ) { // performance tests showed that for rest_bits==2 it's better to use Rcr2_one twice instead of Rcr2(2,c) Rcr2_one(c); last_c = Rcr2_one(c); } else { last_c = Rcr2(rest_bits, c); } TTMATH_LOGC("UInt::Rcr", last_c) return last_c; } /*! this method moves all bits into the left side (it returns value how many bits have been moved) */ uint CompensationToLeft() { uint moving = 0; // a - index a last word which is different from zero sint a; for(a=value_size-1 ; a>=0 && table[a]==0 ; --a); if( a < 0 ) return moving; // all words in table have zero if( a != value_size-1 ) { moving += ( value_size-1 - a ) * TTMATH_BITS_PER_UINT; // moving all words sint i; for(i=value_size-1 ; a>=0 ; --i, --a) table[i] = table[a]; // setting the rest word to zero for(; i>=0 ; --i) table[i] = 0; } uint moving2 = FindLeadingBitInWord( table[value_size-1] ); // moving2 is different from -1 because the value table[value_size-1] // is not zero moving2 = TTMATH_BITS_PER_UINT - moving2 - 1; Rcl(moving2); TTMATH_LOG("UInt::CompensationToLeft") return moving + moving2; } /*! this method looks for the highest set bit result: if 'this' is not zero: return value - true 'table_id' - the index of a word <0..value_size-1> 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT) if 'this' is zero: return value - false both 'table_id' and 'index' are zero */ bool FindLeadingBit(uint & table_id, uint & index) const { for(table_id=value_size-1 ; table_id!=0 && table[table_id]==0 ; --table_id); if( table_id==0 && table[table_id]==0 ) { // is zero index = 0; return false; } // table[table_id] is different from 0 index = FindLeadingBitInWord( table[table_id] ); return true; } /*! this method looks for the smallest set bit result: if 'this' is not zero: return value - true 'table_id' - the index of a word <0..value_size-1> 'index' - the index of this set bit in the word <0..TTMATH_BITS_PER_UINT) if 'this' is zero: return value - false both 'table_id' and 'index' are zero */ bool FindLowestBit(uint & table_id, uint & index) const { for(table_id=0 ; table_id= value_size ) { // is zero index = 0; table_id = 0; return false; } // table[table_id] is different from 0 index = FindLowestBitInWord( table[table_id] ); return true; } /*! getting the 'bit_index' bit bit_index bigger or equal zero */ uint GetBit(uint bit_index) const { TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT ) uint index = bit_index / TTMATH_BITS_PER_UINT; uint bit = bit_index % TTMATH_BITS_PER_UINT; uint temp = table[index]; uint res = SetBitInWord(temp, bit); return res; } /*! setting the 'bit_index' bit and returning the last state of the bit bit_index bigger or equal zero */ uint SetBit(uint bit_index) { TTMATH_ASSERT( bit_index < value_size * TTMATH_BITS_PER_UINT ) uint index = bit_index / TTMATH_BITS_PER_UINT; uint bit = bit_index % TTMATH_BITS_PER_UINT; uint res = SetBitInWord(table[index], bit); TTMATH_LOG("UInt::SetBit") return res; } /*! this method performs a bitwise operation AND */ void BitAnd(const UInt & ss2) { for(uint x=0 ; x & ss2) { for(uint x=0 ; x & ss2) { for(uint x=0 ; x for example: BitNot2(8) = BitNot2( 1000(bin) ) = 111(bin) = 7 */ void BitNot2() { uint table_id, index; if( FindLeadingBit(table_id, index) ) { for(uint x=0 ; x>= shift; table[table_id] ^= mask; } else table[0] = 1; TTMATH_LOG("UInt::BitNot2") } /*! * * Multiplication * * */ public: /*! multiplication: this = this * ss2 it can return a carry */ uint MulInt(uint ss2) { uint r1, r2, x1; uint c = 0; UInt u(*this); SetZero(); if( ss2 == 0 ) { TTMATH_LOGC("UInt::MulInt(uint)", 0) return 0; } for(x1=0 ; x1 void MulInt(uint ss2, UInt & result) const { TTMATH_ASSERT( result_size > value_size ) uint r2,r1; uint x1size=value_size; uint x1start=0; result.SetZero(); if( ss2 == 0 ) { TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size) return; } if( value_size > 2 ) { // if the value_size is smaller than or equal to 2 // there is no sense to set x1size and x1start to another values for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); if( x1size == 0 ) { TTMATH_VECTOR_LOG("UInt::MulInt(uint, UInt<>)", result.table, result_size) return; } for(x1start=0 ; x1start)", result.table, result_size) return; } /*! the multiplication 'this' = 'this' * ss2 algorithm: 100 - means automatically choose the fastest algorithm */ uint Mul(const UInt & ss2, uint algorithm = 100) { switch( algorithm ) { case 1: return Mul1(ss2); case 2: return Mul2(ss2); case 3: return Mul3(ss2); case 100: default: return MulFastest(ss2); } } /*! the multiplication 'result' = 'this' * ss2 since the 'result' is twice bigger than 'this' and 'ss2' this method never returns a carry algorithm: 100 - means automatically choose the fastest algorithm */ void MulBig(const UInt & ss2, UInt & result, uint algorithm = 100) { switch( algorithm ) { case 1: return Mul1Big(ss2, result); case 2: return Mul2Big(ss2, result); case 3: return Mul3Big(ss2, result); case 100: default: return MulFastestBig(ss2, result); } } /*! the first version of the multiplication algorithm */ private: /*! multiplication: this = this * ss2 it returns carry if it has been */ uint Mul1Ref(const UInt & ss2) { TTMATH_REFERENCE_ASSERT( ss2 ) UInt ss1( *this ); SetZero(); for(uint i=0; i < value_size*TTMATH_BITS_PER_UINT ; ++i) { if( Add(*this) ) { TTMATH_LOGC("UInt::Mul1", 1) return 1; } if( ss1.Rcl(1) ) if( Add(ss2) ) { TTMATH_LOGC("UInt::Mul1", 1) return 1; } } TTMATH_LOGC("UInt::Mul1", 0) return 0; } public: /*! multiplication: this = this * ss2 can return carry */ uint Mul1(const UInt & ss2) { if( this == &ss2 ) { UInt copy_ss2(ss2); return Mul1Ref(copy_ss2); } else { return Mul1Ref(ss2); } } /*! multiplication: result = this * ss2 result is twice bigger than 'this' and 'ss2' this method never returns carry */ void Mul1Big(const UInt & ss2_, UInt & result) { UInt ss2; uint i; // copying *this into result and ss2_ into ss2 for(i=0 ; i & ss2) { UInt result; uint i, c = 0; Mul2Big(ss2, result); // copying result for(i=0 ; i & ss2, UInt & result) { Mul2Big2(table, ss2.table, result); TTMATH_LOG("UInt::Mul2Big") } private: /*! an auxiliary method for calculating the multiplication arguments we're taking as pointers (this is to improve the Mul3Big2()- avoiding unnecessary copying objects), the result should be taken as a pointer too, but at the moment there is no method AddTwoInts() which can operate on pointers */ template void Mul2Big2(const uint * ss1, const uint * ss2, UInt & result) { uint x1size = ss_size, x2size = ss_size; uint x1start = 0, x2start = 0; if( ss_size > 2 ) { // if the ss_size is smaller than or equal to 2 // there is no sense to set x1size (and others) to another values for(x1size=ss_size ; x1size>0 && ss1[x1size-1]==0 ; --x1size); for(x2size=ss_size ; x2size>0 && ss2[x2size-1]==0 ; --x2size); for(x1start=0 ; x1start(ss1, ss2, result, x1start, x1size, x2start, x2size); } /*! an auxiliary method for calculating the multiplication */ template void Mul2Big3(const uint * ss1, const uint * ss2, UInt & result, uint x1start, uint x1size, uint x2start, uint x2size) { uint r2, r1; result.SetZero(); if( x1size==0 || x2size==0 ) return; for(uint x1=x1start ; x1 & ss2) { UInt result; uint i, c = 0; Mul3Big(ss2, result); // copying result for(i=0 ; i & ss2, UInt & result) { Mul3Big2(table, ss2.table, result.table); TTMATH_LOG("UInt::Mul3Big") } private: /*! an auxiliary method for calculating the Karatsuba multiplication result_size is equal ss_size*2 */ template void Mul3Big2(const uint * ss1, const uint * ss2, uint * result) { const uint * x1, * x0, * y1, * y0; if( ss_size>1 && ss_size res; Mul2Big2(ss1, ss2, res); for(uint i=0 ; i(x1, x0, y1, y0, result); } else { // ss_size is even x0 = ss1; y0 = ss2; x1 = ss1 + ss_size / 2; y1 = ss2 + ss_size / 2; // all four vectors (x0 x1 y0 y1) are equal in size Mul3Big3(x1, x0, y1, y0, result); } } #ifdef _MSC_VER #pragma warning (disable : 4717) //warning C4717: recursive on all control paths, function will cause runtime stack overflow //we have the stop point in Mul3Big2() method #endif /*! an auxiliary method for calculating the Karatsuba multiplication x = x1*B^m + x0 y = y1*B^m + y0 first_size - is the size of vectors: x0 and y0 second_size - is the size of vectors: x1 and y1 (can be either equal first_size or smaller about one from first_size) x*y = (x1*B^m + x0)(y1*B^m + y0) = z2*B^(2m) + z1*B^m + z0 where z0 = x0*y0 z2 = x1*y1 z1 = (x1 + x0)*(y1 + y0) - z2 - z0 */ template void Mul3Big3(const uint * x1, const uint * x0, const uint * y1, const uint * y0, uint * result) { uint i, c, xc, yc; UInt temp, temp2; UInt z1; // z0 and z2 we store directly in the result (we don't use any temporary variables) Mul3Big2(x0, y0, result); // z0 Mul3Big2(x1, y1, result+first_size*2); // z2 // now we calculate z1 // temp = (x0 + x1) // temp2 = (y0 + y1) // we're using temp and temp2 with UInt, although there can be a carry but // we simple remember it in xc and yc (xc and yc can be either 0 or 1), // and (x0 + x1)*(y0 + y1) we calculate in this way (schoolbook algorithm): // // xc | temp // yc | temp2 // -------------------- // (temp * temp2) // xc*temp2 | // yc*temp | // xc*yc | // ---------- z1 -------- // // and the result is never larger in size than 3*first_size xc = AddVector(x0, x1, first_size, second_size, temp.table); yc = AddVector(y0, y1, first_size, second_size, temp2.table); Mul3Big2(temp.table, temp2.table, z1.table); // clearing the rest of z1 for(i=first_size*2 ; i second_size ) { uint z1_size = result_size - first_size; TTMATH_ASSERT( z1_size <= first_size*3 ) for(i=z1_size ; i & ss2) { UInt result; uint i, c = 0; MulFastestBig(ss2, result); // copying result for(i=0 ; i & ss2, UInt & result) { if( value_size < TTMATH_USE_KARATSUBA_MULTIPLICATION_FROM_SIZE ) return Mul2Big(ss2, result); uint x1size = value_size, x2size = value_size; uint x1start = 0, x2start = 0; for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size); for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size); if( x1size==0 || x2size==0 ) { // either 'this' or 'ss2' is equal zero - the result is zero too result.SetZero(); return; } for(x1start=0 ; x1start(table, ss2.table, result, x1start, x1size, x2start, x2size); // Karatsuba multiplication Mul3Big(ss2, result); TTMATH_LOG("UInt::MulFastestBig") } /*! * * Division * * */ public: /*! division by one unsigned word returns 1 when divisor is zero */ uint DivInt(uint divisor, uint * remainder = 0) { if( divisor == 0 ) { if( remainder ) *remainder = 0; // this is for convenience, without it the compiler can report that 'remainder' is uninitialized TTMATH_LOG("UInt::DivInt") return 1; } if( divisor == 1 ) { if( remainder ) *remainder = 0; TTMATH_LOG("UInt::DivInt") return 0; } UInt dividend(*this); SetZero(); sint i; // i must be with a sign uint r = 0; // we're looking for the last word in ss1 for(i=value_size-1 ; i>0 && dividend.table[i]==0 ; --i); for( ; i>=0 ; --i) DivTwoWords(r, dividend.table[i], divisor, &table[i], &r); if( remainder ) *remainder = r; TTMATH_LOG("UInt::DivInt") return 0; } uint DivInt(uint divisor, uint & remainder) { return DivInt(divisor, &remainder); } /*! division this = this / ss2 return values: 0 - ok 1 - division by zero 'this' will be the quotient 'remainder' - remainder */ uint Div( const UInt & divisor, UInt * remainder = 0, uint algorithm = 3) { switch( algorithm ) { case 1: return Div1(divisor, remainder); case 2: return Div2(divisor, remainder); case 3: default: return Div3(divisor, remainder); } } uint Div(const UInt & divisor, UInt & remainder, uint algorithm = 3) { return Div(divisor, &remainder, algorithm); } private: /*! return values: 0 - none has to be done 1 - division by zero 2 - division should be made */ uint Div_StandardTest( const UInt & v, uint & m, uint & n, UInt * remainder = 0) { switch( Div_CalculatingSize(v, m, n) ) { case 4: // 'this' is equal v if( remainder ) remainder->SetZero(); SetOne(); TTMATH_LOG("UInt::Div_StandardTest") return 0; case 3: // 'this' is smaller than v if( remainder ) *remainder = *this; SetZero(); TTMATH_LOG("UInt::Div_StandardTest") return 0; case 2: // 'this' is zero if( remainder ) remainder->SetZero(); SetZero(); TTMATH_LOG("UInt::Div_StandardTest") return 0; case 1: // v is zero TTMATH_LOG("UInt::Div_StandardTest") return 1; } TTMATH_LOG("UInt::Div_StandardTest") return 2; } /*! return values: 0 - ok 'm' - is the index (from 0) of last non-zero word in table ('this') 'n' - is the index (from 0) of last non-zero word in v.table 1 - v is zero 2 - 'this' is zero 3 - 'this' is smaller than v 4 - 'this' is equal v if the return value is different than zero the 'm' and 'n' are undefined */ uint Div_CalculatingSize(const UInt & v, uint & m, uint & n) { m = n = value_size-1; for( ; n!=0 && v.table[n]==0 ; --n); if( n==0 && v.table[n]==0 ) return 1; for( ; m!=0 && table[m]==0 ; --m); if( m==0 && table[m]==0 ) return 2; if( m < n ) return 3; else if( m == n ) { uint i; for(i = n ; i!=0 && table[i]==v.table[i] ; --i); if( table[i] < v.table[i] ) return 3; else if (table[i] == v.table[i] ) return 4; } return 0; } public: /*! the first division algorithm radix 2 */ uint Div1(const UInt & divisor, UInt * remainder = 0) { uint m,n, test; test = Div_StandardTest(divisor, m, n, remainder); if( test < 2 ) return test; if( !remainder ) { UInt rem; return Div1_Calculate(divisor, rem); } return Div1_Calculate(divisor, *remainder); } /*! the first division algorithm radix 2 */ uint Div1(const UInt & divisor, UInt & remainder) { return Div1(divisor, &remainder); } private: uint Div1_Calculate(const UInt & divisor, UInt & rest) { if( this == &divisor ) { UInt divisor_copy(divisor); return Div1_CalculateRef(divisor_copy, rest); } else { return Div1_CalculateRef(divisor, rest); } } uint Div1_CalculateRef(const UInt & divisor, UInt & rest) { TTMATH_REFERENCE_ASSERT( divisor ) sint loop; sint c; rest.SetZero(); loop = value_size * TTMATH_BITS_PER_UINT; c = 0; div_a: c = Rcl(1, c); c = rest.Add(rest,c); c = rest.Sub(divisor,c); c = !c; if(!c) goto div_d; div_b: --loop; if(loop) goto div_a; c = Rcl(1, c); TTMATH_LOG("UInt::Div1_Calculate") return 0; div_c: c = Rcl(1, c); c = rest.Add(rest,c); c = rest.Add(divisor); if(c) goto div_b; div_d: --loop; if(loop) goto div_c; c = Rcl(1, c); c = rest.Add(divisor); TTMATH_LOG("UInt::Div1_Calculate") return 0; } public: /*! the second division algorithm return values: 0 - ok 1 - division by zero */ uint Div2(const UInt & divisor, UInt * remainder = 0) { if( this == &divisor ) { UInt divisor_copy(divisor); return Div2Ref(divisor_copy, remainder); } else { return Div2Ref(divisor, remainder); } } /*! the second division algorithm return values: 0 - ok 1 - division by zero */ uint Div2(const UInt & divisor, UInt & remainder) { return Div2(divisor, &remainder); } private: /*! the second division algorithm return values: 0 - ok 1 - division by zero */ uint Div2Ref(const UInt & divisor, UInt * remainder = 0) { uint bits_diff; uint status = Div2_Calculate(divisor, remainder, bits_diff); if( status < 2 ) return status; if( CmpBiggerEqual(divisor) ) { Div2(divisor, remainder); SetBit(bits_diff); } else { if( remainder ) *remainder = *this; SetZero(); SetBit(bits_diff); } TTMATH_LOG("UInt::Div2") return 0; } /*! return values: 0 - we've calculated the division 1 - division by zero 2 - we have to still calculate */ uint Div2_Calculate(const UInt & divisor, UInt * remainder, uint & bits_diff) { uint table_id, index; uint divisor_table_id, divisor_index; uint status = Div2_FindLeadingBitsAndCheck( divisor, remainder, table_id, index, divisor_table_id, divisor_index); if( status < 2 ) { TTMATH_LOG("UInt::Div2_Calculate") return status; } // here we know that 'this' is greater than divisor // then 'index' is greater or equal 'divisor_index' bits_diff = index - divisor_index; UInt divisor_copy(divisor); divisor_copy.Rcl(bits_diff, 0); if( CmpSmaller(divisor_copy, table_id) ) { divisor_copy.Rcr(1); --bits_diff; } Sub(divisor_copy, 0); TTMATH_LOG("UInt::Div2_Calculate") return 2; } /*! return values: 0 - we've calculated the division 1 - division by zero 2 - we have to still calculate */ uint Div2_FindLeadingBitsAndCheck( const UInt & divisor, UInt * remainder, uint & table_id, uint & index, uint & divisor_table_id, uint & divisor_index) { if( !divisor.FindLeadingBit(divisor_table_id, divisor_index) ) { // division by zero TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") return 1; } if( !FindLeadingBit(table_id, index) ) { // zero is divided by something SetZero(); if( remainder ) remainder->SetZero(); TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") return 0; } divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT; index += table_id * TTMATH_BITS_PER_UINT; if( divisor_table_id == 0 ) { // dividor has only one 32-bit word uint r; DivInt(divisor.table[0], &r); if( remainder ) { remainder->SetZero(); remainder->table[0] = r; } TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") return 0; } if( Div2_DivisorGreaterOrEqual( divisor, remainder, table_id, index, divisor_index) ) { TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") return 0; } TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") return 2; } /*! return values: true if divisor is equal or greater than 'this' */ bool Div2_DivisorGreaterOrEqual( const UInt & divisor, UInt * remainder, uint table_id, uint index, uint divisor_index ) { if( divisor_index > index ) { // divisor is greater than this if( remainder ) *remainder = *this; SetZero(); TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") return true; } if( divisor_index == index ) { // table_id == divisor_table_id as well uint i; for(i = table_id ; i!=0 && table[i]==divisor.table[i] ; --i); if( table[i] < divisor.table[i] ) { // divisor is greater than 'this' if( remainder ) *remainder = *this; SetZero(); TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") return true; } else if( table[i] == divisor.table[i] ) { // divisor is equal 'this' if( remainder ) remainder->SetZero(); SetOne(); TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") return true; } } TTMATH_LOG("UInt::Div2_DivisorGreaterOrEqual") return false; } public: /*! the third division algorithm */ uint Div3(const UInt & ss2, UInt * remainder = 0) { if( this == &ss2 ) { UInt copy_ss2(ss2); return Div3Ref(copy_ss2, remainder); } else { return Div3Ref(ss2, remainder); } } /*! the third division algorithm */ uint Div3(const UInt & ss2, UInt & remainder) { return Div3(ss2, &remainder); } private: /*! the third division algorithm this algorithm is described in the following book: "The art of computer programming 2" (4.3.1 page 272) Donald E. Knuth !! give the description here (from the book) */ uint Div3Ref(const UInt & v, UInt * remainder = 0) { uint m,n, test; test = Div_StandardTest(v, m, n, remainder); if( test < 2 ) return test; if( n == 0 ) { uint r; DivInt( v.table[0], &r ); if( remainder ) { remainder->SetZero(); remainder->table[0] = r; } TTMATH_LOG("UInt::Div3") return 0; } // we can only use the third division algorithm when // the divisor is greater or equal 2^32 (has more than one 32-bit word) ++m; ++n; m = m - n; Div3_Division(v, remainder, m, n); TTMATH_LOG("UInt::Div3") return 0; } private: void Div3_Division(UInt v, UInt * remainder, uint m, uint n) { TTMATH_ASSERT( n>=2 ) UInt uu, vv; UInt q; uint d, u_value_size, u0, u1, u2, v1, v0, j=m; u_value_size = Div3_Normalize(v, n, d); if( j+n == value_size ) u2 = u_value_size; else u2 = table[j+n]; Div3_MakeBiggerV(v, vv); for(uint i = j+1 ; i & uu, uint j, uint n, uint u_max) { uint i; for(i=0 ; i so and 'i' is from <0..value_size> // then table[i] is always correct (look at the declaration of 'uu') uu.table[i] = u_max; for( ++i ; i & uu, uint j, uint n) { uint i; for(i=0 ; i & v, UInt & vv) { for(uint i=0 ; i & v, uint n, uint & d) { // v.table[n-1] is != 0 uint bit = (uint)FindLeadingBitInWord(v.table[n-1]); uint move = (TTMATH_BITS_PER_UINT - bit - 1); uint res = table[value_size-1]; d = move; if( move > 0 ) { v.Rcl(move, 0); Rcl(move, 0); res = res >> (bit + 1); } else { res = 0; } TTMATH_LOG("UInt::Div3_Normalize") return res; } void Div3_Unnormalize(UInt * remainder, uint n, uint d) { for(uint i=n ; i u_temp; uint rp; bool next_test; TTMATH_ASSERT( v1 != 0 ) u_temp.table[1] = u2; u_temp.table[0] = u1; u_temp.DivInt(v1, &rp); TTMATH_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1 ) do { bool decrease = false; if( u_temp.table[1] == 1 ) decrease = true; else { UInt<2> temp1, temp2; UInt<2>::MulTwoWords(u_temp.table[0], v0, temp1.table+1, temp1.table); temp2.table[1] = rp; temp2.table[0] = u0; if( temp1 > temp2 ) decrease = true; } next_test = false; if( decrease ) { u_temp.SubOne(); rp += v1; if( rp >= v1 ) // it means that there wasn't a carry (r & uu, const UInt & vv, uint & qp) { // D4 (in the book) UInt vv_temp(vv); vv_temp.MulInt(qp); if( uu.Sub(vv_temp) ) { // there was a carry // // !!! this part of code was not tested // --qp; uu.Add(vv); // can be a carry from this additions but it should be ignored // because it cancels with the borrow from uu.Sub(vv_temp) } TTMATH_LOG("UInt::Div3_MultiplySubtract") } public: /*! power this = this ^ pow binary algorithm (r-to-l) return values: 0 - ok 1 - carry 2 - incorrect argument (0^0) */ uint Pow(UInt pow) { if(pow.IsZero() && IsZero()) // we don't define zero^zero return 2; UInt start(*this), start_temp; UInt result; result.SetOne(); uint c = 0; while( !c ) { if( pow.table[0] & 1 ) c += result.Mul(start); pow.Rcr2_one(0); if( pow.IsZero() ) break; start_temp = start; // in the second Mul algorithm we can use start.Mul(start) directly (there is no TTMATH_ASSERT_REFERENCE there) c += start.Mul(start_temp); } *this = result; TTMATH_LOGC("UInt::Pow(UInt<>)", c) return (c==0)? 0 : 1; } /*! square root e.g. Sqrt(9) = 3 ('digit-by-digit' algorithm) */ void Sqrt() { UInt bit, temp; if( IsZero() ) return; UInt value(*this); SetZero(); bit.SetZero(); bit.table[value_size-1] = (TTMATH_UINT_HIGHEST_BIT >> 1); while( bit > value ) bit.Rcr(2); while( !bit.IsZero() ) { temp = *this; temp.Add(bit); if( value >= temp ) { value.Sub(temp); Rcr(1); Add(bit); } else { Rcr(1); } bit.Rcr(2); } TTMATH_LOG("UInt::Sqrt") } /*! this method sets n first bits to value zero For example: let n=2 then if there's a value 111 (bin) there'll be '100' (bin) */ void ClearFirstBits(uint n) { if( n >= value_size*TTMATH_BITS_PER_UINT ) { SetZero(); TTMATH_LOG("UInt::ClearFirstBits") return; } uint * p = table; // first we're clearing the whole words while( n >= TTMATH_BITS_PER_UINT ) { *p++ = 0; n -= TTMATH_BITS_PER_UINT; } if( n == 0 ) { TTMATH_LOG("UInt::ClearFirstBits") return; } // and then we're clearing one word which has left // mask -- all bits are set to one uint mask = TTMATH_UINT_MAX_VALUE; mask = mask << n; (*p) &= mask; TTMATH_LOG("UInt::ClearFirstBits") } /*! this method returns true if the highest bit of the value is set */ bool IsTheHighestBitSet() const { return (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0; } /*! this method returns true if the lowest bit of the value is set */ bool IsTheLowestBitSet() const { return (*table & 1) != 0; } /*! returning true if only the highest bit is set */ bool IsOnlyTheHighestBitSet() const { for(uint i=0 ; i> (TTMATH_BITS_PER_UINT - rest); return (table[i] & mask) == 0; } /*! * * conversion methods * */ /*! this method converts an UInt type to this class this operation has mainly sense if the value from p is equal or smaller than that one which is returned from UInt::SetMax() it returns a carry if the value 'p' is too big */ template uint FromUInt(const UInt & p) { uint min_size = (value_size < argument_size)? value_size : argument_size; uint i; for(i=0 ; i argument_size ) { // 'this' is longer than 'p' for( ; i)", 1) return 1; } } TTMATH_LOGC("UInt::FromUInt(UInt<>)", 0) return 0; } /*! this method converts an UInt type to this class this operation has mainly sense if the value from p is equal or smaller than that one which is returned from UInt::SetMax() it returns a carry if the value 'p' is too big */ template uint FromInt(const UInt & p) { return FromUInt(p); } /*! this method converts the uint type to this class */ uint FromUInt(uint value) { for(uint i=1 ; i type to this class it doesn't return a carry */ template UInt & operator=(const UInt & p) { FromUInt(p); return *this; } /*! the assignment operator */ UInt & operator=(const UInt & p) { for(uint i=0 ; i)") return *this; } /*! this method converts the uint type to this class */ UInt & operator=(uint i) { FromUInt(i); return *this; } /*! a constructor for converting the uint to this class */ UInt(uint i) { FromUInt(i); } /*! this method converts the sint type to this class */ UInt & operator=(sint i) { FromInt(i); return *this; } /*! a constructor for converting the sint to this class look at the description of UInt::operator=(sint) */ UInt(sint i) { FromInt(i); } #ifdef TTMATH_PLATFORM32 /*! this method converts unsigned 64 bit int type to this class ***this method is created only on a 32bit platform*** */ uint FromUInt(ulint n) { table[0] = (uint)n; if( value_size == 1 ) { uint c = ((n >> TTMATH_BITS_PER_UINT) == 0) ? 0 : 1; TTMATH_LOGC("UInt::FromUInt(ulint)", c) return c; } table[1] = (uint)(n >> TTMATH_BITS_PER_UINT); for(uint i=2 ; i & operator=(ulint n) { FromUInt(n); return *this; } /*! a constructor for converting unsigned 64 bit int to this class ***this constructor is created only on a 32bit platform*** */ UInt(ulint n) { FromUInt(n); } /*! this operator converts signed 64 bit int type to this class ***this operator is created only on a 32bit platform*** */ UInt & operator=(slint n) { FromInt(n); return *this; } /*! a constructor for converting signed 64 bit int to this class ***this constructor is created only on a 32bit platform*** */ UInt(slint n) { FromInt(n); } #endif #ifdef TTMATH_PLATFORM64 /*! this method converts 32 bit unsigned int type to this class ***this operator is created only on a 64bit platform*** */ uint FromUInt(unsigned int i) { return FromUInt(uint(i)); } /*! this method converts 32 bit unsigned int type to this class ***this operator is created only on a 64bit platform*** */ uint FromInt(unsigned int i) { return FromUInt(uint(i)); } /*! this method converts 32 bit signed int type to this class ***this operator is created only on a 64bit platform*** */ uint FromInt(signed int i) { return FromInt(sint(i)); } /*! this operator converts 32 bit unsigned int type to this class ***this operator is created only on a 64bit platform*** */ UInt & operator=(unsigned int i) { FromUInt(i); return *this; } /*! a constructor for converting 32 bit unsigned int to this class ***this constructor is created only on a 64bit platform*** */ UInt(unsigned int i) { FromUInt(i); } /*! an operator for converting 32 bit signed int to this class ***this constructor is created only on a 64bit platform*** */ UInt & operator=(signed int i) { FromInt(i); return *this; } /*! a constructor for converting 32 bit signed int to this class ***this constructor is created only on a 64bit platform*** */ UInt(signed int i) { FromInt(i); } #endif /*! a constructor for converting a string to this class (with the base=10) */ UInt(const char * s) { FromString(s); } /*! a constructor for converting a string to this class (with the base=10) */ UInt(const std::string & s) { FromString( s.c_str() ); } #ifndef TTMATH_DONT_USE_WCHAR /*! a constructor for converting a string to this class (with the base=10) */ UInt(const wchar_t * s) { FromString(s); } /*! a constructor for converting a string to this class (with the base=10) */ UInt(const std::wstring & s) { FromString( s.c_str() ); } #endif /*! a default constructor we don't clear the table */ UInt() { // when macro TTMATH_DEBUG_LOG is defined // we set special values to the table // in order to be everywhere the same value of the UInt object // without this it would be difficult to analyse the log file #ifdef TTMATH_DEBUG_LOG #ifdef TTMATH_PLATFORM32 for(uint i=0 ; i & u) { for(uint i=0 ; i)") } /*! a template for producting constructors for copying from another types */ template UInt(const UInt & u) { // look that 'size' we still set as 'value_size' and not as u.value_size FromUInt(u); } /*! a destructor */ ~UInt() { } /*! this method returns the lowest value from table we must be sure when we using this method whether the value will hold in an uint type or not (the rest value from the table must be zero) */ uint ToUInt() const { return table[0]; } /*! this method converts the value to uint type can return a carry if the value is too long to store it in uint type */ uint ToUInt(uint & result) const { result = table[0]; for(uint i=1 ; i> 32) != 0 ) return 1; for(uint i=1 ; i void ToStringBase(string_type & result, uint b = 10) const { UInt temp( *this ); char character; uint rem; result.clear(); if( b<2 || b>16 ) return; do { temp.DivInt(b, &rem); character = static_cast( Misc::DigitToChar(rem) ); result.insert(result.begin(), character); } while( !temp.IsZero() ); return; } public: /*! this method converts the value to a string with a base equal 'b' */ void ToString(std::string & result, uint b = 10) const { return ToStringBase(result, b); } std::string ToString(uint b = 10) const { std::string result; ToStringBase(result, b); return result; } #ifndef TTMATH_DONT_USE_WCHAR void ToString(std::wstring & result, uint b = 10) const { return ToStringBase(result, b); } std::wstring ToWString(uint b = 10) const { std::wstring result; ToStringBase(result, b); return result; } #endif private: /*! an auxiliary method for converting from a string */ template uint FromStringBase(const char_type * s, uint b = 10, const char_type ** after_source = 0, bool * value_read = 0) { UInt base( b ); UInt temp; sint z; uint c = 0; SetZero(); temp.SetZero(); Misc::SkipWhiteCharacters(s); if( after_source ) *after_source = s; if( value_read ) *value_read = false; if( b<2 || b>16 ) return 1; for( ; (z=Misc::CharToDigit(*s, b)) != -1 ; ++s) { if( value_read ) *value_read = true; if( c == 0 ) { temp.table[0] = z; c += Mul(base); c += Add(temp); } } if( after_source ) *after_source = s; TTMATH_LOGC("UInt::FromString", c) return (c==0)? 0 : 1; } public: /*! this method converts a string into its value it returns carry=1 if the value will be too big or an incorrect base 'b' is given string is ended with a non-digit value, for example: "12" will be translated to 12 as well as: "12foo" will be translated to 12 too existing first white characters will be ommited if the value from s is too large the rest digits will be skipped after_source (if exists) is pointing at the end of the parsed string value_read (if exists) tells whether something has actually been read (at least one digit) */ uint FromString(const char * s, uint b = 10, const char ** after_source = 0, bool * value_read = 0) { return FromStringBase(s, b, after_source, value_read); } /*! this method converts a string into its value (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) */ uint FromString(const std::string & s, uint b = 10) { return FromString( s.c_str(), b ); } /*! this operator converts a string into its value (with base = 10) */ UInt & operator=(const char * s) { FromString(s); return *this; } /*! this operator converts a string into its value (with base = 10) */ UInt & operator=(const std::string & s) { FromString( s.c_str() ); return *this; } #ifndef TTMATH_DONT_USE_WCHAR /*! this method converts a string into its value */ uint FromString(const wchar_t * s, uint b = 10, const wchar_t ** after_source = 0, bool * value_read = 0) { return FromStringBase(s, b, after_source, value_read); } /*! this method converts a string into its value (it returns carry=1 if the value will be too big or an incorrect base 'b' is given) */ uint FromString(const std::wstring & s, uint b = 10) { return FromString( s.c_str(), b ); } /*! this operator converts a string into its value (with base = 10) */ UInt & operator=(const wchar_t * s) { FromString(s); return *this; } /*! this operator converts a string into its value (with base = 10) */ UInt & operator=(const std::wstring & s) { FromString( s.c_str() ); return *this; } #endif /*! * * methods for comparing * */ /*! this method returns true if 'this' is smaller than 'l' 'index' is an index of the first word from will be the comparison performed (note: we start the comparison from back - from the last word, when index is -1 /default/ it is automatically set into the last word) I introduced it for some kind of optimization made in the second division algorithm (Div2) */ bool CmpSmaller(const UInt & l, sint index = -1) const { sint i; if( index==-1 || index>=sint(value_size) ) i = value_size - 1; else i = index; for( ; i>=0 ; --i) { if( table[i] != l.table[i] ) return table[i] < l.table[i]; } // they're equal return false; } /*! this method returns true if 'this' is bigger than 'l' 'index' is an index of the first word from will be the comparison performed (note: we start the comparison from back - from the last word, when index is -1 /default/ it is automatically set into the last word) I introduced it for some kind of optimization made in the second division algorithm (Div2) */ bool CmpBigger(const UInt & l, sint index = -1) const { sint i; if( index==-1 || index>=sint(value_size) ) i = value_size - 1; else i = index; for( ; i>=0 ; --i) { if( table[i] != l.table[i] ) return table[i] > l.table[i]; } // they're equal return false; } /*! this method returns true if 'this' is equal 'l' 'index' is an index of the first word from will be the comparison performed (note: we start the comparison from back - from the last word, when index is -1 /default/ it is automatically set into the last word) */ bool CmpEqual(const UInt & l, sint index = -1) const { sint i; if( index==-1 || index>=sint(value_size) ) i = value_size - 1; else i = index; for( ; i>=0 ; --i) if( table[i] != l.table[i] ) return false; return true; } /*! this method returns true if 'this' is smaller than or equal 'l' 'index' is an index of the first word from will be the comparison performed (note: we start the comparison from back - from the last word, when index is -1 /default/ it is automatically set into the last word) */ bool CmpSmallerEqual(const UInt & l, sint index=-1) const { sint i; if( index==-1 || index>=sint(value_size) ) i = value_size - 1; else i = index; for( ; i>=0 ; --i) { if( table[i] != l.table[i] ) return table[i] < l.table[i]; } // they're equal return true; } /*! this method returns true if 'this' is bigger than or equal 'l' 'index' is an index of the first word from will be the comparison performed (note: we start the comparison from back - from the last word, when index is -1 /default/ it is automatically set into the last word) */ bool CmpBiggerEqual(const UInt & l, sint index=-1) const { sint i; if( index==-1 || index>=sint(value_size) ) i = value_size - 1; else i = index; for( ; i>=0 ; --i) { if( table[i] != l.table[i] ) return table[i] > l.table[i]; } // they're equal return true; } /* operators for comparising */ bool operator<(const UInt & l) const { return CmpSmaller(l); } bool operator>(const UInt & l) const { return CmpBigger(l); } bool operator==(const UInt & l) const { return CmpEqual(l); } bool operator!=(const UInt & l) const { return !operator==(l); } bool operator<=(const UInt & l) const { return CmpSmallerEqual(l); } bool operator>=(const UInt & l) const { return CmpBiggerEqual(l); } /*! * * standard mathematical operators * */ UInt operator-(const UInt & p2) const { UInt temp(*this); temp.Sub(p2); return temp; } UInt & operator-=(const UInt & p2) { Sub(p2); return *this; } UInt operator+(const UInt & p2) const { UInt temp(*this); temp.Add(p2); return temp; } UInt & operator+=(const UInt & p2) { Add(p2); return *this; } UInt operator*(const UInt & p2) const { UInt temp(*this); temp.Mul(p2); return temp; } UInt & operator*=(const UInt & p2) { Mul(p2); return *this; } UInt operator/(const UInt & p2) const { UInt temp(*this); temp.Div(p2); return temp; } UInt & operator/=(const UInt & p2) { Div(p2); return *this; } UInt operator%(const UInt & p2) const { UInt temp(*this); UInt remainder; temp.Div( p2, remainder ); return remainder; } UInt & operator%=(const UInt & p2) { UInt remainder; Div( p2, remainder ); operator=(remainder); return *this; } /*! Prefix operator e.g ++variable */ UInt & operator++() { AddOne(); return *this; } /*! Postfix operator e.g variable++ */ UInt operator++(int) { UInt temp( *this ); AddOne(); return temp; } UInt & operator--() { SubOne(); return *this; } UInt operator--(int) { UInt temp( *this ); SubOne(); return temp; } /*! * * bitwise operators * */ UInt operator~() const { UInt temp( *this ); temp.BitNot(); return temp; } UInt operator&(const UInt & p2) const { UInt temp( *this ); temp.BitAnd(p2); return temp; } UInt & operator&=(const UInt & p2) { BitAnd(p2); return *this; } UInt operator|(const UInt & p2) const { UInt temp( *this ); temp.BitOr(p2); return temp; } UInt & operator|=(const UInt & p2) { BitOr(p2); return *this; } UInt operator^(const UInt & p2) const { UInt temp( *this ); temp.BitXor(p2); return temp; } UInt & operator^=(const UInt & p2) { BitXor(p2); return *this; } UInt operator>>(int move) const { UInt temp( *this ); temp.Rcr(move); return temp; } UInt & operator>>=(int move) { Rcr(move); return *this; } UInt operator<<(int move) const { UInt temp( *this ); temp.Rcl(move); return temp; } UInt & operator<<=(int move) { Rcl(move); return *this; } /*! * * input/output operators for standard streams * * (they are very simple, in the future they should be changed) * */ private: /*! an auxiliary method for outputing to standard streams */ template static ostream_type & OutputToStream(ostream_type & s, const UInt & l) { string_type ss; l.ToString(ss); s << ss; return s; } public: /*! output to standard streams */ friend std::ostream & operator<<(std::ostream & s, const UInt & l) { return OutputToStream(s, l); } #ifndef TTMATH_DONT_USE_WCHAR /*! output to standard streams */ friend std::wostream & operator<<(std::wostream & s, const UInt & l) { return OutputToStream(s, l); } #endif private: /*! an auxiliary method for reading from standard streams */ template static istream_type & InputFromStream(istream_type & s, UInt & l) { string_type ss; // char or wchar_t for operator>> char_type z; // operator>> omits white characters if they're set for ommiting s >> z; // we're reading only digits (base=10) while( s.good() && Misc::CharToDigit(z, 10)>=0 ) { ss += z; z = static_cast(s.get()); } // we're leaving the last read character // (it's not belonging to the value) s.unget(); l.FromString(ss); return s; } public: /*! input from standard streams */ friend std::istream & operator>>(std::istream & s, UInt & l) { return InputFromStream(s, l); } #ifndef TTMATH_DONT_USE_WCHAR /*! input from standard streams */ friend std::wistream & operator>>(std::wistream & s, UInt & l) { return InputFromStream(s, l); } #endif /* following methods are defined in: ttmathuint_x86.h ttmathuint_x86_64.h ttmathuint_noasm.h */ #ifdef TTMATH_NOASM static uint AddTwoWords(uint a, uint b, uint carry, uint * result); static uint SubTwoWords(uint a, uint b, uint carry, uint * result); #ifdef TTMATH_PLATFORM64 union uint_ { struct { unsigned int low; // 32 bit unsigned int high; // 32 bit } u_; uint u; // 64 bit }; static void DivTwoWords2(uint a,uint b, uint c, uint * r, uint * rest); static uint DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_); static uint DivTwoWordsUnnormalize(uint u, uint d); static unsigned int DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_); static void MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_); #endif // TTMATH_PLATFORM64 #endif // TTMATH_NOASM private: uint Rcl2_one(uint c); uint Rcr2_one(uint c); uint Rcl2(uint bits, uint c); uint Rcr2(uint bits, uint c); public: static const char * LibTypeStr(); static LibTypeCode LibType(); uint Add(const UInt & ss2, uint c=0); uint AddInt(uint value, uint index = 0); uint AddTwoInts(uint x2, uint x1, uint index); static uint AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); uint Sub(const UInt & ss2, uint c=0); uint SubInt(uint value, uint index = 0); static uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result); static sint FindLeadingBitInWord(uint x); static sint FindLowestBitInWord(uint x); static uint SetBitInWord(uint & value, uint bit); static void MulTwoWords(uint a, uint b, uint * result_high, uint * result_low); static void DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest); }; /*! this specialization is needed in order to not confused the compiler "error: ISO C++ forbids zero-size array" when compiling Mul3Big2() method */ template<> class UInt<0> { public: uint table[1]; void Mul2Big(const UInt<0> &, UInt<0> &) { TTMATH_ASSERT(false) }; void SetZero() { TTMATH_ASSERT(false) }; uint AddTwoInts(uint, uint, uint) { TTMATH_ASSERT(false) return 0; }; }; } //namespace #include "ttmathuint_x86.h" #include "ttmathuint_x86_64.h" #include "ttmathuint_noasm.h" #endif discoSnp/minia/ttmath/ttmathbig.h0000644000000000000000000041124412062133074016074 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2010, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathbig #define headerfilettmathbig /*! \file ttmathbig.h \brief A Class for representing floating point numbers */ #include "ttmathint.h" #include "ttmaththreads.h" #include #ifdef TTMATH_MULTITHREADS #include #endif namespace ttmath { /*! \brief Big implements the floating point numbers */ template class Big { /* value = mantissa * 2^exponent exponent - an integer value with a sign mantissa - an integer value without a sing mantissa must be pushed into the left side that is the highest bit from mantissa must be one (of course if there's another value than zero) -- this job (pushing bits into the left side) making Standardizing() method for example: if we want to store value one (1) into our Big object we must: set mantissa to 1 set exponent to 0 set info to 0 and call method Standardizing() */ public: Int exponent; UInt mantissa; unsigned char info; /*! Sign the mask of a bit from 'info' which means that there is a sign (when the bit is set) */ #define TTMATH_BIG_SIGN 128 /*! Not a number if this bit is set that there is not a valid number */ #define TTMATH_BIG_NAN 64 /*! Zero if this bit is set that there is value zero mantissa should be zero and exponent should be zero too (the Standardizing() method does this) */ #define TTMATH_BIG_ZERO 32 /*! this method sets NaN if there was a carry (and returns 1 in such a case) c can be 0, 1 or other value different from zero */ uint CheckCarry(uint c) { if( c != 0 ) { SetNan(); return 1; } return 0; } public: /*! returning the string represents the currect type of the library we have following types: asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) asm_gcc_32 - with asm code designed for GCC (32 bits) asm_vc_64 - with asm for VC (64 bit) asm_gcc_64 - with asm for GCC (64 bit) no_asm_32 - pure C++ version (32 bit) - without any asm code no_asm_64 - pure C++ version (64 bit) - without any asm code */ static const char * LibTypeStr() { return UInt::LibTypeStr(); } /*! returning the currect type of the library */ static LibTypeCode LibType() { return UInt::LibType(); } /*! this method moves all bits from mantissa into its left side (suitably changes the exponent) or if the mantissa is zero it sets the exponent to zero as well (and clears the sign bit and sets the zero bit) it can return a carry the carry will be when we don't have enough space in the exponent you don't have to use this method if you don't change the mantissa and exponent directly */ uint Standardizing() { if( mantissa.IsTheHighestBitSet() ) { ClearInfoBit(TTMATH_BIG_ZERO); return 0; } if( CorrectZero() ) return 0; uint comp = mantissa.CompensationToLeft(); return exponent.Sub( comp ); } private: /*! if the mantissa is equal zero this method sets exponent to zero and info without the sign it returns true if there was the correction */ bool CorrectZero() { if( mantissa.IsZero() ) { SetInfoBit(TTMATH_BIG_ZERO); ClearInfoBit(TTMATH_BIG_SIGN); exponent.SetZero(); return true; } else { ClearInfoBit(TTMATH_BIG_ZERO); } return false; } public: /*! this method clears a specific bit in the 'info' variable bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc. */ void ClearInfoBit(unsigned char bit) { info = info & (~bit); } /*! this method sets a specific bit in the 'info' variable bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc. */ void SetInfoBit(unsigned char bit) { info = info | bit; } /*! this method returns true if a specific bit in the 'info' variable is set bit is one of: TTMATH_BIG_SIGN, TTMATH_BIG_NAN etc. */ bool IsInfoBit(unsigned char bit) const { return (info & bit) != 0; } /*! this method sets zero */ void SetZero() { info = TTMATH_BIG_ZERO; exponent.SetZero(); mantissa.SetZero(); /* we don't have to compensate zero */ } /*! this method sets one */ void SetOne() { info = 0; mantissa.SetZero(); mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; exponent = -sint(man * TTMATH_BITS_PER_UINT - 1); // don't have to Standardize() - the last bit from mantissa is set } /*! this method sets value 0.5 */ void Set05() { SetOne(); exponent.SubOne(); } /*! this method sets NaN flag (Not a Number) when this flag is set that means there is no a valid number */ void SetNan() { SetInfoBit(TTMATH_BIG_NAN); } /*! this method sets NaN flag (Not a Number) also clears the mantissa and exponent (similarly as it would be a zero value) */ void SetZeroNan() { SetZero(); SetNan(); } /*! this method swappes this for an argument */ void Swap(Big & ss2) { unsigned char info_temp = info; info = ss2.info; ss2.info = info_temp; exponent.Swap(ss2.exponent); mantissa.Swap(ss2.mantissa); } private: /*! this method sets the mantissa of the value of pi */ void SetMantissaPi() { // this is a static table which represents the value of Pi (mantissa of it) // (first is the highest word) // we must define this table as 'unsigned int' because // both on 32bit and 64bit platforms this table is 32bit static const unsigned int temp_table[] = { 0xc90fdaa2, 0x2168c234, 0xc4c6628b, 0x80dc1cd1, 0x29024e08, 0x8a67cc74, 0x020bbea6, 0x3b139b22, 0x514a0879, 0x8e3404dd, 0xef9519b3, 0xcd3a431b, 0x302b0a6d, 0xf25f1437, 0x4fe1356d, 0x6d51c245, 0xe485b576, 0x625e7ec6, 0xf44c42e9, 0xa637ed6b, 0x0bff5cb6, 0xf406b7ed, 0xee386bfb, 0x5a899fa5, 0xae9f2411, 0x7c4b1fe6, 0x49286651, 0xece45b3d, 0xc2007cb8, 0xa163bf05, 0x98da4836, 0x1c55d39a, 0x69163fa8, 0xfd24cf5f, 0x83655d23, 0xdca3ad96, 0x1c62f356, 0x208552bb, 0x9ed52907, 0x7096966d, 0x670c354e, 0x4abc9804, 0xf1746c08, 0xca18217c, 0x32905e46, 0x2e36ce3b, 0xe39e772c, 0x180e8603, 0x9b2783a2, 0xec07a28f, 0xb5c55df0, 0x6f4c52c9, 0xde2bcbf6, 0x95581718, 0x3995497c, 0xea956ae5, 0x15d22618, 0x98fa0510, 0x15728e5a, 0x8aaac42d, 0xad33170d, 0x04507a33, 0xa85521ab, 0xdf1cba64, 0xecfb8504, 0x58dbef0a, 0x8aea7157, 0x5d060c7d, 0xb3970f85, 0xa6e1e4c7, 0xabf5ae8c, 0xdb0933d7, 0x1e8c94e0, 0x4a25619d, 0xcee3d226, 0x1ad2ee6b, 0xf12ffa06, 0xd98a0864, 0xd8760273, 0x3ec86a64, 0x521f2b18, 0x177b200c, 0xbbe11757, 0x7a615d6c, 0x770988c0, 0xbad946e2, 0x08e24fa0, 0x74e5ab31, 0x43db5bfc, 0xe0fd108e, 0x4b82d120, 0xa9210801, 0x1a723c12, 0xa787e6d7, 0x88719a10, 0xbdba5b26, 0x99c32718, 0x6af4e23c, 0x1a946834, 0xb6150bda, 0x2583e9ca, 0x2ad44ce8, 0xdbbbc2db, 0x04de8ef9, 0x2e8efc14, 0x1fbecaa6, 0x287c5947, 0x4e6bc05d, 0x99b2964f, 0xa090c3a2, 0x233ba186, 0x515be7ed, 0x1f612970, 0xcee2d7af, 0xb81bdd76, 0x2170481c, 0xd0069127, 0xd5b05aa9, 0x93b4ea98, 0x8d8fddc1, 0x86ffb7dc, 0x90a6c08f, 0x4df435c9, 0x34028492, 0x36c3fab4, 0xd27c7026, 0xc1d4dcb2, 0x602646de, 0xc9751e76, 0x3dba37bd, 0xf8ff9406, 0xad9e530e, 0xe5db382f, 0x413001ae, 0xb06a53ed, 0x9027d831, 0x179727b0, 0x865a8918, 0xda3edbeb, 0xcf9b14ed, 0x44ce6cba, 0xced4bb1b, 0xdb7f1447, 0xe6cc254b, 0x33205151, 0x2bd7af42, 0x6fb8f401, 0x378cd2bf, 0x5983ca01, 0xc64b92ec, 0xf032ea15, 0xd1721d03, 0xf482d7ce, 0x6e74fef6, 0xd55e702f, 0x46980c82, 0xb5a84031, 0x900b1c9e, 0x59e7c97f, 0xbec7e8f3, 0x23a97a7e, 0x36cc88be, 0x0f1d45b7, 0xff585ac5, 0x4bd407b2, 0x2b4154aa, 0xcc8f6d7e, 0xbf48e1d8, 0x14cc5ed2, 0x0f8037e0, 0xa79715ee, 0xf29be328, 0x06a1d58b, 0xb7c5da76, 0xf550aa3d, 0x8a1fbff0, 0xeb19ccb1, 0xa313d55c, 0xda56c9ec, 0x2ef29632, 0x387fe8d7, 0x6e3c0468, 0x043e8f66, 0x3f4860ee, 0x12bf2d5b, 0x0b7474d6, 0xe694f91e, 0x6dbe1159, 0x74a3926f, 0x12fee5e4, 0x38777cb6, 0xa932df8c, 0xd8bec4d0, 0x73b931ba, 0x3bc832b6, 0x8d9dd300, 0x741fa7bf, 0x8afc47ed, 0x2576f693, 0x6ba42466, 0x3aab639c, 0x5ae4f568, 0x3423b474, 0x2bf1c978, 0x238f16cb, 0xe39d652d, 0xe3fdb8be, 0xfc848ad9, 0x22222e04, 0xa4037c07, 0x13eb57a8, 0x1a23f0c7, 0x3473fc64, 0x6cea306b, 0x4bcbc886, 0x2f8385dd, 0xfa9d4b7f, 0xa2c087e8, 0x79683303, 0xed5bdd3a, 0x062b3cf5, 0xb3a278a6, 0x6d2a13f8, 0x3f44f82d, 0xdf310ee0, 0x74ab6a36, 0x4597e899, 0xa0255dc1, 0x64f31cc5, 0x0846851d, 0xf9ab4819, 0x5ded7ea1, 0xb1d510bd, 0x7ee74d73, 0xfaf36bc3, 0x1ecfa268, 0x359046f4, 0xeb879f92, 0x4009438b, 0x481c6cd7, 0x889a002e, 0xd5ee382b, 0xc9190da6, 0xfc026e47, 0x9558e447, 0x5677e9aa, 0x9e3050e2, 0x765694df, 0xc81f56e8, 0x80b96e71, 0x60c980dd, 0x98a573ea, 0x4472065a, 0x139cd290, 0x6cd1cb72, 0x9ec52a53 // last one was: 0x9ec52a52 //0x86d44014, ... // (the last word 0x9ec52a52 was rounded up because the next one is 0x86d44014 -- first bit is one 0x8..) // 256 32bit words for the mantissa -- about 2464 valid decimal digits }; // the value of PI is comming from the website http://zenwerx.com/pi.php // 3101 digits were taken from this website // (later the digits were compared with: // http://www.eveandersson.com/pi/digits/1000000 and http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html ) // and they were set into Big<1,400> type (using operator=(const char*) on a 32bit platform) // and then the first 256 words were taken into this table // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, // and on 64bit platform value 128 (256/2=128)) mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int)); } public: /*! this method sets the value of pi */ void SetPi() { SetMantissaPi(); info = 0; exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2; } /*! this method sets the value of 0.5 * pi */ void Set05Pi() { SetMantissaPi(); info = 0; exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 1; } /*! this method sets the value of 2 * pi */ void Set2Pi() { SetMantissaPi(); info = 0; exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 3; } /*! this method sets the value of e (the base of the natural logarithm) */ void SetE() { static const unsigned int temp_table[] = { 0xadf85458, 0xa2bb4a9a, 0xafdc5620, 0x273d3cf1, 0xd8b9c583, 0xce2d3695, 0xa9e13641, 0x146433fb, 0xcc939dce, 0x249b3ef9, 0x7d2fe363, 0x630c75d8, 0xf681b202, 0xaec4617a, 0xd3df1ed5, 0xd5fd6561, 0x2433f51f, 0x5f066ed0, 0x85636555, 0x3ded1af3, 0xb557135e, 0x7f57c935, 0x984f0c70, 0xe0e68b77, 0xe2a689da, 0xf3efe872, 0x1df158a1, 0x36ade735, 0x30acca4f, 0x483a797a, 0xbc0ab182, 0xb324fb61, 0xd108a94b, 0xb2c8e3fb, 0xb96adab7, 0x60d7f468, 0x1d4f42a3, 0xde394df4, 0xae56ede7, 0x6372bb19, 0x0b07a7c8, 0xee0a6d70, 0x9e02fce1, 0xcdf7e2ec, 0xc03404cd, 0x28342f61, 0x9172fe9c, 0xe98583ff, 0x8e4f1232, 0xeef28183, 0xc3fe3b1b, 0x4c6fad73, 0x3bb5fcbc, 0x2ec22005, 0xc58ef183, 0x7d1683b2, 0xc6f34a26, 0xc1b2effa, 0x886b4238, 0x611fcfdc, 0xde355b3b, 0x6519035b, 0xbc34f4de, 0xf99c0238, 0x61b46fc9, 0xd6e6c907, 0x7ad91d26, 0x91f7f7ee, 0x598cb0fa, 0xc186d91c, 0xaefe1309, 0x85139270, 0xb4130c93, 0xbc437944, 0xf4fd4452, 0xe2d74dd3, 0x64f2e21e, 0x71f54bff, 0x5cae82ab, 0x9c9df69e, 0xe86d2bc5, 0x22363a0d, 0xabc52197, 0x9b0deada, 0x1dbf9a42, 0xd5c4484e, 0x0abcd06b, 0xfa53ddef, 0x3c1b20ee, 0x3fd59d7c, 0x25e41d2b, 0x669e1ef1, 0x6e6f52c3, 0x164df4fb, 0x7930e9e4, 0xe58857b6, 0xac7d5f42, 0xd69f6d18, 0x7763cf1d, 0x55034004, 0x87f55ba5, 0x7e31cc7a, 0x7135c886, 0xefb4318a, 0xed6a1e01, 0x2d9e6832, 0xa907600a, 0x918130c4, 0x6dc778f9, 0x71ad0038, 0x092999a3, 0x33cb8b7a, 0x1a1db93d, 0x7140003c, 0x2a4ecea9, 0xf98d0acc, 0x0a8291cd, 0xcec97dcf, 0x8ec9b55a, 0x7f88a46b, 0x4db5a851, 0xf44182e1, 0xc68a007e, 0x5e0dd902, 0x0bfd64b6, 0x45036c7a, 0x4e677d2c, 0x38532a3a, 0x23ba4442, 0xcaf53ea6, 0x3bb45432, 0x9b7624c8, 0x917bdd64, 0xb1c0fd4c, 0xb38e8c33, 0x4c701c3a, 0xcdad0657, 0xfccfec71, 0x9b1f5c3e, 0x4e46041f, 0x388147fb, 0x4cfdb477, 0xa52471f7, 0xa9a96910, 0xb855322e, 0xdb6340d8, 0xa00ef092, 0x350511e3, 0x0abec1ff, 0xf9e3a26e, 0x7fb29f8c, 0x183023c3, 0x587e38da, 0x0077d9b4, 0x763e4e4b, 0x94b2bbc1, 0x94c6651e, 0x77caf992, 0xeeaac023, 0x2a281bf6, 0xb3a739c1, 0x22611682, 0x0ae8db58, 0x47a67cbe, 0xf9c9091b, 0x462d538c, 0xd72b0374, 0x6ae77f5e, 0x62292c31, 0x1562a846, 0x505dc82d, 0xb854338a, 0xe49f5235, 0xc95b9117, 0x8ccf2dd5, 0xcacef403, 0xec9d1810, 0xc6272b04, 0x5b3b71f9, 0xdc6b80d6, 0x3fdd4a8e, 0x9adb1e69, 0x62a69526, 0xd43161c1, 0xa41d570d, 0x7938dad4, 0xa40e329c, 0xcff46aaa, 0x36ad004c, 0xf600c838, 0x1e425a31, 0xd951ae64, 0xfdb23fce, 0xc9509d43, 0x687feb69, 0xedd1cc5e, 0x0b8cc3bd, 0xf64b10ef, 0x86b63142, 0xa3ab8829, 0x555b2f74, 0x7c932665, 0xcb2c0f1c, 0xc01bd702, 0x29388839, 0xd2af05e4, 0x54504ac7, 0x8b758282, 0x2846c0ba, 0x35c35f5c, 0x59160cc0, 0x46fd8251, 0x541fc68c, 0x9c86b022, 0xbb709987, 0x6a460e74, 0x51a8a931, 0x09703fee, 0x1c217e6c, 0x3826e52c, 0x51aa691e, 0x0e423cfc, 0x99e9e316, 0x50c1217b, 0x624816cd, 0xad9a95f9, 0xd5b80194, 0x88d9c0a0, 0xa1fe3075, 0xa577e231, 0x83f81d4a, 0x3f2fa457, 0x1efc8ce0, 0xba8a4fe8, 0xb6855dfe, 0x72b0a66e, 0xded2fbab, 0xfbe58a30, 0xfafabe1c, 0x5d71a87e, 0x2f741ef8, 0xc1fe86fe, 0xa6bbfde5, 0x30677f0d, 0x97d11d49, 0xf7a8443d, 0x0822e506, 0xa9f4614e, 0x011e2a94, 0x838ff88c, 0xd68c8bb7, 0xc51eef6d, 0x49ea8ab4, 0xf2c3df5b, 0xb4e0735a, 0xb0d68749 // 0x2fe26dd4, ... // 256 32bit words for the mantissa -- about 2464 valid decimal digits }; // above value was calculated using Big<1,400> type on a 32bit platform // and then the first 256 words were taken, // the calculating was made by using ExpSurrounding0(1) method // which took 1420 iterations // (the result was compared with e taken from http://antwrp.gsfc.nasa.gov/htmltest/gifcity/e.2mil) // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, // and on 64bit platform value 128 (256/2=128)) mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int)); exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2; info = 0; } /*! this method sets the value of ln(2) the natural logarithm from 2 */ void SetLn2() { static const unsigned int temp_table[] = { 0xb17217f7, 0xd1cf79ab, 0xc9e3b398, 0x03f2f6af, 0x40f34326, 0x7298b62d, 0x8a0d175b, 0x8baafa2b, 0xe7b87620, 0x6debac98, 0x559552fb, 0x4afa1b10, 0xed2eae35, 0xc1382144, 0x27573b29, 0x1169b825, 0x3e96ca16, 0x224ae8c5, 0x1acbda11, 0x317c387e, 0xb9ea9bc3, 0xb136603b, 0x256fa0ec, 0x7657f74b, 0x72ce87b1, 0x9d6548ca, 0xf5dfa6bd, 0x38303248, 0x655fa187, 0x2f20e3a2, 0xda2d97c5, 0x0f3fd5c6, 0x07f4ca11, 0xfb5bfb90, 0x610d30f8, 0x8fe551a2, 0xee569d6d, 0xfc1efa15, 0x7d2e23de, 0x1400b396, 0x17460775, 0xdb8990e5, 0xc943e732, 0xb479cd33, 0xcccc4e65, 0x9393514c, 0x4c1a1e0b, 0xd1d6095d, 0x25669b33, 0x3564a337, 0x6a9c7f8a, 0x5e148e82, 0x074db601, 0x5cfe7aa3, 0x0c480a54, 0x17350d2c, 0x955d5179, 0xb1e17b9d, 0xae313cdb, 0x6c606cb1, 0x078f735d, 0x1b2db31b, 0x5f50b518, 0x5064c18b, 0x4d162db3, 0xb365853d, 0x7598a195, 0x1ae273ee, 0x5570b6c6, 0x8f969834, 0x96d4e6d3, 0x30af889b, 0x44a02554, 0x731cdc8e, 0xa17293d1, 0x228a4ef9, 0x8d6f5177, 0xfbcf0755, 0x268a5c1f, 0x9538b982, 0x61affd44, 0x6b1ca3cf, 0x5e9222b8, 0x8c66d3c5, 0x422183ed, 0xc9942109, 0x0bbb16fa, 0xf3d949f2, 0x36e02b20, 0xcee886b9, 0x05c128d5, 0x3d0bd2f9, 0x62136319, 0x6af50302, 0x0060e499, 0x08391a0c, 0x57339ba2, 0xbeba7d05, 0x2ac5b61c, 0xc4e9207c, 0xef2f0ce2, 0xd7373958, 0xd7622658, 0x901e646a, 0x95184460, 0xdc4e7487, 0x156e0c29, 0x2413d5e3, 0x61c1696d, 0xd24aaebd, 0x473826fd, 0xa0c238b9, 0x0ab111bb, 0xbd67c724, 0x972cd18b, 0xfbbd9d42, 0x6c472096, 0xe76115c0, 0x5f6f7ceb, 0xac9f45ae, 0xcecb72f1, 0x9c38339d, 0x8f682625, 0x0dea891e, 0xf07afff3, 0xa892374e, 0x175eb4af, 0xc8daadd8, 0x85db6ab0, 0x3a49bd0d, 0xc0b1b31d, 0x8a0e23fa, 0xc5e5767d, 0xf95884e0, 0x6425a415, 0x26fac51c, 0x3ea8449f, 0xe8f70edd, 0x062b1a63, 0xa6c4c60c, 0x52ab3316, 0x1e238438, 0x897a39ce, 0x78b63c9f, 0x364f5b8a, 0xef22ec2f, 0xee6e0850, 0xeca42d06, 0xfb0c75df, 0x5497e00c, 0x554b03d7, 0xd2874a00, 0x0ca8f58d, 0x94f0341c, 0xbe2ec921, 0x56c9f949, 0xdb4a9316, 0xf281501e, 0x53daec3f, 0x64f1b783, 0x154c6032, 0x0e2ff793, 0x33ce3573, 0xfacc5fdc, 0xf1178590, 0x3155bbd9, 0x0f023b22, 0x0224fcd8, 0x471bf4f4, 0x45f0a88a, 0x14f0cd97, 0x6ea354bb, 0x20cdb5cc, 0xb3db2392, 0x88d58655, 0x4e2a0e8a, 0x6fe51a8c, 0xfaa72ef2, 0xad8a43dc, 0x4212b210, 0xb779dfe4, 0x9d7307cc, 0x846532e4, 0xb9694eda, 0xd162af05, 0x3b1751f3, 0xa3d091f6, 0x56658154, 0x12b5e8c2, 0x02461069, 0xac14b958, 0x784934b8, 0xd6cce1da, 0xa5053701, 0x1aa4fb42, 0xb9a3def4, 0x1bda1f85, 0xef6fdbf2, 0xf2d89d2a, 0x4b183527, 0x8fd94057, 0x89f45681, 0x2b552879, 0xa6168695, 0xc12963b0, 0xff01eaab, 0x73e5b5c1, 0x585318e7, 0x624f14a5, 0x1a4a026b, 0x68082920, 0x57fd99b6, 0x6dc085a9, 0x8ac8d8ca, 0xf9eeeea9, 0x8a2400ca, 0xc95f260f, 0xd10036f9, 0xf91096ac, 0x3195220a, 0x1a356b2a, 0x73b7eaad, 0xaf6d6058, 0x71ef7afb, 0x80bc4234, 0x33562e94, 0xb12dfab4, 0x14451579, 0xdf59eae0, 0x51707062, 0x4012a829, 0x62c59cab, 0x347f8304, 0xd889659e, 0x5a9139db, 0x14efcc30, 0x852be3e8, 0xfc99f14d, 0x1d822dd6, 0xe2f76797, 0xe30219c8, 0xaa9ce884, 0x8a886eb3, 0xc87b7295, 0x988012e8, 0x314186ed, 0xbaf86856, 0xccd3c3b6, 0xee94e62f, 0x110a6783, 0xd2aae89c, 0xcc3b76fc, 0x435a0ce1, 0x34c2838f, 0xd571ec6c, 0x1366a993 // last one was: 0x1366a992 //0xcbb9ac40, ... // (the last word 0x1366a992 was rounded up because the next one is 0xcbb9ac40 -- first bit is one 0xc..) // 256 32bit words for the mantissa -- about 2464 valid decimal digits }; // above value was calculated using Big<1,400> type on a 32bit platform // and then the first 256 words were taken, // the calculating was made by using LnSurrounding1(2) method // which took 4035 iterations // (the result was compared with ln(2) taken from http://ja0hxv.calico.jp/pai/estart.html) // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, // and on 64bit platform value 128 (256/2=128)) mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int)); exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT); info = 0; } /*! this method sets the value of ln(10) the natural logarithm from 10 I introduced this constant especially to make the conversion ToString() being faster. In fact the method ToString() is keeping values of logarithms it has calculated but it must calculate the logarithm at least once. If a program, which uses this library, is running for a long time this would be ok, but for programs which are running shorter, for example for CGI applications which only once are printing values, this would be much inconvenience. Then if we're printing with base (radix) 10 and the mantissa of our value is smaller than or equal to TTMATH_BUILTIN_VARIABLES_SIZE we don't calculate the logarithm but take it from this constant. */ void SetLn10() { static const unsigned int temp_table[] = { 0x935d8ddd, 0xaaa8ac16, 0xea56d62b, 0x82d30a28, 0xe28fecf9, 0xda5df90e, 0x83c61e82, 0x01f02d72, 0x962f02d7, 0xb1a8105c, 0xcc70cbc0, 0x2c5f0d68, 0x2c622418, 0x410be2da, 0xfb8f7884, 0x02e516d6, 0x782cf8a2, 0x8a8c911e, 0x765aa6c3, 0xb0d831fb, 0xef66ceb0, 0x4ab3c6fa, 0x5161bb49, 0xd219c7bb, 0xca67b35b, 0x23605085, 0x8e93368d, 0x44789c4f, 0x5b08b057, 0xd5ede20f, 0x469ea58e, 0x9305e981, 0xe2478fca, 0xad3aee98, 0x9cd5b42e, 0x6a271619, 0xa47ecb26, 0x978c5d4f, 0xdb1d28ea, 0x57d4fdc0, 0xe40bf3cc, 0x1e14126a, 0x45765cde, 0x268339db, 0xf47fa96d, 0xeb271060, 0xaf88486e, 0xa9b7401e, 0x3dfd3c51, 0x748e6d6e, 0x3848c8d2, 0x5faf1bca, 0xe88047f1, 0x7b0d9b50, 0xa949eaaa, 0xdf69e8a5, 0xf77e3760, 0x4e943960, 0xe38a5700, 0xffde2db1, 0xad6bfbff, 0xd821ba0a, 0x4cb0466d, 0x61ba648e, 0xef99c8e5, 0xf6974f36, 0x3982a78c, 0xa45ddfc8, 0x09426178, 0x19127a6e, 0x3b70fcda, 0x2d732d47, 0xb5e4b1c8, 0xc0e5a10a, 0xaa6604a5, 0x324ec3dc, 0xbc64ea80, 0x6e198566, 0x1f1d366c, 0x20663834, 0x4d5e843f, 0x20642b97, 0x0a62d18e, 0x478f7bd5, 0x8fcd0832, 0x4a7b32a6, 0xdef85a05, 0xeb56323a, 0x421ef5e0, 0xb00410a0, 0xa0d9c260, 0x794a976f, 0xf6ff363d, 0xb00b6b33, 0xf42c58de, 0xf8a3c52d, 0xed69b13d, 0xc1a03730, 0xb6524dc1, 0x8c167e86, 0x99d6d20e, 0xa2defd2b, 0xd006f8b4, 0xbe145a2a, 0xdf3ccbb3, 0x189da49d, 0xbc1261c8, 0xb3e4daad, 0x6a36cecc, 0xb2d5ae5b, 0x89bf752f, 0xb5dfb353, 0xff3065c4, 0x0cfceec8, 0x1be5a9a9, 0x67fddc57, 0xc4b83301, 0x006bf062, 0x4b40ed7a, 0x56c6cdcd, 0xa2d6fe91, 0x388e9e3e, 0x48a93f5f, 0x5e3b6eb4, 0xb81c4a5b, 0x53d49ea6, 0x8e668aea, 0xba83c7f8, 0xfb5f06c3, 0x58ac8f70, 0xfa9d8c59, 0x8c574502, 0xbaf54c96, 0xc84911f0, 0x0482d095, 0x1a0af022, 0xabbab080, 0xec97efd3, 0x671e4e0e, 0x52f166b6, 0xcd5cd226, 0x0dc67795, 0x2e1e34a3, 0xf799677f, 0x2c1d48f1, 0x2944b6c5, 0x2ba1307e, 0x704d67f9, 0x1c1035e4, 0x4e927c63, 0x03cf12bf, 0xe2cd2e31, 0xf8ee4843, 0x344d51b0, 0xf37da42b, 0x9f0b0fd9, 0x134fb2d9, 0xf815e490, 0xd966283f, 0x23962766, 0xeceab1e4, 0xf3b5fc86, 0x468127e2, 0xb606d10d, 0x3a45f4b6, 0xb776102d, 0x2fdbb420, 0x80c8fa84, 0xd0ff9f45, 0xc58aef38, 0xdb2410fd, 0x1f1cebad, 0x733b2281, 0x52ca5f36, 0xddf29daa, 0x544334b8, 0xdeeaf659, 0x4e462713, 0x1ed485b4, 0x6a0822e1, 0x28db471c, 0xa53938a8, 0x44c3bef7, 0xf35215c8, 0xb382bc4e, 0x3e4c6f15, 0x6285f54c, 0x17ab408e, 0xccbf7f5e, 0xd16ab3f6, 0xced2846d, 0xf457e14f, 0xbb45d9c5, 0x646ad497, 0xac697494, 0x145de32e, 0x93907128, 0xd263d521, 0x79efb424, 0xd64651d6, 0xebc0c9f0, 0xbb583a44, 0xc6412c84, 0x85bb29a6, 0x4d31a2cd, 0x92954469, 0xa32b1abd, 0xf7f5202c, 0xa4aa6c93, 0x2e9b53cf, 0x385ab136, 0x2741f356, 0x5de9c065, 0x6009901c, 0x88abbdd8, 0x74efcf73, 0x3f761ad4, 0x35f3c083, 0xfd6b8ee0, 0x0bef11c7, 0xc552a89d, 0x58ce4a21, 0xd71e54f2, 0x4157f6c7, 0xd4622316, 0xe98956d7, 0x450027de, 0xcbd398d8, 0x4b98b36a, 0x0724c25c, 0xdb237760, 0xe9324b68, 0x7523e506, 0x8edad933, 0x92197f00, 0xb853a326, 0xb330c444, 0x65129296, 0x34bc0670, 0xe177806d, 0xe338dac4, 0x5537492a, 0xe19add83, 0xcf45000f, 0x5b423bce, 0x6497d209, 0xe30e18a1, 0x3cbf0687, 0x67973103, 0xd9485366, 0x81506bba, 0x2e93a9a4, 0x7dd59d3f, 0xf17cd746, 0x8c2075be, 0x552a4348 // last one was: 0x552a4347 // 0xb4a638ef, ... //(the last word 0x552a4347 was rounded up because the next one is 0xb4a638ef -- first bit is one 0xb..) // 256 32bit words for the mantissa -- about 2464 valid digits (decimal) }; // above value was calculated using Big<1,400> type on a 32bit platform // and then the first 256 32bit words were taken, // the calculating was made by using LnSurrounding1(10) method // which took 22080 iterations // (the result was compared with ln(10) taken from http://ja0hxv.calico.jp/pai/estart.html) // (the formula used in LnSurrounding1(x) converges badly when // the x is greater than one but in fact we can use it, only the // number of iterations will be greater) // (TTMATH_BUILTIN_VARIABLES_SIZE on 32bit platform should have the value 256, // and on 64bit platform value 128 (256/2=128)) mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(int)); exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2; info = 0; } /*! this method sets the maximum value which can be held in this type */ void SetMax() { info = 0; mantissa.SetMax(); exponent.SetMax(); // we don't have to use 'Standardizing()' because the last bit from // the mantissa is set } /*! this method sets the minimum value which can be held in this type */ void SetMin() { info = 0; mantissa.SetMax(); exponent.SetMax(); SetSign(); // we don't have to use 'Standardizing()' because the last bit from // the mantissa is set } /*! testing whether there is a value zero or not */ bool IsZero() const { return IsInfoBit(TTMATH_BIG_ZERO); } /*! this method returns true when there's the sign set also we don't check the NaN flag */ bool IsSign() const { return IsInfoBit(TTMATH_BIG_SIGN); } /*! this method returns true when there is not a valid number */ bool IsNan() const { return IsInfoBit(TTMATH_BIG_NAN); } /*! this method clears the sign (there'll be an absolute value) e.g. -1 -> 1 2 -> 2 */ void Abs() { ClearInfoBit(TTMATH_BIG_SIGN); } /*! this method remains the 'sign' of the value e.g. -2 = -1 0 = 0 10 = 1 */ void Sgn() { // we have to check the NaN flag, because the next SetOne() method would clear it if( IsNan() ) return; if( IsSign() ) { SetOne(); SetSign(); } else if( IsZero() ) SetZero(); // !! is nedeed here? else SetOne(); } /*! this method sets the sign e.g. -1 -> -1 2 -> -2 we do not check whether there is a zero or not, if you're using this method you must be sure that the value is (or will be afterwards) different from zero */ void SetSign() { SetInfoBit(TTMATH_BIG_SIGN); } /*! this method changes the sign when there is a value of zero then the sign is not changed e.g. -1 -> 1 2 -> -2 */ void ChangeSign() { // we don't have to check the NaN flag here if( IsZero() ) return; if( IsSign() ) ClearInfoBit(TTMATH_BIG_SIGN); else SetInfoBit(TTMATH_BIG_SIGN); } private: /*! this method does the half-to-even rounding (banker's rounding) if is_half is: true - that means the rest was equal the half (0.5 decimal) false - that means the rest was greater than a half (greater than 0.5 decimal) if the rest was less than a half then don't call this method (the rounding should does nothing then) */ uint RoundHalfToEven(bool is_half, bool rounding_up = true) { uint c = 0; if( !is_half || mantissa.IsTheLowestBitSet() ) { if( rounding_up ) { if( mantissa.AddOne() ) { mantissa.Rcr(1, 1); c = exponent.AddOne(); } } else { #ifdef TTMATH_DEBUG uint c_from_zero = #endif mantissa.SubOne(); // we're using rounding_up=false in Add() when the mantissas have different signs // mantissa can be zero only when previous mantissa was equal to ss2.mantissa // but in such a case 'last_bit_set' will not be set and consequently 'do_rounding' will be false TTMATH_ASSERT( c_from_zero == 0 ) } } return c; } /*! * * basic mathematic functions * */ /*! this method adds one to the existing value */ uint AddOne() { Big one; one.SetOne(); return Add(one); } /*! this method subtracts one from the existing value */ uint SubOne() { Big one; one.SetOne(); return Sub(one); } private: /*! an auxiliary method for adding */ void AddCheckExponents( Big & ss2, Int & exp_offset, bool & last_bit_set, bool & rest_zero, bool & do_adding, bool & do_rounding) { Int mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); if( exp_offset == mantissa_size_in_bits ) { last_bit_set = ss2.mantissa.IsTheHighestBitSet(); rest_zero = ss2.mantissa.AreFirstBitsZero(man*TTMATH_BITS_PER_UINT - 1); do_rounding = true; // we'are only rounding } else if( exp_offset < mantissa_size_in_bits ) { uint moved = exp_offset.ToInt(); // how many times we must move ss2.mantissa rest_zero = true; if( moved > 0 ) { last_bit_set = static_cast( ss2.mantissa.GetBit(moved-1) ); if( moved > 1 ) rest_zero = ss2.mantissa.AreFirstBitsZero(moved - 1); // (2) moving 'exp_offset' times ss2.mantissa.Rcr(moved, 0); } do_adding = true; do_rounding = true; } // if exp_offset is greater than mantissa_size_in_bits then we do nothing // ss2 is too small for taking into consideration in the sum } /*! an auxiliary method for adding */ uint AddMantissas( Big & ss2, bool & last_bit_set, bool & rest_zero) { uint c = 0; if( IsSign() == ss2.IsSign() ) { // values have the same signs if( mantissa.Add(ss2.mantissa) ) { // we have one bit more from addition (carry) // now rest_zero means the old rest_zero with the old last_bit_set rest_zero = (!last_bit_set && rest_zero); last_bit_set = mantissa.Rcr(1,1); c += exponent.AddOne(); } } else { // values have different signs // there shouldn't be a carry here because // (1) (2) guarantee that the mantissa of this // is greater than or equal to the mantissa of the ss2 #ifdef TTMATH_DEBUG uint c_temp = #endif mantissa.Sub(ss2.mantissa); TTMATH_ASSERT( c_temp == 0 ) } return c; } public: /*! Addition this = this + ss2 it returns carry if the sum is too big */ uint Add(Big ss2, bool round = true, bool adding = true) { bool last_bit_set, rest_zero, do_adding, do_rounding, rounding_up; Int exp_offset( exponent ); uint c = 0; if( IsNan() || ss2.IsNan() ) return CheckCarry(1); if( !adding ) ss2.ChangeSign(); // subtracting exp_offset.Sub( ss2.exponent ); exp_offset.Abs(); // (1) abs(this) will be >= abs(ss2) if( SmallerWithoutSignThan(ss2) ) Swap(ss2); if( ss2.IsZero() ) return 0; last_bit_set = rest_zero = do_adding = do_rounding = false; rounding_up = (IsSign() == ss2.IsSign()); AddCheckExponents(ss2, exp_offset, last_bit_set, rest_zero, do_adding, do_rounding); if( do_adding ) c += AddMantissas(ss2, last_bit_set, rest_zero); if( !round || !last_bit_set ) do_rounding = false; if( do_rounding ) c += RoundHalfToEven(rest_zero, rounding_up); if( do_adding || do_rounding ) c += Standardizing(); return CheckCarry(c); } /*! Subtraction this = this - ss2 it returns carry if the result is too big */ uint Sub(const Big & ss2, bool round = true) { return Add(ss2, round, false); } /*! bitwise AND this and ss2 must be >= 0 return values: 0 - ok 1 - carry 2 - this or ss2 was negative */ uint BitAnd(Big ss2) { if( IsNan() || ss2.IsNan() ) return CheckCarry(1); if( IsSign() || ss2.IsSign() ) { SetNan(); return 2; } if( IsZero() ) return 0; if( ss2.IsZero() ) { SetZero(); return 0; } Int exp_offset( exponent ); Int mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); uint c = 0; exp_offset.Sub( ss2.exponent ); exp_offset.Abs(); // abs(this) will be >= abs(ss2) if( SmallerWithoutSignThan(ss2) ) Swap(ss2); if( exp_offset >= mantissa_size_in_bits ) { // the second value is too small SetZero(); return 0; } // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times ss2.mantissa.Rcr( exp_offset.ToInt(), 0 ); mantissa.BitAnd(ss2.mantissa); c += Standardizing(); return CheckCarry(c); } /*! bitwise OR this and ss2 must be >= 0 return values: 0 - ok 1 - carry 2 - this or ss2 was negative */ uint BitOr(Big ss2) { if( IsNan() || ss2.IsNan() ) return CheckCarry(1); if( IsSign() || ss2.IsSign() ) { SetNan(); return 2; } if( IsZero() ) { *this = ss2; return 0; } if( ss2.IsZero() ) return 0; Int exp_offset( exponent ); Int mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); uint c = 0; exp_offset.Sub( ss2.exponent ); exp_offset.Abs(); // abs(this) will be >= abs(ss2) if( SmallerWithoutSignThan(ss2) ) Swap(ss2); if( exp_offset >= mantissa_size_in_bits ) // the second value is too small return 0; // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times ss2.mantissa.Rcr( exp_offset.ToInt(), 0 ); mantissa.BitOr(ss2.mantissa); c += Standardizing(); return CheckCarry(c); } /*! bitwise XOR this and ss2 must be >= 0 return values: 0 - ok 1 - carry 2 - this or ss2 was negative */ uint BitXor(Big ss2) { if( IsNan() || ss2.IsNan() ) return CheckCarry(1); if( IsSign() || ss2.IsSign() ) { SetNan(); return 2; } if( ss2.IsZero() ) return 0; if( IsZero() ) { *this = ss2; return 0; } Int exp_offset( exponent ); Int mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT ); uint c = 0; exp_offset.Sub( ss2.exponent ); exp_offset.Abs(); // abs(this) will be >= abs(ss2) if( SmallerWithoutSignThan(ss2) ) Swap(ss2); if( exp_offset >= mantissa_size_in_bits ) // the second value is too small return 0; // exp_offset < mantissa_size_in_bits, moving 'exp_offset' times ss2.mantissa.Rcr( exp_offset.ToInt(), 0 ); mantissa.BitXor(ss2.mantissa); c += Standardizing(); return CheckCarry(c); } /*! Multiplication this = this * ss2 (ss2 is uint) ss2 without a sign */ uint MulUInt(uint ss2) { UInt man_result; uint i,c = 0; if( IsNan() ) return 1; if( IsZero() ) return 0; if( ss2 == 0 ) { SetZero(); return 0; } // man_result = mantissa * ss2.mantissa mantissa.MulInt(ss2, man_result); sint bit = UInt::FindLeadingBitInWord(man_result.table[man]); // man - last word if( bit!=-1 && uint(bit) > (TTMATH_BITS_PER_UINT/2) ) { // 'i' will be from 0 to TTMATH_BITS_PER_UINT i = man_result.CompensationToLeft(); c = exponent.Add( TTMATH_BITS_PER_UINT - i ); for(i=0 ; i0 && (tab[len-1] & TTMATH_UINT_HIGHEST_BIT)!=0 ) for(i=0 ; i & ss2, bool round = true) { TTMATH_REFERENCE_ASSERT( ss2 ) UInt man_result; uint c = 0; uint i; if( IsNan() || ss2.IsNan() ) return CheckCarry(1); if( IsZero() ) return 0; if( ss2.IsZero() ) { SetZero(); return 0; } // man_result = mantissa * ss2.mantissa mantissa.MulBig(ss2.mantissa, man_result); // 'i' will be from 0 to man*TTMATH_BITS_PER_UINT // because mantissa and ss2.mantissa are standardized // (the highest bit in man_result is set to 1 or // if there is a zero value in man_result the method CompensationToLeft() // returns 0 but we'll correct this at the end in Standardizing() method) i = man_result.CompensationToLeft(); uint exp_add = man * TTMATH_BITS_PER_UINT - i; if( exp_add ) c += exponent.Add( exp_add ); c += exponent.Add( ss2.exponent ); for(i=0 ; i & ss2, bool round = true) { if( this == &ss2 ) { Big copy_ss2(ss2); return MulRef(copy_ss2, round); } else { return MulRef(ss2, round); } } private: /*! division this = this / ss2 return value: 0 - ok 1 - carry (in a division carry can be as well) 2 - improper argument (ss2 is zero) */ uint DivRef(const Big & ss2, bool round = true) { TTMATH_REFERENCE_ASSERT( ss2 ) UInt man1; UInt man2; uint i,c = 0; if( IsNan() || ss2.IsNan() ) return CheckCarry(1); if( ss2.IsZero() ) { SetNan(); return 2; } if( IsZero() ) return 0; // !! this two loops can be joined together for(i=0 ; i & ss2, bool round = true) { if( this == &ss2 ) { Big copy_ss2(ss2); return DivRef(copy_ss2, round); } else { return DivRef(ss2, round); } } private: /*! the remainder from a division */ uint ModRef(const Big & ss2) { TTMATH_REFERENCE_ASSERT( ss2 ) uint c = 0; if( IsNan() || ss2.IsNan() ) return CheckCarry(1); if( ss2.IsZero() ) { SetNan(); return 2; } if( !SmallerWithoutSignThan(ss2) ) { Big temp(*this); c = temp.Div(ss2); temp.SkipFraction(); c += temp.Mul(ss2); c += Sub(temp); if( !SmallerWithoutSignThan( ss2 ) ) c += 1; } return CheckCarry(c); } public: /*! the remainder from a division e.g. 12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6 -12.6 mod 3 = -0.6 bacause -12.6 = 3*(-4) + (-0.6) 12.6 mod -3 = 0.6 -12.6 mod -3 = -0.6 it means: in other words: this(old) = ss2 * q + this(new) return value: 0 - ok 1 - carry 2 - improper argument (ss2 is zero) */ uint Mod(const Big & ss2) { if( this == &ss2 ) { Big copy_ss2(ss2); return ModRef(copy_ss2); } else { return ModRef(ss2); } } /*! this method returns: 'this' mod 2 (either zero or one) this method is much faster than using Mod( object_with_value_two ) */ uint Mod2() const { if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) ) return 0; sint exp_int = exponent.ToInt(); // 'exp_int' is negative (or zero), we set it as positive exp_int = -exp_int; return mantissa.GetBit(exp_int); } /*! power this = this ^ pow (pow without a sign) binary algorithm (r-to-l) return values: 0 - ok 1 - carry 2 - incorrect arguments (0^0) */ template uint Pow(UInt pow) { if( IsNan() ) return 1; if( IsZero() ) { if( pow.IsZero() ) { // we don't define zero^zero SetNan(); return 2; } // 0^(+something) is zero return 0; } Big start(*this), start_temp; Big result; result.SetOne(); uint c = 0; while( !c ) { if( pow.table[0] & 1 ) c += result.Mul(start); pow.Rcr(1); if( pow.IsZero() ) break; start_temp = start; c += start.Mul(start_temp); } *this = result; return CheckCarry(c); } /*! power this = this ^ pow p can be negative return values: 0 - ok 1 - carry 2 - incorrect arguments 0^0 or 0^(-something) */ template uint Pow(Int pow) { if( IsNan() ) return 1; if( !pow.IsSign() ) return Pow( UInt(pow) ); if( IsZero() ) { // if 'p' is negative then // 'this' must be different from zero SetNan(); return 2; } uint c = pow.ChangeSign(); Big t(*this); c += t.Pow( UInt(pow) ); // here can only be a carry (return:1) SetOne(); c += Div(t); return CheckCarry(c); } /*! power this = this ^ abs([pow]) pow is treated as a value without a sign and without a fraction if pow has a sign then the method pow.Abs() is used if pow has a fraction the fraction is skipped (not used in calculation) return values: 0 - ok 1 - carry 2 - incorrect arguments (0^0) */ uint PowUInt(Big pow) { if( IsNan() || pow.IsNan() ) return CheckCarry(1); if( IsZero() ) { if( pow.IsZero() ) { SetNan(); return 2; } // 0^(+something) is zero return 0; } if( pow.IsSign() ) pow.Abs(); Big start(*this), start_temp; Big result; Big one; Int e_one; uint c = 0; e_one.SetOne(); one.SetOne(); result = one; while( !c ) { if( pow.Mod2() ) c += result.Mul(start); c += pow.exponent.Sub( e_one ); // !! may use SubOne() here? if( pow < one ) break; start_temp = start; c += start.Mul(start_temp); } *this = result; return CheckCarry(c); } /*! power this = this ^ [pow] pow is treated as a value without a fraction pow can be negative return values: 0 - ok 1 - carry 2 - incorrect arguments 0^0 or 0^(-something) */ uint PowInt(const Big & pow) { if( IsNan() || pow.IsNan() ) return CheckCarry(1); if( !pow.IsSign() ) return PowUInt(pow); if( IsZero() ) { // if 'pow' is negative then // 'this' must be different from zero SetNan(); return 2; } Big temp(*this); uint c = temp.PowUInt(pow); // here can only be a carry (result:1) SetOne(); c += Div(temp); return CheckCarry(c); } /*! power this = this ^ pow this must be greater than zero (this > 0) pow can be negative and with fraction return values: 0 - ok 1 - carry 2 - incorrect argument ('this' <= 0) */ uint PowFrac(const Big & pow) { if( IsNan() || pow.IsNan() ) return CheckCarry(1); Big temp; uint c = temp.Ln(*this); if( c != 0 ) // can be 2 from Ln() { SetNan(); return c; } c += temp.Mul(pow); c += Exp(temp); return CheckCarry(c); } /*! power this = this ^ pow pow can be negative and with fraction return values: 0 - ok 1 - carry 2 - incorrect argument ('this' or 'pow') */ uint Pow(const Big & pow) { if( IsNan() || pow.IsNan() ) return CheckCarry(1); if( IsZero() ) { // 0^pow will be 0 only for pow>0 if( pow.IsSign() || pow.IsZero() ) { SetNan(); return 2; } SetZero(); return 0; } if( pow.exponent>-sint(man*TTMATH_BITS_PER_UINT) && pow.exponent<=0 ) { if( pow.IsInteger() ) return PowInt( pow ); } return PowFrac(pow); } /*! this function calculates the square root e.g. let this=9 then this.Sqrt() gives 3 return: 0 - ok 1 - carry 2 - improper argument (this<0 or NaN) */ uint Sqrt() { if( IsNan() || IsSign() ) { SetNan(); return 2; } if( IsZero() ) return 0; Big old(*this); Big ln; uint c = 0; // we're using the formula: sqrt(x) = e ^ (ln(x) / 2) c += ln.Ln(*this); c += ln.exponent.SubOne(); // ln = ln / 2 c += Exp(ln); // above formula doesn't give accurate results for some integers // e.g. Sqrt(81) would not be 9 but a value very closed to 9 // we're rounding the result, calculating result*result and comparing // with the old value, if they are equal then the result is an integer too if( !c && old.IsInteger() && !IsInteger() ) { Big temp(*this); c += temp.Round(); Big temp2(temp); c += temp.Mul(temp2); if( temp == old ) *this = temp2; } return CheckCarry(c); } private: #ifdef TTMATH_CONSTANTSGENERATOR public: #endif /*! Exponent this = exp(x) = e^x where x is in (-1,1) we're using the formula exp(x) = 1 + (x)/(1!) + (x^2)/(2!) + (x^3)/(3!) + ... */ void ExpSurrounding0(const Big & x, uint * steps = 0) { TTMATH_REFERENCE_ASSERT( x ) Big denominator, denominator_i; Big one, old_value, next_part; Big numerator = x; SetOne(); one.SetOne(); denominator.SetOne(); denominator_i.SetOne(); uint i; old_value = *this; // we begin from 1 in order to not test at the beginning #ifdef TTMATH_CONSTANTSGENERATOR for(i=1 ; true ; ++i) #else for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) #endif { bool testing = ((i & 3) == 0); // it means '(i % 4) == 0' next_part = numerator; if( next_part.Div( denominator ) ) // if there is a carry here we only break the loop // however the result we return as good // it means there are too many parts of the formula break; // there shouldn't be a carry here Add( next_part ); if( testing ) { if( old_value == *this ) // we've added next few parts of the formula but the result // is still the same then we break the loop break; else old_value = *this; } // we set the denominator and the numerator for a next part of the formula if( denominator_i.Add(one) ) // if there is a carry here the result we return as good break; if( denominator.Mul(denominator_i) ) break; if( numerator.Mul(x) ) break; } if( steps ) *steps = i; } public: /*! Exponent this = exp(x) = e^x we're using the fact that our value is stored in form of: x = mantissa * 2^exponent then e^x = e^(mantissa* 2^exponent) or e^x = (e^mantissa)^(2^exponent) 'Exp' returns a carry if we can't count the result ('x' is too big) */ uint Exp(const Big & x) { uint c = 0; if( x.IsNan() ) return CheckCarry(1); if( x.IsZero() ) { SetOne(); return 0; } // m will be the value of the mantissa in range (-1,1) Big m(x); m.exponent = -sint(man*TTMATH_BITS_PER_UINT); // 'e_' will be the value of '2^exponent' // e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and // e_.exponent.Add(1) mean: // e_.mantissa.table[0] = 1; // e_.Standardizing(); // e_.exponent.Add(man*TTMATH_BITS_PER_UINT) // (we must add 'man*TTMATH_BITS_PER_UINT' because we've taken it from the mantissa) Big e_(x); e_.mantissa.SetZero(); e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; c += e_.exponent.Add(1); e_.Abs(); /* now we've got: m - the value of the mantissa in range (-1,1) e_ - 2^exponent e_ can be as: ...2^-2, 2^-1, 2^0, 2^1, 2^2 ... ...1/4 , 1/2 , 1 , 2 , 4 ... above one e_ is integer if e_ is greater than 1 we calculate the exponent as: e^(m * e_) = ExpSurrounding0(m) ^ e_ and if e_ is smaller or equal one we calculate the exponent in this way: e^(m * e_) = ExpSurrounding0(m* e_) because if e_ is smaller or equal 1 then the product of m*e_ is smaller or equal m */ if( e_ <= 1 ) { m.Mul(e_); ExpSurrounding0(m); } else { ExpSurrounding0(m); c += PowUInt(e_); } return CheckCarry(c); } private: #ifdef TTMATH_CONSTANTSGENERATOR public: #endif /*! Natural logarithm this = ln(x) where x in range <1,2) we're using the formula: ln x = 2 * [ (x-1)/(x+1) + (1/3)((x-1)/(x+1))^3 + (1/5)((x-1)/(x+1))^5 + ... ] */ void LnSurrounding1(const Big & x, uint * steps = 0) { Big old_value, next_part, denominator, one, two, x1(x), x2(x); one.SetOne(); if( x == one ) { // LnSurrounding1(1) is 0 SetZero(); return; } two = 2; x1.Sub(one); x2.Add(one); x1.Div(x2); x2 = x1; x2.Mul(x1); denominator.SetOne(); SetZero(); old_value = *this; uint i; #ifdef TTMATH_CONSTANTSGENERATOR for(i=1 ; true ; ++i) #else // we begin from 1 in order to not test at the beginning for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) #endif { bool testing = ((i & 3) == 0); // it means '(i % 4) == 0' next_part = x1; if( next_part.Div(denominator) ) // if there is a carry here we only break the loop // however the result we return as good // it means there are too many parts of the formula break; // there shouldn't be a carry here Add(next_part); if( testing ) { if( old_value == *this ) // we've added next (step_test) parts of the formula but the result // is still the same then we break the loop break; else old_value = *this; } if( x1.Mul(x2) ) // if there is a carry here the result we return as good break; if( denominator.Add(two) ) break; } // this = this * 2 // ( there can't be a carry here because we calculate the logarithm between <1,2) ) exponent.AddOne(); if( steps ) *steps = i; } public: /*! Natural logarithm this = ln(x) (a logarithm with the base equal 'e') we're using the fact that our value is stored in form of: x = mantissa * 2^exponent then ln(x) = ln (mantissa * 2^exponent) = ln (mantissa) + (exponent * ln (2)) the mantissa we'll show as a value from range <1,2) because the logarithm is decreasing too fast when 'x' is going to 0 return values: 0 - ok 1 - overflow (carry) 2 - incorrect argument (x<=0) */ uint Ln(const Big & x) { if( x.IsNan() ) return CheckCarry(1); if( x.IsSign() || x.IsZero() ) { SetNan(); return 2; } Big exponent_temp; exponent_temp.FromInt( x.exponent ); // m will be the value of the mantissa in range <1,2) Big m(x); m.exponent = -sint(man*TTMATH_BITS_PER_UINT - 1); // we must add 'man*TTMATH_BITS_PER_UINT-1' because we've taken it from the mantissa uint c = exponent_temp.Add(man*TTMATH_BITS_PER_UINT-1); LnSurrounding1(m); Big ln2; ln2.SetLn2(); c += exponent_temp.Mul(ln2); c += Add(exponent_temp); return CheckCarry(c); } /*! Logarithm from 'x' with a 'base' we're using the formula: Log(x) with 'base' = ln(x) / ln(base) return values: 0 - ok 1 - overflow 2 - incorrect argument (x<=0) 3 - incorrect base (a<=0 lub a=1) */ uint Log(const Big & x, const Big & base) { if( x.IsNan() || base.IsNan() ) return CheckCarry(1); if( x.IsSign() || x.IsZero() ) { SetNan(); return 2; } Big denominator;; denominator.SetOne(); if( base.IsSign() || base.IsZero() || base==denominator ) { SetNan(); return 3; } if( x == denominator ) // (this is: if x == 1) { // log(1) is 0 SetZero(); return 0; } // another error values we've tested at the beginning // there can only be a carry uint c = Ln(x); c += denominator.Ln(base); c += Div(denominator); return CheckCarry(c); } /*! * * converting methods * */ /*! converting from another type of a Big object */ template uint FromBig(const Big & another) { info = another.info; if( IsNan() ) return 1; if( exponent.FromInt(another.exponent) ) { SetNan(); return 1; } uint man_len_min = (man < another_man)? man : another_man; uint i; uint c = 0; for( i = 0 ; i another_man )' and 'if( man < another_man )' and there'll be no such situation here #ifdef _MSC_VER #pragma warning( disable: 4307 ) #endif if( man > another_man ) { uint man_diff = (man - another_man) * TTMATH_BITS_PER_UINT; c += exponent.SubInt(man_diff, 0); } else if( man < another_man ) { uint man_diff = (another_man - man) * TTMATH_BITS_PER_UINT; c += exponent.AddInt(man_diff, 0); } #ifdef _MSC_VER #pragma warning( default: 4307 ) #endif // mantissa doesn't have to be standardized (either the highest bit is set or all bits are equal zero) CorrectZero(); return CheckCarry(c); } private: /*! an auxiliary method for converting 'this' into 'result' if the value is too big this method returns a carry (1) */ uint ToUIntOrInt(uint & result) const { result = 0; if( IsZero() ) return 0; sint maxbit = -sint(man*TTMATH_BITS_PER_UINT); if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) ) // if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed // into the 'sint' type (it's too big) return 1; if( exponent <= maxbit ) // our value is from the range of (-1,1) and we return zero return 0; // exponent is from a range of (maxbit, maxbit + sint(TTMATH_BITS_PER_UINT) > // and [maxbit + sint(TTMATH_BITS_PER_UINT] <= 0 sint how_many_bits = exponent.ToInt(); // how_many_bits is negative, we'll make it positive how_many_bits = -how_many_bits; result = (mantissa.table[man-1] >> (how_many_bits % TTMATH_BITS_PER_UINT)); return 0; } public: /*! this method converts 'this' into uint */ uint ToUInt() const { uint result; ToUInt(result); return result; } /*! this method converts 'this' into 'result' if the value is too big this method returns a carry (1) */ uint ToUInt(uint & result) const { if( ToUIntOrInt(result) ) return 1; if( IsSign() ) return 1; return 0; } /*! this method converts 'this' into sint */ sint ToInt() const { sint result; ToInt(result); return result; } /*! this method converts 'this' into 'result' if the value is too big this method returns a carry (1) */ uint ToInt(uint & result) const { return ToUInt(result); } /*! this method converts 'this' into 'result' if the value is too big this method returns a carry (1) */ uint ToInt(sint & result) const { uint result_uint; uint c = ToUIntOrInt(result_uint); result = sint(result_uint); if( c ) return 1; uint mask = 0; if( IsSign() ) { mask = TTMATH_UINT_MAX_VALUE; result = -result; } return ((result & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT)) ? 0 : 1; } private: /*! an auxiliary method for converting 'this' into 'result' if the value is too big this method returns a carry (1) */ template uint ToUIntOrInt(UInt & result) const { result.SetZero(); if( IsZero() ) return 0; sint maxbit = -sint(man*TTMATH_BITS_PER_UINT); if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) ) // if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed // into the 'UInt' type (it's too big) return 1; if( exponent <= maxbit ) // our value is from range (-1,1) and we return zero return 0; sint how_many_bits = exponent.ToInt(); if( how_many_bits < 0 ) { how_many_bits = -how_many_bits; uint index = how_many_bits / TTMATH_BITS_PER_UINT; UInt mantissa_temp(mantissa); mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 ); for(uint i=index, a=0 ; i maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )" // but gcc doesn't understand our types - exponent is Int<> for(uint i=0 ; i uint ToUInt(UInt & result) const { uint c = ToUIntOrInt(result); if( c ) return 1; if( IsSign() ) return 1; return 0; } /*! this method converts 'this' into 'result' if the value is too big this method returns a carry (1) */ template uint ToInt(UInt & result) const { return ToUInt(result); } /*! this method converts 'this' into 'result' if the value is too big this method returns a carry (1) */ template uint ToInt(Int & result) const { uint c = ToUIntOrInt(result); if( c ) return 1; uint mask = 0; if( IsSign() ) { result.ChangeSign(); mask = TTMATH_UINT_MAX_VALUE; } return ((result.table[int_size-1] & TTMATH_UINT_HIGHEST_BIT) == (mask & TTMATH_UINT_HIGHEST_BIT))? 0 : 1; } /*! a method for converting 'uint' to this class */ uint FromUInt(uint value) { if( value == 0 ) { SetZero(); return 0; } info = 0; for(uint i=0 ; i> 20; uint m1 = ((temp.u[1] & 0xFFFFFu) << 11) | (temp.u[0] >> 21); uint m2 = temp.u[0] << 11; if( e == 2047 ) { // If E=2047 and F is nonzero, then V=NaN ("Not a number") // If E=2047 and F is zero and S is 1, then V=-Infinity // If E=2047 and F is zero and S is 0, then V=Infinity // we do not support -Infinity and +Infinity // we assume that there is always NaN SetNan(); } else if( e > 0 ) { // If 0 m; m.table[1] = m1; m.table[0] = m2; uint moved = m.CompensationToLeft(); FromDouble_SetExpAndMan((temp.u[1] & 0x80000000u) != 0, e - 1022 - man*TTMATH_BITS_PER_UINT + 1 - moved, 0, m.table[1], m.table[2]); } else { // If E=0 and F is zero and S is 1, then V=-0 // If E=0 and F is zero and S is 0, then V=0 // we do not support -0 or 0, only is one 0 SetZero(); } } return 0; // never be a carry } private: void FromDouble_SetExpAndMan(bool is_sign, int e, uint mhighest, uint m1, uint m2) { exponent = e; if( man > 1 ) { mantissa.table[man-1] = m1 | mhighest; mantissa.table[sint(man-2)] = m2; // although man>1 we're using casting into sint // to get rid from a warning which generates Microsoft Visual: // warning C4307: '*' : integral constant overflow for(uint i=0 ; i> 52; uint m = (temp.u & 0xFFFFFFFFFFFFFul) << 11; if( e == 2047 ) { // If E=2047 and F is nonzero, then V=NaN ("Not a number") // If E=2047 and F is zero and S is 1, then V=-Infinity // If E=2047 and F is zero and S is 0, then V=Infinity // we do not support -Infinity and +Infinity // we assume that there is always NaN SetNan(); } else if( e > 0 ) { // If 0> 23) & 0xff) == 0xff ) { if( (temp.u & 0x7FFFFF) == 0 ) return true; // +/- infinity } return false; } public: /*! this method converts from this class into the 'float' if the value is too big: 'result' will be +/-infinity (depending on the sign) if the value is too small: 'result' will be 0 */ float ToFloat() const { float result; ToFloat(result); return result; } /*! this method converts from this class into the 'float' if the value is too big: 'result' will be +/-infinity (depending on the sign) and the method returns 1 if the value is too small: 'result' will be 0 and the method returns 1 */ uint ToFloat(float & result) const { double result_double; uint c = ToDouble(result_double); result = float(result_double); if( result == -0.0f ) result = 0.0f; if( c ) return 1; // although the result_double can have a correct value // but after converting to float there can be infinity if( IsInf(result) ) return 1; if( result == 0.0f && result_double != 0.0 ) // result_double was too small for float return 1; return 0; } /*! this method converts from this class into the 'double' if the value is too big: 'result' will be +/-infinity (depending on the sign) and the method returns 1 if the value is too small: 'result' will be 0 and the method returns 1 */ uint ToDouble(double & result) const { if( IsZero() ) { result = 0.0; return 0; } if( IsNan() ) { result = ToDouble_SetDouble( false, 2047, 0, false, true); return 0; } sint e_correction = sint(man*TTMATH_BITS_PER_UINT) - 1; if( exponent >= 1024 - e_correction ) { // +/- infinity result = ToDouble_SetDouble( IsSign(), 2047, 0, true); return 1; } else if( exponent <= -1023 - 52 - e_correction ) { // too small value - we assume that there'll be a zero result = 0; // and return a carry return 1; } sint e = exponent.ToInt() + e_correction; if( e <= -1023 ) { // -1023-52 < e <= -1023 (unnormalized value) result = ToDouble_SetDouble( IsSign(), 0, -(e + 1023)); } else { // -1023 < e < 1024 result = ToDouble_SetDouble( IsSign(), e + 1023, -1); } return 0; } private: #ifdef TTMATH_PLATFORM32 // 32bit platforms double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const { union { double d; uint u[2]; // two 32bit words } temp; temp.u[0] = temp.u[1] = 0; if( is_sign ) temp.u[1] |= 0x80000000u; temp.u[1] |= (e << 20) & 0x7FF00000u; if( nan ) { temp.u[0] |= 1; return temp.d; } if( infinity ) return temp.d; UInt<2> m; m.table[1] = mantissa.table[man-1]; m.table[0] = ( man > 1 ) ? mantissa.table[sint(man-2)] : 0; // although man>1 we're using casting into sint // to get rid from a warning which generates Microsoft Visual: // warning C4307: '*' : integral constant overflow m.Rcr( 12 + move ); m.table[1] &= 0xFFFFFu; // cutting the 20 bit (when 'move' was -1) temp.u[1] |= m.table[1]; temp.u[0] |= m.table[0]; return temp.d; } #else // 64bit platforms double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const { union { double d; uint u; // 64bit word } temp; temp.u = 0; if( is_sign ) temp.u |= 0x8000000000000000ul; temp.u |= (e << 52) & 0x7FF0000000000000ul; if( nan ) { temp.u |= 1; return temp.d; } if( infinity ) return temp.d; uint m = mantissa.table[man-1]; m >>= ( 12 + move ); m &= 0xFFFFFFFFFFFFFul; // cutting the 20 bit (when 'move' was -1) temp.u |= m; return temp.d; } #endif public: /*! an operator= for converting 'sint' to this class */ Big & operator=(sint value) { FromInt(value); return *this; } /*! an operator= for converting 'uint' to this class */ Big & operator=(uint value) { FromUInt(value); return *this; } /*! an operator= for converting 'float' to this class */ Big & operator=(float value) { FromFloat(value); return *this; } /*! an operator= for converting 'double' to this class */ Big & operator=(double value) { FromDouble(value); return *this; } /*! a constructor for converting 'sint' to this class */ Big(sint value) { FromInt(value); } /*! a constructor for converting 'uint' to this class */ Big(uint value) { FromUInt(value); } /*! a constructor for converting 'double' to this class */ Big(double value) { FromDouble(value); } /*! a constructor for converting 'float' to this class */ Big(float value) { FromFloat(value); } #ifdef TTMATH_PLATFORM32 /*! this method converts 'this' into 'result' (64 bit unsigned integer) if the value is too big this method returns a carry (1) */ uint ToUInt(ulint & result) const { UInt<2> temp; // 64 bits container uint c = ToUInt(temp); temp.ToUInt(result); return c; } /*! this method converts 'this' into 'result' (64 bit unsigned integer) if the value is too big this method returns a carry (1) */ uint ToInt(ulint & result) const { return ToUInt(result); } /*! this method converts 'this' into 'result' (64 bit unsigned integer) if the value is too big this method returns a carry (1) */ uint ToInt(slint & result) const { Int<2> temp; // 64 bits container uint c = ToInt(temp); temp.ToInt(result); return c; } /*! a method for converting 'ulint' (64bit unsigned integer) to this class */ uint FromUInt(ulint value) { if( value == 0 ) { SetZero(); return 0; } info = 0; if( man == 1 ) { sint bit = mantissa.FindLeadingBitInWord(uint(value >> TTMATH_BITS_PER_UINT)); if( bit != -1 ) { // the highest word from value is different from zero bit += 1; value >>= bit; exponent = bit; } else { exponent.SetZero(); } mantissa.table[0] = uint(value); } else { #ifdef _MSC_VER //warning C4307: '*' : integral constant overflow #pragma warning( disable: 4307 ) #endif // man >= 2 mantissa.table[man-1] = uint(value >> TTMATH_BITS_PER_UINT); mantissa.table[man-2] = uint(value); #ifdef _MSC_VER //warning C4307: '*' : integral constant overflow #pragma warning( default: 4307 ) #endif exponent = -sint(man-2) * sint(TTMATH_BITS_PER_UINT); for(uint i=0 ; i & operator=(ulint value) { FromUInt(value); return *this; } /*! a constructor for converting 'slint' (64bit signed integer) to this class */ Big(slint value) { FromInt(value); } /*! an operator for converting 'slint' (64bit signed integer) to this class */ Big & operator=(slint value) { FromInt(value); return *this; } #endif #ifdef TTMATH_PLATFORM64 /*! this method converts 'this' into 'result' (32 bit unsigned integer) ***this method is created only on a 64bit platform*** if the value is too big this method returns a carry (1) */ uint ToUInt(unsigned int & result) const { uint result_uint; uint c = ToUInt(result_uint); result = (unsigned int)result_uint; if( c || result_uint != uint(result) ) return 1; return 0; } /*! this method converts 'this' into 'result' (32 bit unsigned integer) ***this method is created only on a 64bit platform*** if the value is too big this method returns a carry (1) */ uint ToInt(unsigned int & result) const { return ToUInt(result); } /*! this method converts 'this' into 'result' (32 bit signed integer) ***this method is created only on a 64bit platform*** if the value is too big this method returns a carry (1) */ uint ToInt(signed int & result) const { sint result_sint; uint c = ToInt(result_sint); result = (signed int)result_sint; if( c || result_sint != sint(result) ) return 1; return 0; } /* this method converts 32 bit unsigned int to this class ***this method is created only on a 64bit platform*** */ uint FromUInt(unsigned int value) { return FromUInt(uint(value)); } /* this method converts 32 bit unsigned int to this class ***this method is created only on a 64bit platform*** */ uint FromInt(unsigned int value) { return FromUInt(uint(value)); } /* this method converts 32 bit signed int to this class ***this method is created only on a 64bit platform*** */ uint FromInt(signed int value) { return FromInt(sint(value)); } /*! an operator= for converting 32 bit unsigned int to this class ***this operator is created only on a 64bit platform*** */ Big & operator=(unsigned int value) { FromUInt(value); return *this; } /*! a constructor for converting 32 bit unsigned int to this class ***this constructor is created only on a 64bit platform*** */ Big(unsigned int value) { FromUInt(value); } /*! an operator for converting 32 bit signed int to this class ***this operator is created only on a 64bit platform*** */ Big & operator=(signed int value) { FromInt(value); return *this; } /*! a constructor for converting 32 bit signed int to this class ***this constructor is created only on a 64bit platform*** */ Big(signed int value) { FromInt(value); } #endif private: /*! an auxiliary method for converting from UInt and Int we assume that there'll never be a carry here (we have an exponent and the value in Big can be bigger than that one from the UInt) */ template uint FromUIntOrInt(const UInt & value, sint compensation) { uint minimum_size = (int_size < man)? int_size : man; exponent = (sint(int_size)-sint(man)) * sint(TTMATH_BITS_PER_UINT) - compensation; // copying the highest words uint i; for(i=1 ; i<=minimum_size ; ++i) mantissa.table[man-i] = value.table[int_size-i]; // setting the rest of mantissa.table into zero (if some has left) for( ; i<=man ; ++i) mantissa.table[man-i] = 0; // the highest bit is either one or zero (when the whole mantissa is zero) // we can only call CorrectZero() CorrectZero(); return 0; } public: /*! a method for converting from 'UInt' to this class */ template uint FromUInt(UInt value) { info = 0; sint compensation = (sint)value.CompensationToLeft(); return FromUIntOrInt(value, compensation); } /*! a method for converting from 'UInt' to this class */ template uint FromInt(const UInt & value) { return FromUInt(value); } /*! a method for converting from 'Int' to this class */ template uint FromInt(Int value) { info = 0; bool is_sign = false; if( value.IsSign() ) { value.ChangeSign(); is_sign = true; } sint compensation = (sint)value.CompensationToLeft(); FromUIntOrInt(value, compensation); if( is_sign ) SetSign(); return 0; } /*! an operator= for converting from 'Int' to this class */ template Big & operator=(const Int & value) { FromInt(value); return *this; } /*! a constructor for converting from 'Int' to this class */ template Big(const Int & value) { FromInt(value); } /*! an operator= for converting from 'UInt' to this class */ template Big & operator=(const UInt & value) { FromUInt(value); return *this; } /*! a constructor for converting from 'UInt' to this class */ template Big(const UInt & value) { FromUInt(value); } /*! an operator= for converting from 'Big' to this class */ template Big & operator=(const Big & value) { FromBig(value); return *this; } /*! a constructor for converting from 'Big' to this class */ template Big(const Big & value) { FromBig(value); } /*! a default constructor by default we don't set any of the members to zero only NaN flag is set if you want the mantissa and exponent to be set to zero define TTMATH_BIG_DEFAULT_CLEAR macro (useful for debug purposes) */ Big() { #ifdef TTMATH_BIG_DEFAULT_CLEAR SetZeroNan(); #else info = TTMATH_BIG_NAN; // we're directly setting 'info' (instead of calling SetNan()) // in order to get rid of a warning saying that 'info' is uninitialized #endif } /*! a destructor */ ~Big() { } /*! the default assignment operator */ Big & operator=(const Big & value) { info = value.info; exponent = value.exponent; mantissa = value.mantissa; return *this; } /*! a constructor for copying from another object of this class */ Big(const Big & value) { operator=(value); } /*! a method for converting into a string struct Conv is defined in ttmathtypes.h, look there for more information about parameters output: return value: 0 - ok and 'result' will be an object of type std::string (or std::wstring) which holds the value 1 - if there is a carry (it shoudn't be in a normal situation - if it is that means there is somewhere an error in the library) */ uint ToString( std::string & result, uint base = 10, bool scient = false, sint scient_from = 15, sint round = -1, bool trim_zeroes = true, char comma = '.' ) const { Conv conv; conv.base = base; conv.scient = scient; conv.scient_from = scient_from; conv.round = round; conv.trim_zeroes = trim_zeroes; conv.comma = static_cast(comma); return ToStringBase(result, conv); } /*! a method for converting into a string struct Conv is defined in ttmathtypes.h, look there for more information about parameters */ uint ToString(std::string & result, const Conv & conv) const { return ToStringBase(result, conv); } /*! a method for converting into a string struct Conv is defined in ttmathtypes.h, look there for more information about parameters */ std::string ToString(const Conv & conv) const { std::string result; ToStringBase(result, conv); return result; } /*! a method for converting into a string struct Conv is defined in ttmathtypes.h, look there for more information about parameters */ std::string ToString(uint base = 10) const { Conv conv; conv.base = base; return ToString(conv); } #ifndef TTMATH_DONT_USE_WCHAR /*! a method for converting into a string struct Conv is defined in ttmathtypes.h, look there for more information about parameters */ uint ToString( std::wstring & result, uint base = 10, bool scient = false, sint scient_from = 15, sint round = -1, bool trim_zeroes = true, wchar_t comma = '.' ) const { Conv conv; conv.base = base; conv.scient = scient; conv.scient_from = scient_from; conv.round = round; conv.trim_zeroes = trim_zeroes; conv.comma = static_cast(comma); return ToStringBase(result, conv); } /*! a method for converting into a string struct Conv is defined in ttmathtypes.h, look there for more information about parameters */ uint ToString(std::wstring & result, const Conv & conv) const { return ToStringBase(result, conv); } /*! a method for converting into a string struct Conv is defined in ttmathtypes.h, look there for more information about parameters */ std::wstring ToWString(const Conv & conv) const { std::wstring result; ToStringBase(result, conv); return result; } /*! a method for converting into a string struct Conv is defined in ttmathtypes.h, look there for more information about parameters */ std::wstring ToWString(uint base = 10) const { Conv conv; conv.base = base; return ToWString(conv); } #endif private: /*! an auxiliary method for converting into the string */ template uint ToStringBase(string_type & result, const Conv & conv) const { static char error_overflow_msg[] = "overflow"; static char error_nan_msg[] = "NaN"; result.erase(); if( IsNan() ) { Misc::AssignString(result, error_nan_msg); return 0; } if( conv.base<2 || conv.base>16 ) { Misc::AssignString(result, error_overflow_msg); return 1; } if( IsZero() ) { result = '0'; return 0; } /* since 'base' is greater or equal 2 that 'new_exp' of type 'Int' should hold the new value of exponent but we're using 'Int' because if the value for example would be 'max()' then we couldn't show it max() -> 11111111 * 2 ^ 11111111111 (bin)(the mantissa and exponent have all bits set) if we were using 'Int' we couldn't show it in this format: 1,1111111 * 2 ^ 11111111111 (bin) because we have to add something to the mantissa and because mantissa is full we can't do it and it'll be a carry (look at ToString_SetCommaAndExponent(...)) when the base would be greater than two (for example 10) we could use 'Int' here */ Int new_exp; if( ToString_CreateNewMantissaAndExponent(result, conv, new_exp) ) { Misc::AssignString(result, error_overflow_msg); return 1; } if( ToString_SetCommaAndExponent(result, conv, new_exp) ) { Misc::AssignString(result, error_overflow_msg); return 1; } if( IsSign() ) result.insert(result.begin(), '-'); // converted successfully return 0; } /*! in the method 'ToString_CreateNewMantissaAndExponent()' we're using type 'Big' and we should have the ability to use some necessary methods from that class (methods which are private here) */ friend class Big; /*! an auxiliary method for converting into the string input: base - the base in range <2,16> output: return values: 0 - ok 1 - if there was a carry new_man - the new mantissa for 'base' new_exp - the new exponent for 'base' mathematic part: the value is stored as: value = mantissa * 2^exponent we want to show 'value' as: value = new_man * base^new_exp then 'new_man' we'll print using the standard method from UInt<> type for printing and 'new_exp' is the offset of the comma operator in a system of a base 'base' value = mantissa * 2^exponent value = mantissa * 2^exponent * (base^new_exp / base^new_exp) value = mantissa * (2^exponent / base^new_exp) * base^new_exp look at the part (2^exponent / base^new_exp), there'll be good if we take a 'new_exp' equal that value when the (2^exponent / base^new_exp) will be equal one on account of the 'base' is not as power of 2 (can be from 2 to 16), this formula will not be true for integer 'new_exp' then in our case we take 'base^new_exp' _greater_ than '2^exponent' if 'base^new_exp' were smaller than '2^exponent' the new mantissa could be greater than the max value of the container UInt value = mantissa * (2^exponent / base^new_exp) * base^new_exp let M = mantissa * (2^exponent / base^new_exp) then value = M * base^new_exp in our calculation we treat M as floating value showing it as: M = mm * 2^ee where ee will be <= 0 next we'll move all bits of mm into the right when ee is equal zero abs(ee) must not be too big that only few bits from mm we can leave then we'll have: M = mmm * 2^0 'mmm' is the new_man which we're looking for new_exp we calculate in this way: 2^exponent <= base^new_exp new_exp >= log base (2^exponent) <- logarithm with the base 'base' from (2^exponent) but we need new_exp as integer then we test: if new_exp is greater than zero and with fraction we add one to new_exp new_exp = new_exp + 1 (if new_exp>0 and with fraction) and at the end we take the integer part: new_exp = int(new_exp) */ template uint ToString_CreateNewMantissaAndExponent( string_type & new_man, const Conv & conv, Int & new_exp) const { uint c = 0; if( conv.base<2 || conv.base>16 ) return 1; // special method for base equal 2 if( conv.base == 2 ) return ToString_CreateNewMantissaAndExponent_Base2(new_man, new_exp); // special method for base equal 4 if( conv.base == 4 ) return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 2); // special method for base equal 8 if( conv.base == 8 ) return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 3); // special method for base equal 16 if( conv.base == 16 ) return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 4); // this = mantissa * 2^exponent // temp = +1 * 2^exponent // we're using a bigger type than 'big' (look below) Big temp; temp.info = 0; temp.exponent = exponent; temp.mantissa.SetOne(); c += temp.Standardizing(); // new_exp_ = log base (2^exponent) // if new_exp_ is positive and with fraction then we add one Big new_exp_; c += new_exp_.ToString_Log(temp, conv.base); // this logarithm isn't very complicated // rounding up to the nearest integer if( !new_exp_.IsInteger() ) { if( !new_exp_.IsSign() ) c += new_exp_.AddOne(); // new_exp_ > 0 and with fraction new_exp_.SkipFraction(); } if( ToString_CreateNewMantissaTryExponent(new_man, conv, new_exp_, new_exp) ) { // in very rare cases there can be an overflow from ToString_CreateNewMantissaTryExponent // it means that new_exp_ was too small (the problem comes from floating point numbers precision) // so we increse new_exp_ and try again new_exp_.AddOne(); c += ToString_CreateNewMantissaTryExponent(new_man, conv, new_exp_, new_exp); } return (c==0)? 0 : 1; } /*! an auxiliary method for converting into the string trying to calculate new_man for given exponent (new_exp_) if there is a carry it can mean that new_exp_ is too small */ template uint ToString_CreateNewMantissaTryExponent( string_type & new_man, const Conv & conv, const Big & new_exp_, Int & new_exp) const { uint c = 0; // because 'base^new_exp' is >= '2^exponent' then // because base is >= 2 then we've got: // 'new_exp_' must be smaller or equal 'new_exp' // and we can pass it into the Int type // (in fact we're using a greater type then it'll be ok) c += new_exp_.ToInt(new_exp); // base_ = base Big base_(conv.base); // base_ = base_ ^ new_exp_ c += base_.Pow( new_exp_ ); // use new_exp_ so Pow(Big<> &) version will be used // if we hadn't used a bigger type than 'Big' then the result // of this formula 'Pow(...)' would have been with an overflow // temp = mantissa * 2^exponent / base_^new_exp_ Big temp; temp.info = 0; temp.mantissa = mantissa; temp.exponent = exponent; c += temp.Div(base_); // moving all bits of the mantissa into the right // (how many times to move depend on the exponent) c += temp.ToString_MoveMantissaIntoRight(); // because we took 'new_exp' as small as it was // possible ([log base (2^exponent)] + 1) that after the division // (temp.Div( base_ )) the value of exponent should be equal zero or // minimum smaller than zero then we've got the mantissa which has // maximum valid bits temp.mantissa.ToString(new_man, conv.base); if( IsInteger() ) { // making sure the new mantissa will be without fraction (integer) ToString_CheckMantissaInteger(new_man, new_exp); } else if( conv.base_round ) { c += ToString_BaseRound(new_man, conv, new_exp); } return (c==0)? 0 : 1; } /*! this method calculates the logarithm it is used by ToString_CreateNewMantissaAndExponent() method it's not too complicated because x=+1*2^exponent (mantissa is one) then during the calculation the Ln(x) will not be making the long formula from LnSurrounding1() and only we have to calculate 'Ln(base)' but it'll be calculated only once, the next time we will get it from the 'history' x is greater than 0 base is in <2,16> range */ uint ToString_Log(const Big & x, uint base) { TTMATH_REFERENCE_ASSERT( x ) TTMATH_ASSERT( base>=2 && base<=16 ) Big temp; temp.SetOne(); if( x == temp ) { // log(1) is 0 SetZero(); return 0; } // there can be only a carry // because the 'x' is in '1+2*exponent' form then // the long formula from LnSurrounding1() will not be calculated // (LnSurrounding1() will return one immediately) uint c = Ln(x); if( base==10 && man<=TTMATH_BUILTIN_VARIABLES_SIZE ) { // for the base equal 10 we're using SetLn10() instead of calculating it // (only if we have the constant sufficient big) temp.SetLn10(); } else { c += ToString_LogBase(base, temp); } c += Div( temp ); return (c==0)? 0 : 1; } #ifndef TTMATH_MULTITHREADS /*! this method calculates the logarithm of 'base' it's used in single thread environment */ uint ToString_LogBase(uint base, Big & result) { TTMATH_ASSERT( base>=2 && base<=16 ) // this guardians are initialized before the program runs (static POD types) static int guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static Big log_history[15]; uint index = base - 2; uint c = 0; if( guardians[index] == 0 ) { Big base_(base); c += log_history[index].Ln(base_); guardians[index] = 1; } result = log_history[index]; return (c==0)? 0 : 1; } #else /*! this method calculates the logarithm of 'base' it's used in multi-thread environment */ uint ToString_LogBase(uint base, Big & result) { TTMATH_ASSERT( base>=2 && base<=16 ) // this guardians are initialized before the program runs (static POD types) volatile static sig_atomic_t guardians[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static Big * plog_history; uint index = base - 2; uint c = 0; // double-checked locking if( guardians[index] == 0 ) { ThreadLock thread_lock; // locking if( thread_lock.Lock() ) { static Big log_history[15]; if( guardians[index] == 0 ) { plog_history = log_history; Big base_(base); c += log_history[index].Ln(base_); guardians[index] = 1; } } else { // there was a problem with locking, we store the result directly in 'result' object Big base_(base); c += result.Ln(base_); return (c==0)? 0 : 1; } // automatically unlocking } result = plog_history[index]; return (c==0)? 0 : 1; } #endif /*! an auxiliary method for converting into the string (private) this method moving all bits from mantissa into the right side the exponent tell us how many times moving (the exponent is <=0) */ uint ToString_MoveMantissaIntoRight() { if( exponent.IsZero() ) return 0; // exponent can't be greater than zero // because we would cat the highest bits of the mantissa if( !exponent.IsSign() ) return 1; if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) // if 'exponent' is <= than '-sint(man*TTMATH_BITS_PER_UINT)' // it means that we must cut the whole mantissa // (there'll not be any of the valid bits) return 1; // e will be from (-man*TTMATH_BITS_PER_UINT, 0> sint e = -( exponent.ToInt() ); mantissa.Rcr(e,0); return 0; } /*! a special method similar to the 'ToString_CreateNewMantissaAndExponent' when the 'base' is equal 2 we use it because if base is equal 2 we don't have to make those complicated calculations and the output is directly from the source (there will not be any small distortions) */ template uint ToString_CreateNewMantissaAndExponent_Base2( string_type & new_man, Int & new_exp ) const { for( sint i=man-1 ; i>=0 ; --i ) { uint value = mantissa.table[i]; for( uint bit=0 ; bit uint ToString_CreateNewMantissaAndExponent_BasePow2( string_type & new_man, Int & new_exp, uint bits) const { sint move; // how many times move the mantissa UInt man_temp(mantissa); // man+1 for moving new_exp = exponent; new_exp.DivInt((sint)bits, move); if( move != 0 ) { // we're moving the man_temp to left-hand side if( move < 0 ) { move = sint(bits) + move; new_exp.SubOne(); // when move is < than 0 then new_exp is < 0 too } man_temp.Rcl(move); } if( bits == 3 ) { // base 8 // now 'move' is greater than or equal 0 uint len = man*TTMATH_BITS_PER_UINT + move; return ToString_CreateNewMantissaAndExponent_Base8(new_man, man_temp, len, bits); } else { // base 4 or 16 return ToString_CreateNewMantissaAndExponent_Base4or16(new_man, man_temp, bits); } } /*! a special method used to calculate the new mantissa when the 'base' is equal 8 bits is always 3 we can use this algorithm when the base is 4 or 16 too but we have a faster method ToString_CreateNewMantissaAndExponent_Base4or16() */ template uint ToString_CreateNewMantissaAndExponent_Base8( string_type & new_man, UInt & man_temp, uint len, uint bits) const { uint shift = TTMATH_BITS_PER_UINT - bits; uint mask = TTMATH_UINT_MAX_VALUE >> shift; uint i; for( i=0 ; i(Misc::DigitToChar(digit))); man_temp.Rcr(bits); } TTMATH_ASSERT( man_temp.IsZero() ) return 0; } /*! a special method used to calculate the new mantissa when the 'base' is equal 4 or 16 when the base is equal 4 or 16 the bits is 2 or 4 and because TTMATH_BITS_PER_UINT (32 or 64) is divisible by 2 (or 4) then we can get digits from the end of our mantissa */ template uint ToString_CreateNewMantissaAndExponent_Base4or16( string_type & new_man, UInt & man_temp, uint bits) const { TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 2 == 0 ) TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 4 == 0 ) uint shift = TTMATH_BITS_PER_UINT - bits; uint mask = TTMATH_UINT_MAX_VALUE << shift; uint digit; // table[man] - last word - is different from zero if we moved man_temp digit = man_temp.table[man]; if( digit != 0 ) new_man += static_cast(Misc::DigitToChar(digit)); for( int i=man-1 ; i>=0 ; --i ) { uint shift_local = shift; uint mask_local = mask; while( mask_local != 0 ) { digit = man_temp.table[i] & mask_local; if( shift_local != 0 ) digit = digit >> shift_local; new_man += static_cast(Misc::DigitToChar(digit)); mask_local = mask_local >> bits; shift_local = shift_local - bits; } } return 0; } /*! an auxiliary method for converting into the string */ template bool ToString_RoundMantissaWouldBeInteger(string_type & new_man, const Conv & conv, Int & new_exp) const { // if new_exp is greater or equal to zero then we have an integer value, // if new_exp is equal -1 then we have only one digit after the comma // and after rounding it would be an integer value if( !new_exp.IsSign() || new_exp == -1 ) return true; if( new_man.size() >= TTMATH_UINT_HIGHEST_BIT || new_man.size() < 2 ) return true; // oops, the mantissa is too large for calculating (or too small) - we are not doing the base rounding uint i = 0; char_type digit; if( new_exp >= -sint(new_man.size()) ) { uint new_exp_abs = -new_exp.ToInt(); i = new_man.size() - new_exp_abs; // start from the first digit after the comma operator } if( Misc::CharToDigit(new_man[new_man.size()-1]) >= conv.base/2 ) { if( new_exp < -sint(new_man.size()) ) { // there are some zeroes after the comma operator // (between the comma and the first digit from the mantissa) // and the result value will never be an integer return false; } digit = static_cast( Misc::DigitToChar(conv.base-1) ); } else { digit = '0'; } for( ; i < new_man.size()-1 ; ++i) if( new_man[i] != digit ) return false; // it will not be an integer return true; // it will be integer after rounding } /*! an auxiliary method for converting into the string (when this is integer) after floating point calculating the new mantissa can consist of some fraction so if our value is integer we should check the new mantissa (after the decimal point there should be only zeroes) often this is a last digit different from zero ToString_BaseRound would not get rid of it because the method make a test against an integer value (ToString_RoundMantissaWouldBeInteger) and returns immediately */ template void ToString_CheckMantissaInteger(string_type & new_man, const Int & new_exp) const { if( !new_exp.IsSign() ) return; // return if new_exp >= 0 uint i = 0; uint man_size = new_man.size(); if( man_size >= TTMATH_UINT_HIGHEST_BIT ) return; // ops, the mantissa is too long sint sman_size = -sint(man_size); if( new_exp >= sman_size ) { sint e = new_exp.ToInt(); e = -e; // now e means how many last digits from the mantissa should be equal zero i = man_size - uint(e); } for( ; i uint ToString_BaseRound(string_type & new_man, const Conv & conv, Int & new_exp) const { // we must have minimum two characters if( new_man.size() < 2 ) return 0; // assert that there will not be an integer after rounding if( ToString_RoundMantissaWouldBeInteger(new_man, conv, new_exp) ) return 0; typename string_type::size_type i = new_man.length() - 1; // we're erasing the last character uint digit = Misc::CharToDigit( new_man[i] ); new_man.erase(i, 1); uint c = new_exp.AddOne(); // if the last character is greater or equal 'base/2' // we are adding one into the new mantissa if( digit >= conv.base / 2 ) ToString_RoundMantissa_AddOneIntoMantissa(new_man, conv); return c; } /*! an auxiliary method for converting into the string this method addes one into the new mantissa */ template void ToString_RoundMantissa_AddOneIntoMantissa(string_type & new_man, const Conv & conv) const { if( new_man.empty() ) return; sint i = sint( new_man.length() ) - 1; bool was_carry = true; for( ; i>=0 && was_carry ; --i ) { // we can have the comma as well because // we're using this method later in ToString_CorrectDigitsAfterComma_Round() // (we're only ignoring it) if( new_man[i] == static_cast(conv.comma) ) continue; // we're adding one uint digit = Misc::CharToDigit( new_man[i] ) + 1; if( digit == conv.base ) digit = 0; else was_carry = false; new_man[i] = static_cast( Misc::DigitToChar(digit) ); } if( i<0 && was_carry ) new_man.insert( new_man.begin() , '1' ); } /*! an auxiliary method for converting into the string this method sets the comma operator and/or puts the exponent into the string */ template uint ToString_SetCommaAndExponent(string_type & new_man, const Conv & conv, Int & new_exp) const { uint carry = 0; if( new_man.empty() ) return carry; Int scientific_exp( new_exp ); // 'new_exp' depends on the 'new_man' which is stored like this e.g: // 32342343234 (the comma is at the end) // we'd like to show it in this way: // 3.2342343234 (the 'scientific_exp' is connected with this example) sint offset = sint( new_man.length() ) - 1; carry += scientific_exp.Add( offset ); // there shouldn't have been a carry because we're using // a greater type -- 'Int' instead of 'Int' bool print_scientific = conv.scient; if( !print_scientific ) { if( scientific_exp > conv.scient_from || scientific_exp < -sint(conv.scient_from) ) print_scientific = true; } if( !print_scientific ) ToString_SetCommaAndExponent_Normal(new_man, conv, new_exp); else // we're passing the 'scientific_exp' instead of 'new_exp' here ToString_SetCommaAndExponent_Scientific(new_man, conv, scientific_exp); return (carry==0)? 0 : 1; } /*! an auxiliary method for converting into the string */ template void ToString_SetCommaAndExponent_Normal(string_type & new_man, const Conv & conv, Int & new_exp ) const { if( !new_exp.IsSign() ) // it means: if( new_exp >= 0 ) ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp); else ToString_SetCommaAndExponent_Normal_SetCommaInside(new_man, conv, new_exp); ToString_Group_man(new_man, conv); } /*! an auxiliary method for converting into the string */ template void ToString_SetCommaAndExponent_Normal_AddingZero(string_type & new_man, Int & new_exp) const { // we're adding zero characters at the end // 'i' will be smaller than 'when_scientific' (or equal) uint i = new_exp.ToInt(); if( new_man.length() + i > new_man.capacity() ) // about 6 characters more (we'll need it for the comma or something) new_man.reserve( new_man.length() + i + 6 ); for( ; i>0 ; --i) new_man += '0'; } /*! an auxiliary method for converting into the string */ template void ToString_SetCommaAndExponent_Normal_SetCommaInside( string_type & new_man, const Conv & conv, Int & new_exp ) const { // new_exp is < 0 sint new_man_len = sint(new_man.length()); // 'new_man_len' with a sign sint e = -( new_exp.ToInt() ); // 'e' will be positive if( new_exp > -new_man_len ) { // we're setting the comma within the mantissa sint index = new_man_len - e; new_man.insert( new_man.begin() + index, static_cast(conv.comma)); } else { // we're adding zero characters before the mantissa uint how_many = e - new_man_len; string_type man_temp(how_many+1, '0'); man_temp.insert( man_temp.begin()+1, static_cast(conv.comma)); new_man.insert(0, man_temp); } ToString_CorrectDigitsAfterComma(new_man, conv); } /*! an auxiliary method for converting into the string */ template void ToString_SetCommaAndExponent_Scientific( string_type & new_man, const Conv & conv, Int & scientific_exp ) const { if( new_man.empty() ) return; if( new_man.size() > 1 ) { new_man.insert( new_man.begin()+1, static_cast(conv.comma) ); ToString_CorrectDigitsAfterComma(new_man, conv); } ToString_Group_man(new_man, conv); if( conv.base == 10 ) { new_man += 'e'; if( !scientific_exp.IsSign() ) new_man += '+'; } else { // the 10 here is meant as the base 'base' // (no matter which 'base' we're using there'll always be 10 here) Misc::AddString(new_man, "*10^"); } string_type temp_exp; scientific_exp.ToString( temp_exp, conv.base ); new_man += temp_exp; } /*! an auxiliary method for converting into the string */ template void ToString_Group_man(string_type & new_man, const Conv & conv) const { typedef typename string_type::size_type StrSize; if( conv.group == 0 ) return; // first we're looking for the comma operator StrSize index = new_man.find(static_cast(conv.comma), 0); if( index == string_type::npos ) index = new_man.size(); ToString_Group_man_before_comma(new_man, conv, index); ToString_Group_man_after_comma(new_man, conv, index+1); } /*! an auxiliary method for converting into the string */ template void ToString_Group_man_before_comma( string_type & new_man, const Conv & conv, typename string_type::size_type & index) const { typedef typename string_type::size_type StrSize; uint group = 0; StrSize i = index; // adding group characters before the comma operator // i>0 because on the first position we don't put any additional grouping characters for( ; i>0 ; --i, ++group) { if( group >= 3 ) { group = 0; new_man.insert(i, 1, static_cast(conv.group)); ++index; } } } /*! an auxiliary method for converting into the string */ template void ToString_Group_man_after_comma(string_type & new_man, const Conv & conv, typename string_type::size_type index) const { uint group = 0; for( ; index= 3 ) { group = 0; new_man.insert(index, 1, static_cast(conv.group)); ++index; } } } /*! an auxiliary method for converting into the string */ template void ToString_CorrectDigitsAfterComma( string_type & new_man, const Conv & conv ) const { if( conv.round >= 0 ) ToString_CorrectDigitsAfterComma_Round(new_man, conv); if( conv.trim_zeroes ) ToString_CorrectDigitsAfterComma_CutOffZeroCharacters(new_man, conv); } /*! an auxiliary method for converting into the string */ template void ToString_CorrectDigitsAfterComma_CutOffZeroCharacters( string_type & new_man, const Conv & conv) const { // minimum two characters if( new_man.length() < 2 ) return; // we're looking for the index of the last character which is not zero uint i = uint( new_man.length() ) - 1; for( ; i>0 && new_man[i]=='0' ; --i ); // if there is another character than zero at the end // we're finishing if( i == new_man.length() - 1 ) return; // we must have a comma // (the comma can be removed by ToString_CorrectDigitsAfterComma_Round // which is called before) if( new_man.find_last_of(static_cast(conv.comma), i) == string_type::npos ) return; // if directly before the first zero is the comma operator // we're cutting it as well if( i>0 && new_man[i]==static_cast(conv.comma) ) --i; new_man.erase(i+1, new_man.length()-i-1); } /*! an auxiliary method for converting into the string */ template void ToString_CorrectDigitsAfterComma_Round( string_type & new_man, const Conv & conv ) const { typedef typename string_type::size_type StrSize; // first we're looking for the comma operator StrSize index = new_man.find(static_cast(conv.comma), 0); if( index == string_type::npos ) // nothing was found (actually there can't be this situation) return; // we're calculating how many digits there are at the end (after the comma) // 'after_comma' will be greater than zero because at the end // we have at least one digit StrSize after_comma = new_man.length() - index - 1; // if 'max_digit_after_comma' is greater than 'after_comma' (or equal) // we don't have anything for cutting if( static_cast(conv.round) >= after_comma ) return; uint last_digit = Misc::CharToDigit( new_man[ index + conv.round + 1 ], conv.base ); // we're cutting the rest of the string new_man.erase(index + conv.round + 1, after_comma - conv.round); if( conv.round == 0 ) { // we're cutting the comma operator as well // (it's not needed now because we've cut the whole rest after the comma) new_man.erase(index, 1); } if( last_digit >= conv.base / 2 ) // we must round here ToString_RoundMantissa_AddOneIntoMantissa(new_man, conv); } public: /*! a method for converting a string into its value it returns 1 if the value is too big -- we cannot pass it into the range of our class Big (or if the base is incorrect) that means only digits before the comma operator can make this value too big, all digits after the comma we can ignore 'source' - pointer to the string for parsing if 'after_source' is set that when this method finishes it sets the pointer to the new first character after parsed value 'value_read' - if the pointer is provided that means the value_read will be true only when a value has been actually read, there can be situation where only such a string '-' or '+' will be parsed -- 'after_source' will be different from 'source' but no value has been read (there are no digits) on other words if 'value_read' is true -- there is at least one digit in the string */ uint FromString(const char * source, uint base = 10, const char ** after_source = 0, bool * value_read = 0) { Conv conv; conv.base = base; return FromStringBase(source, conv, after_source, value_read); } /*! a method for converting a string into its value */ uint FromString(const char * source, const Conv & conv, const char ** after_source = 0, bool * value_read = 0) { return FromStringBase(source, conv, after_source, value_read); } /*! a method for converting a string into its value */ uint FromString(const std::string & string, uint base = 10, const char ** after_source = 0, bool * value_read = 0) { return FromString(string.c_str(), base, after_source, value_read); } /*! a method for converting a string into its value */ uint FromString(const std::string & string, const Conv & conv, const char ** after_source = 0, bool * value_read = 0) { return FromString(string.c_str(), conv, after_source, value_read); } #ifndef TTMATH_DONT_USE_WCHAR /*! a method for converting a string into its value */ uint FromString(const wchar_t * source, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0) { Conv conv; conv.base = base; return FromStringBase(source, conv, after_source, value_read); } /*! a method for converting a string into its value */ uint FromString(const wchar_t * source, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0) { return FromStringBase(source, conv, after_source, value_read); } /*! a method for converting a string into its value */ uint FromString(const std::wstring & string, uint base = 10, const wchar_t ** after_source = 0, bool * value_read = 0) { return FromString(string.c_str(), base, after_source, value_read); } /*! a method for converting a string into its value */ uint FromString(const std::wstring & string, const Conv & conv, const wchar_t ** after_source = 0, bool * value_read = 0) { return FromString(string.c_str(), conv, after_source, value_read); } #endif private: /*! an auxiliary method for converting from a string */ template uint FromStringBase(const char_type * source, const Conv & conv, const char_type ** after_source = 0, bool * value_read = 0) { bool is_sign; bool value_read_temp = false; if( conv.base<2 || conv.base>16 ) { SetNan(); if( after_source ) *after_source = source; if( value_read ) *value_read = value_read_temp; return 1; } SetZero(); FromString_TestSign( source, is_sign ); uint c = FromString_ReadPartBeforeComma( source, conv, value_read_temp ); if( FromString_TestCommaOperator(source, conv) ) c += FromString_ReadPartAfterComma( source, conv, value_read_temp ); if( value_read_temp && conv.base == 10 ) c += FromString_ReadScientificIfExists( source ); if( is_sign && !IsZero() ) ChangeSign(); if( after_source ) *after_source = source; if( value_read ) *value_read = value_read_temp; return CheckCarry(c); } /*! we're testing whether the value is with the sign (this method is used from 'FromString_ReadPartScientific' too) */ template void FromString_TestSign( const char_type * & source, bool & is_sign ) { Misc::SkipWhiteCharacters(source); is_sign = false; if( *source == '-' ) { is_sign = true; ++source; } else if( *source == '+' ) { ++source; } } /*! we're testing whether there's a comma operator */ template bool FromString_TestCommaOperator(const char_type * & source, const Conv & conv) { if( (*source == static_cast(conv.comma)) || (*source == static_cast(conv.comma2) && conv.comma2 != 0 ) ) { ++source; return true; } return false; } /*! this method reads the first part of a string (before the comma operator) */ template uint FromString_ReadPartBeforeComma( const char_type * & source, const Conv & conv, bool & value_read ) { sint character; Big temp; Big base_( conv.base ); Misc::SkipWhiteCharacters( source ); for( ; true ; ++source ) { if( conv.group!=0 && *source==static_cast(conv.group) ) continue; character = Misc::CharToDigit(*source, conv.base); if( character == -1 ) break; value_read = true; temp = character; if( Mul(base_) ) return 1; if( Add(temp) ) return 1; } return 0; } /*! this method reads the second part of a string (after the comma operator) */ template uint FromString_ReadPartAfterComma( const char_type * & source, const Conv & conv, bool & value_read ) { sint character; uint c = 0, index = 1; Big sum, part, power, old_value, base_( conv.base ); // we don't remove any white characters here // this is only to avoid getting a warning about an uninitialized object 'old_value' which GCC reports // (in fact we will initialize it later when the condition 'testing' is fulfilled) old_value.SetZero(); power.SetOne(); sum.SetZero(); for( ; true ; ++source, ++index ) { if( conv.group!=0 && *source==static_cast(conv.group) ) continue; character = Misc::CharToDigit(*source, conv.base); if( character == -1 ) break; value_read = true; part = character; if( power.Mul( base_ ) ) // there's no sens to add the next parts, but we can't report this // as an error (this is only inaccuracy) break; if( part.Div( power ) ) break; // every 5 iteration we make a test whether the value will be changed or not // (character must be different from zero to this test) bool testing = (character != 0 && (index % 5) == 0); if( testing ) old_value = sum; // there actually shouldn't be a carry here c += sum.Add( part ); if( testing && old_value == sum ) // after adding 'part' the value has not been changed // there's no sense to add any next parts break; } // we could break the parsing somewhere in the middle of the string, // but the result (value) still can be good // we should set a correct value of 'source' now for( ; Misc::CharToDigit(*source, conv.base) != -1 ; ++source ); c += Add(sum); return (c==0)? 0 : 1; } /*! this method checks whether there is a scientific part: [e|E][-|+]value it is called when the base is 10 and some digits were read before */ template uint FromString_ReadScientificIfExists(const char_type * & source) { uint c = 0; bool scientific_read = false; const char_type * before_scientific = source; if( FromString_TestScientific(source) ) c += FromString_ReadPartScientific( source, scientific_read ); if( !scientific_read ) source = before_scientific; return (c==0)? 0 : 1; } /*! we're testing whether is there the character 'e' this character is only allowed when we're using the base equals 10 */ template bool FromString_TestScientific(const char_type * & source) { Misc::SkipWhiteCharacters(source); if( *source=='e' || *source=='E' ) { ++source; return true; } return false; } /*! this method reads the exponent (after 'e' character) when there's a scientific format of value and only when we're using the base equals 10 */ template uint FromString_ReadPartScientific( const char_type * & source, bool & scientific_read ) { uint c = 0; Big new_exponent, temp; bool was_sign = false; FromString_TestSign( source, was_sign ); c += FromString_ReadPartScientific_ReadExponent( source, new_exponent, scientific_read ); if( scientific_read ) { if( was_sign ) new_exponent.ChangeSign(); temp = 10; c += temp.Pow( new_exponent ); c += Mul(temp); } return (c==0)? 0 : 1; } /*! this method reads the value of the extra exponent when scientific format is used (only when base == 10) */ template uint FromString_ReadPartScientific_ReadExponent( const char_type * & source, Big & new_exponent, bool & scientific_read ) { sint character; Big base, temp; Misc::SkipWhiteCharacters(source); new_exponent.SetZero(); base = 10; for( ; (character=Misc::CharToDigit(*source, 10)) != -1 ; ++source ) { scientific_read = true; temp = character; if( new_exponent.Mul(base) ) return 1; if( new_exponent.Add(temp) ) return 1; } return 0; } public: /*! a constructor for converting a string into this class */ Big(const char * string) { FromString( string ); } /*! a constructor for converting a string into this class */ Big(const std::string & string) { FromString( string.c_str() ); } /*! an operator= for converting a string into its value */ Big & operator=(const char * string) { FromString( string ); return *this; } /*! an operator= for converting a string into its value */ Big & operator=(const std::string & string) { FromString( string.c_str() ); return *this; } #ifndef TTMATH_DONT_USE_WCHAR /*! a constructor for converting a string into this class */ Big(const wchar_t * string) { FromString( string ); } /*! a constructor for converting a string into this class */ Big(const std::wstring & string) { FromString( string.c_str() ); } /*! an operator= for converting a string into its value */ Big & operator=(const wchar_t * string) { FromString( string ); return *this; } /*! an operator= for converting a string into its value */ Big & operator=(const std::wstring & string) { FromString( string.c_str() ); return *this; } #endif /*! * * methods for comparing * */ /*! this method performs the formula 'abs(this) < abs(ss2)' and returns the result (in other words it treats 'this' and 'ss2' as values without a sign) we don't check the NaN flag */ bool SmallerWithoutSignThan(const Big & ss2) const { if( IsZero() ) { if( ss2.IsZero() ) // we've got two zeroes return false; else // this==0 and ss2!=0 return true; } if( ss2.IsZero() ) // this!=0 and ss2==0 return false; // we're using the fact that all bits in mantissa are pushed // into the left side -- Standardizing() if( exponent == ss2.exponent ) return mantissa < ss2.mantissa; return exponent < ss2.exponent; } /*! this method performs the formula 'abs(this) > abs(ss2)' and returns the result (in other words it treats 'this' and 'ss2' as values without a sign) we don't check the NaN flag */ bool GreaterWithoutSignThan(const Big & ss2) const { if( IsZero() ) { if( ss2.IsZero() ) // we've got two zeroes return false; else // this==0 and ss2!=0 return false; } if( ss2.IsZero() ) // this!=0 and ss2==0 return true; // we're using the fact that all bits in mantissa are pushed // into the left side -- Standardizing() if( exponent == ss2.exponent ) return mantissa > ss2.mantissa; return exponent > ss2.exponent; } /*! this method performs the formula 'abs(this) == abs(ss2)' and returns the result (in other words it treats 'this' and 'ss2' as values without a sign) we don't check the NaN flag */ bool EqualWithoutSign(const Big & ss2) const { if( IsZero() ) { if( ss2.IsZero() ) // we've got two zeroes return true; else // this==0 and ss2!=0 return false; } if( ss2.IsZero() ) // this!=0 and ss2==0 return false; if( exponent==ss2.exponent && mantissa==ss2.mantissa ) return true; return false; } bool operator<(const Big & ss2) const { if( IsSign() && !ss2.IsSign() ) // this<0 and ss2>=0 return true; if( !IsSign() && ss2.IsSign() ) // this>=0 and ss2<0 return false; // both signs are the same if( IsSign() ) return ss2.SmallerWithoutSignThan( *this ); return SmallerWithoutSignThan( ss2 ); } bool operator==(const Big & ss2) const { if( IsSign() != ss2.IsSign() ) return false; return EqualWithoutSign( ss2 ); } bool operator>(const Big & ss2) const { if( IsSign() && !ss2.IsSign() ) // this<0 and ss2>=0 return false; if( !IsSign() && ss2.IsSign() ) // this>=0 and ss2<0 return true; // both signs are the same if( IsSign() ) return ss2.GreaterWithoutSignThan( *this ); return GreaterWithoutSignThan( ss2 ); } bool operator>=(const Big & ss2) const { return !operator<( ss2 ); } bool operator<=(const Big & ss2) const { return !operator>( ss2 ); } bool operator!=(const Big & ss2) const { return !operator==(ss2); } /*! * * standard mathematical operators * */ /*! an operator for changing the sign this method is not changing 'this' but the changed value is returned */ Big operator-() const { Big temp(*this); temp.ChangeSign(); return temp; } Big operator-(const Big & ss2) const { Big temp(*this); temp.Sub(ss2); return temp; } Big & operator-=(const Big & ss2) { Sub(ss2); return *this; } Big operator+(const Big & ss2) const { Big temp(*this); temp.Add(ss2); return temp; } Big & operator+=(const Big & ss2) { Add(ss2); return *this; } Big operator*(const Big & ss2) const { Big temp(*this); temp.Mul(ss2); return temp; } Big & operator*=(const Big & ss2) { Mul(ss2); return *this; } Big operator/(const Big & ss2) const { Big temp(*this); temp.Div(ss2); return temp; } Big & operator/=(const Big & ss2) { Div(ss2); return *this; } /*! Prefix operator e.g ++variable */ Big & operator++() { AddOne(); return *this; } /*! Postfix operator e.g variable++ */ Big operator++(int) { Big temp( *this ); AddOne(); return temp; } Big & operator--() { SubOne(); return *this; } Big operator--(int) { Big temp( *this ); SubOne(); return temp; } /*! * * bitwise operators * (we do not define bitwise not) */ Big operator&(const Big & p2) const { Big temp( *this ); temp.BitAnd(p2); return temp; } Big & operator&=(const Big & p2) { BitAnd(p2); return *this; } Big operator|(const Big & p2) const { Big temp( *this ); temp.BitOr(p2); return temp; } Big & operator|=(const Big & p2) { BitOr(p2); return *this; } Big operator^(const Big & p2) const { Big temp( *this ); temp.BitXor(p2); return temp; } Big & operator^=(const Big & p2) { BitXor(p2); return *this; } /*! this method makes an integer value by skipping any fractions for example: 10.7 will be 10 12.1 -- 12 -20.2 -- 20 -20.9 -- 20 -0.7 -- 0 0.8 -- 0 */ void SkipFraction() { if( IsNan() || IsZero() ) return; if( !exponent.IsSign() ) // exponent >=0 -- the value don't have any fractions return; if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) { // the value is from (-1,1), we return zero SetZero(); return; } // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0) sint e = exponent.ToInt(); mantissa.ClearFirstBits( -e ); // we don't have to standardize 'Standardizing()' the value because // there's at least one bit in the mantissa // (the highest bit which we didn't touch) } /*! this method remains only a fraction from the value for example: 30.56 will be 0.56 -12.67 -- -0.67 */ void RemainFraction() { if( IsNan() || IsZero() ) return; if( !exponent.IsSign() ) { // exponent >= 0 -- the value doesn't have any fractions // we return zero SetZero(); return; } if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) { // the value is from (-1,1) // we don't make anything with the value return; } // e will be from (-man*TTMATH_BITS_PER_UINT, 0) sint e = exponent.ToInt(); sint how_many_bits_leave = sint(man*TTMATH_BITS_PER_UINT) + e; // there'll be a subtraction -- e is negative mantissa.Rcl( how_many_bits_leave, 0); // there'll not be a carry because the exponent is too small exponent.Sub( how_many_bits_leave ); // we must call Standardizing() here Standardizing(); } /*! this method returns true if the value is integer (there is no a fraction) (we don't check nan) */ bool IsInteger() const { if( IsZero() ) return true; if( !exponent.IsSign() ) // exponent >=0 -- the value don't have any fractions return true; if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) ) // the value is from (-1,1) return false; // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0) sint e = exponent.ToInt(); e = -e; // e means how many bits we must check uint len = e / TTMATH_BITS_PER_UINT; uint rest = e % TTMATH_BITS_PER_UINT; uint i = 0; for( ; i 0 ) { uint rest_mask = TTMATH_UINT_MAX_VALUE >> (TTMATH_BITS_PER_UINT - rest); if( (mantissa.table[i] & rest_mask) != 0 ) return false; } return true; } /*! this method rounds to the nearest integer value (it returns a carry if it was) for example: 2.3 = 2 2.8 = 3 -2.3 = -2 -2.8 = 3 */ uint Round() { Big half; uint c; if( IsNan() ) return 1; if( IsZero() ) return 0; half.Set05(); if( IsSign() ) { // 'this' is < 0 c = Sub( half ); } else { // 'this' is > 0 c = Add( half ); } SkipFraction(); return CheckCarry(c); } /*! * * input/output operators for standard streams * */ private: /*! an auxiliary method for outputing to standard streams */ template static ostream_type & OutputToStream(ostream_type & s, const Big & l) { string_type ss; l.ToString(ss); s << ss; return s; } public: /*! output to standard streams */ friend std::ostream & operator<<(std::ostream & s, const Big & l) { return OutputToStream(s, l); } #ifndef TTMATH_DONT_USE_WCHAR /*! output to standard streams */ friend std::wostream & operator<<(std::wostream & s, const Big & l) { return OutputToStream(s, l); } #endif private: /*! an auxiliary method for converting from a string */ template static istream_type & InputFromStream(istream_type & s, Big & l) { string_type ss; // char or wchar_t for operator>> char_type z, old_z; bool was_comma = false; bool was_e = false; // operator>> omits white characters if they're set for ommiting s >> z; if( z=='-' || z=='+' ) { ss += z; s >> z; // we're reading a next character (white characters can be ommited) } old_z = 0; // we're reading only digits (base=10) and only one comma operator for( ; s.good() ; z=static_cast(s.get()) ) { if( z=='.' || z==',' ) { if( was_comma || was_e ) // second comma operator or comma operator after 'e' character break; was_comma = true; } else if( z == 'e' || z == 'E' ) { if( was_e ) // second 'e' character break; was_e = true; } else if( z == '+' || z == '-' ) { if( old_z != 'e' && old_z != 'E' ) // '+' or '-' is allowed only after 'e' character break; } else if( Misc::CharToDigit(z, 10) < 0 ) break; ss += z; old_z = z; } // we're leaving the last read character // (it's not belonging to the value) s.unget(); l.FromString( ss ); return s; } public: /*! input from standard streams */ friend std::istream & operator>>(std::istream & s, Big & l) { return InputFromStream(s, l); } #ifndef TTMATH_DONT_USE_WCHAR /*! input from standard streams */ friend std::wistream & operator>>(std::wistream & s, Big & l) { return InputFromStream(s, l); } #endif }; } // namespace #endif discoSnp/minia/ttmath/ttmaththreads.h0000644000000000000000000001166112062133074016764 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2009, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmaththreads #define headerfilettmaththreads #include "ttmathtypes.h" #ifdef TTMATH_WIN32_THREADS #include #include #endif #ifdef TTMATH_POSIX_THREADS #include #endif /*! \file ttmaththreads.h \brief Some objects used in multithreads environment */ /* this is a simple skeleton of a program in multithreads environment: #define TTMATH_MULTITHREADS #include TTMATH_MULTITHREADS_HELPER int main() { [...] } make sure that macro TTMATH_MULTITHREADS is defined and (somewhere in *.cpp file) use TTMATH_MULTITHREADS_HELPER macro (outside of any classes/functions/namespaces scope) */ namespace ttmath { #ifdef TTMATH_WIN32_THREADS /* we use win32 threads */ /*! in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro somewhere in *.cpp file (at the moment in win32 this macro does nothing) */ #define TTMATH_MULTITHREADS_HELPER /*! objects of this class are used to synchronize */ class ThreadLock { HANDLE mutex_handle; void CreateName(char * buffer) const { #ifdef _MSC_VER #pragma warning (disable : 4996) // warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. #endif sprintf(buffer, "TTMATH_LOCK_%ul", (unsigned long)GetCurrentProcessId()); #ifdef _MSC_VER #pragma warning (default : 4996) #endif } public: bool Lock() { char buffer[50]; CreateName(buffer); mutex_handle = CreateMutexA(0, false, buffer); if( mutex_handle == 0 ) return false; WaitForSingleObject(mutex_handle, INFINITE); return true; } ThreadLock() { mutex_handle = 0; } ~ThreadLock() { if( mutex_handle != 0 ) { ReleaseMutex(mutex_handle); CloseHandle(mutex_handle); } } }; #endif // #ifdef TTMATH_WIN32_THREADS #ifdef TTMATH_POSIX_THREADS /* we use posix threads */ /*! in multithreads environment you should use TTMATH_MULTITHREADS_HELPER macro somewhere in *.cpp file (this macro defines a pthread_mutex_t object used by TTMath library) */ #define TTMATH_MULTITHREADS_HELPER \ namespace ttmath \ { \ pthread_mutex_t ttmath_mutex = PTHREAD_MUTEX_INITIALIZER; \ } /*! ttmath_mutex will be defined by TTMATH_MULTITHREADS_HELPER macro */ extern pthread_mutex_t ttmath_mutex; /*! objects of this class are used to synchronize */ class ThreadLock { public: bool Lock() { if( pthread_mutex_lock(&ttmath_mutex) != 0 ) return false; return true; } ~ThreadLock() { pthread_mutex_unlock(&ttmath_mutex); } }; #endif // #ifdef TTMATH_POSIX_THREADS #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) /*! we don't use win32 and pthreads */ /*! */ #define TTMATH_MULTITHREADS_HELPER /*! objects of this class are used to synchronize actually we don't synchronize, the method Lock() returns always 'false' */ class ThreadLock { public: bool Lock() { return false; } }; #endif // #if !defined(TTMATH_POSIX_THREADS) && !defined(TTMATH_WIN32_THREADS) } // namespace #endif discoSnp/minia/ttmath/ttmath.h0000644000000000000000000015207412062133074015415 0ustar rootroot/* * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2006-2010, Tomasz Sowa * 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 Tomasz Sowa nor the names of contributors to this * project 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 headerfilettmathmathtt #define headerfilettmathmathtt /*! \file ttmath.h \brief Mathematics functions. */ #ifdef _MSC_VER //warning C4127: conditional expression is constant #pragma warning( disable: 4127 ) //warning C4702: unreachable code #pragma warning( disable: 4702 ) //warning C4800: forcing value to bool 'true' or 'false' (performance warning) #pragma warning( disable: 4800 ) #endif #include "ttmathbig.h" #include "ttmathobjects.h" namespace ttmath { /* * * functions defined here are used only with Big<> types * * */ /* * * functions for rounding * * */ /*! this function skips the fraction from x e.g 2.2 = 2 2.7 = 2 -2.2 = 2 -2.7 = 2 */ template ValueType SkipFraction(const ValueType & x) { ValueType result( x ); result.SkipFraction(); return result; } /*! this function rounds to the nearest integer value e.g 2.2 = 2 2.7 = 3 -2.2 = -2 -2.7 = -3 */ template ValueType Round(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType result( x ); uint c = result.Round(); if( err ) *err = c ? err_overflow : err_ok; return result; } /*! this function returns a value representing the smallest integer that is greater than or equal to x Ceil(-3.7) = -3 Ceil(-3.1) = -3 Ceil(-3.0) = -3 Ceil(4.0) = 4 Ceil(4.2) = 5 Ceil(4.8) = 5 */ template ValueType Ceil(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType result(x); uint c = 0; result.SkipFraction(); if( result != x ) { // x is with fraction // if x is negative we don't have to do anything if( !x.IsSign() ) { ValueType one; one.SetOne(); c += result.Add(one); } } if( err ) *err = c ? err_overflow : err_ok; return result; } /*! this function returns a value representing the largest integer that is less than or equal to x Floor(-3.6) = -4 Floor(-3.1) = -4 Floor(-3) = -3 Floor(2) = 2 Floor(2.3) = 2 Floor(2.8) = 2 */ template ValueType Floor(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType result(x); uint c = 0; result.SkipFraction(); if( result != x ) { // x is with fraction // if x is positive we don't have to do anything if( x.IsSign() ) { ValueType one; one.SetOne(); c += result.Sub(one); } } if( err ) *err = c ? err_overflow : err_ok; return result; } /* * * logarithms and the exponent * * */ /*! this function calculates the natural logarithm (logarithm with the base 'e') */ template ValueType Ln(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType result; uint state = result.Ln(x); if( err ) { switch( state ) { case 0: *err = err_ok; break; case 1: *err = err_overflow; break; case 2: *err = err_improper_argument; break; default: *err = err_internal_error; break; } } return result; } /*! this function calculates the logarithm */ template ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; } if( base.IsNan() ) { if( err ) *err = err_improper_argument; return base; } ValueType result; uint state = result.Log(x, base); if( err ) { switch( state ) { case 0: *err = err_ok; break; case 1: *err = err_overflow; break; case 2: case 3: *err = err_improper_argument; break; default: *err = err_internal_error; break; } } return result; } /*! this function calculates the expression e^x */ template ValueType Exp(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType result; uint c = result.Exp(x); if( err ) *err = c ? err_overflow : err_ok; return result; } /*! * * trigonometric functions * */ /* this namespace consists of auxiliary functions (something like 'private' in a class) */ namespace auxiliaryfunctions { /*! an auxiliary function for calculating the Sine (you don't have to call this function) */ template uint PrepareSin(ValueType & x, bool & change_sign) { ValueType temp; change_sign = false; if( x.IsSign() ) { // we're using the formula 'sin(-x) = -sin(x)' change_sign = !change_sign; x.ChangeSign(); } // we're reducing the period 2*PI // (for big values there'll always be zero) temp.Set2Pi(); if( x.Mod(temp) ) return 1; // we're setting 'x' as being in the range of <0, 0.5PI> temp.SetPi(); if( x > temp ) { // x is in (pi, 2*pi> x.Sub( temp ); change_sign = !change_sign; } temp.Set05Pi(); if( x > temp ) { // x is in (0.5pi, pi> x.Sub( temp ); x = temp - x; } return 0; } /*! an auxiliary function for calculating the Sine (you don't have to call this function) it returns Sin(x) where 'x' is from <0, PI/2> we're calculating the Sin with using Taylor series in zero or PI/2 (depending on which point of these two points is nearer to the 'x') Taylor series: sin(x) = sin(a) + cos(a)*(x-a)/(1!) - sin(a)*((x-a)^2)/(2!) - cos(a)*((x-a)^3)/(3!) + sin(a)*((x-a)^4)/(4!) + ... when a=0 it'll be: sin(x) = (x)/(1!) - (x^3)/(3!) + (x^5)/(5!) - (x^7)/(7!) + (x^9)/(9!) ... and when a=PI/2: sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ... */ template ValueType Sin0pi05(const ValueType & x) { ValueType result; ValueType numerator, denominator; ValueType d_numerator, d_denominator; ValueType one, temp, old_result; // temp = pi/4 temp.Set05Pi(); temp.exponent.SubOne(); one.SetOne(); if( x < temp ) { // we're using the Taylor series with a=0 result = x; numerator = x; denominator = one; // d_numerator = x^2 d_numerator = x; d_numerator.Mul(x); d_denominator = 2; } else { // we're using the Taylor series with a=PI/2 result = one; numerator = one; denominator = one; // d_numerator = (x-pi/2)^2 ValueType pi05; pi05.Set05Pi(); temp = x; temp.Sub( pi05 ); d_numerator = temp; d_numerator.Mul( temp ); d_denominator = one; } uint c = 0; bool addition = false; old_result = result; for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) { // we're starting from a second part of the formula c += numerator. Mul( d_numerator ); c += denominator. Mul( d_denominator ); c += d_denominator.Add( one ); c += denominator. Mul( d_denominator ); c += d_denominator.Add( one ); temp = numerator; c += temp.Div(denominator); if( c ) // Sin is from <-1,1> and cannot make an overflow // but the carry can be from the Taylor series // (then we only break our calculations) break; if( addition ) result.Add( temp ); else result.Sub( temp ); addition = !addition; // we're testing whether the result has changed after adding // the next part of the Taylor formula, if not we end the loop // (it means 'x' is zero or 'x' is PI/2 or this part of the formula // is too small) if( result == old_result ) break; old_result = result; } return result; } } // namespace auxiliaryfunctions /*! this function calculates the Sine */ template ValueType Sin(ValueType x, ErrorCode * err = 0) { using namespace auxiliaryfunctions; ValueType one, result; bool change_sign; if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; } if( err ) *err = err_ok; if( PrepareSin( x, change_sign ) ) { // x is too big, we cannnot reduce the 2*PI period // prior to version 0.8.5 the result was zero // result has NaN flag set by default if( err ) *err = err_overflow; // maybe another error code? err_improper_argument? return result; // NaN is set by default } result = Sin0pi05( x ); one.SetOne(); // after calculations there can be small distortions in the result if( result > one ) result = one; else if( result.IsSign() ) // we've calculated the sin from <0, pi/2> and the result // should be positive result.SetZero(); if( change_sign ) result.ChangeSign(); return result; } /*! this function calulates the Cosine we're using the formula cos(x) = sin(x + PI/2) */ template ValueType Cos(ValueType x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType pi05; pi05.Set05Pi(); uint c = x.Add( pi05 ); if( c ) { if( err ) *err = err_overflow; return ValueType(); // result is undefined (NaN is set by default) } return Sin(x, err); } /*! this function calulates the Tangent we're using the formula tan(x) = sin(x) / cos(x) it takes more time than calculating the Tan directly from for example Taylor series but should be a bit preciser because Tan receives its values from -infinity to +infinity and when we calculate it from any series then we can make a greater mistake than calculating 'sin/cos' */ template ValueType Tan(const ValueType & x, ErrorCode * err = 0) { ValueType result = Cos(x, err); if( err && *err != err_ok ) return result; if( result.IsZero() ) { if( err ) *err = err_improper_argument; result.SetNan(); return result; } return Sin(x, err) / result; } /*! this function calulates the Tangent look at the description of Tan(...) (the abbreviation of Tangent can be 'tg' as well) */ template ValueType Tg(const ValueType & x, ErrorCode * err = 0) { return Tan(x, err); } /*! this function calulates the Cotangent we're using the formula tan(x) = cos(x) / sin(x) (why do we make it in this way? look at information in Tan() function) */ template ValueType Cot(const ValueType & x, ErrorCode * err = 0) { ValueType result = Sin(x, err); if( err && *err != err_ok ) return result; if( result.IsZero() ) { if( err ) *err = err_improper_argument; result.SetNan(); return result; } return Cos(x, err) / result; } /*! this function calulates the Cotangent look at the description of Cot(...) (the abbreviation of Cotangent can be 'ctg' as well) */ template ValueType Ctg(const ValueType & x, ErrorCode * err = 0) { return Cot(x, err); } /* * * inverse trigonometric functions * * */ namespace auxiliaryfunctions { /*! an auxiliary function for calculating the Arc Sine we're calculating asin from the following formula: asin(x) = x + (1*x^3)/(2*3) + (1*3*x^5)/(2*4*5) + (1*3*5*x^7)/(2*4*6*7) + ... where abs(x) <= 1 we're using this formula when x is from <0, 1/2> */ template ValueType ASin_0(const ValueType & x) { ValueType nominator, denominator, nominator_add, nominator_x, denominator_add, denominator_x; ValueType two, result(x), x2(x); ValueType nominator_temp, denominator_temp, old_result = result; uint c = 0; x2.Mul(x); two = 2; nominator.SetOne(); denominator = two; nominator_add = nominator; denominator_add = denominator; nominator_x = x; denominator_x = 3; for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) { c += nominator_x.Mul(x2); nominator_temp = nominator_x; c += nominator_temp.Mul(nominator); denominator_temp = denominator; c += denominator_temp.Mul(denominator_x); c += nominator_temp.Div(denominator_temp); // if there is a carry somewhere we only break the calculating // the result should be ok -- it's from <-pi/2, pi/2> if( c ) break; result.Add(nominator_temp); if( result == old_result ) // there's no sense to calculate more break; old_result = result; c += nominator_add.Add(two); c += denominator_add.Add(two); c += nominator.Mul(nominator_add); c += denominator.Mul(denominator_add); c += denominator_x.Add(two); } return result; } /*! an auxiliary function for calculating the Arc Sine we're calculating asin from the following formula: asin(x) = pi/2 - sqrt(2)*sqrt(1-x) * asin_temp asin_temp = 1 + (1*(1-x))/((2*3)*(2)) + (1*3*(1-x)^2)/((2*4*5)*(4)) + (1*3*5*(1-x)^3)/((2*4*6*7)*(8)) + ... where abs(x) <= 1 we're using this formula when x is from (1/2, 1> */ template ValueType ASin_1(const ValueType & x) { ValueType nominator, denominator, nominator_add, nominator_x, nominator_x_add, denominator_add, denominator_x; ValueType denominator2; ValueType one, two, result; ValueType nominator_temp, denominator_temp, old_result; uint c = 0; two = 2; one.SetOne(); nominator = one; result = one; old_result = result; denominator = two; nominator_add = nominator; denominator_add = denominator; nominator_x = one; nominator_x.Sub(x); nominator_x_add = nominator_x; denominator_x = 3; denominator2 = two; for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) { nominator_temp = nominator_x; c += nominator_temp.Mul(nominator); denominator_temp = denominator; c += denominator_temp.Mul(denominator_x); c += denominator_temp.Mul(denominator2); c += nominator_temp.Div(denominator_temp); // if there is a carry somewhere we only break the calculating // the result should be ok -- it's from <-pi/2, pi/2> if( c ) break; result.Add(nominator_temp); if( result == old_result ) // there's no sense to calculate more break; old_result = result; c += nominator_x.Mul(nominator_x_add); c += nominator_add.Add(two); c += denominator_add.Add(two); c += nominator.Mul(nominator_add); c += denominator.Mul(denominator_add); c += denominator_x.Add(two); c += denominator2.Mul(two); } nominator_x_add.exponent.AddOne(); // *2 one.exponent.SubOne(); // =0.5 nominator_x_add.Pow(one); // =sqrt(nominator_x_add) result.Mul(nominator_x_add); one.Set05Pi(); one.Sub(result); return one; } } // namespace auxiliaryfunctions /*! this function calculates the Arc Sine x is from <-1,1> */ template ValueType ASin(ValueType x, ErrorCode * err = 0) { using namespace auxiliaryfunctions; ValueType result, one; one.SetOne(); bool change_sign = false; if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; } if( x.GreaterWithoutSignThan(one) ) { if( err ) *err = err_improper_argument; return result; // NaN is set by default } if( x.IsSign() ) { change_sign = true; x.Abs(); } one.exponent.SubOne(); // =0.5 // asin(-x) = -asin(x) if( x.GreaterWithoutSignThan(one) ) result = ASin_1(x); else result = ASin_0(x); if( change_sign ) result.ChangeSign(); if( err ) *err = err_ok; return result; } /*! this function calculates the Arc Cosine we're using the formula: acos(x) = pi/2 - asin(x) */ template ValueType ACos(const ValueType & x, ErrorCode * err = 0) { ValueType temp; temp.Set05Pi(); temp.Sub(ASin(x, err)); return temp; } namespace auxiliaryfunctions { /*! an auxiliary function for calculating the Arc Tangent arc tan (x) where x is in <0; 0.5) (x can be in (-0.5 ; 0.5) too) we're using the Taylor series expanded in zero: atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ... */ template ValueType ATan0(const ValueType & x) { ValueType nominator, denominator, nominator_add, denominator_add, temp; ValueType result, old_result; bool adding = false; uint c = 0; result = x; old_result = result; nominator = x; nominator_add = x; nominator_add.Mul(x); denominator.SetOne(); denominator_add = 2; for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) { c += nominator.Mul(nominator_add); c += denominator.Add(denominator_add); temp = nominator; c += temp.Div(denominator); if( c ) // the result should be ok break; if( adding ) result.Add(temp); else result.Sub(temp); if( result == old_result ) // there's no sense to calculate more break; old_result = result; adding = !adding; } return result; } /*! an auxiliary function for calculating the Arc Tangent where x is in <0 ; 1> */ template ValueType ATan01(const ValueType & x) { ValueType half; half.Set05(); /* it would be better if we chose about sqrt(2)-1=0.41... instead of 0.5 here because as you can see below: when x = sqrt(2)-1 abs(x) = abs( (x-1)/(1+x) ) so when we're calculating values around x then they will be better converged to each other for example if we have x=0.4999 then during calculating ATan0(0.4999) we have to make about 141 iterations but when we have x=0.5 then during calculating ATan0( (x-1)/(1+x) ) we have to make only about 89 iterations (both for Big<3,9>) in the future this 0.5 can be changed */ if( x.SmallerWithoutSignThan(half) ) return ATan0(x); /* x>=0.5 and x<=1 (x can be even smaller than 0.5) y = atac(x) x = tan(y) tan(y-b) = (tan(y)-tab(b)) / (1+tan(y)*tan(b)) y-b = atan( (tan(y)-tab(b)) / (1+tan(y)*tan(b)) ) y = b + atan( (x-tab(b)) / (1+x*tan(b)) ) let b = pi/4 tan(b) = tan(pi/4) = 1 y = pi/4 + atan( (x-1)/(1+x) ) so atac(x) = pi/4 + atan( (x-1)/(1+x) ) when x->1 (x converges to 1) the (x-1)/(1+x) -> 0 and we can use ATan0() function here */ ValueType n(x),d(x),one,result; one.SetOne(); n.Sub(one); d.Add(one); n.Div(d); result = ATan0(n); n.Set05Pi(); n.exponent.SubOne(); // =pi/4 result.Add(n); return result; } /*! an auxiliary function for calculating the Arc Tangent where x > 1 we're using the formula: atan(x) = pi/2 - atan(1/x) for x>0 */ template ValueType ATanGreaterThanPlusOne(const ValueType & x) { ValueType temp, atan; temp.SetOne(); if( temp.Div(x) ) { // if there was a carry here that means x is very big // and atan(1/x) fast converged to 0 atan.SetZero(); } else atan = ATan01(temp); temp.Set05Pi(); temp.Sub(atan); return temp; } } // namespace auxiliaryfunctions /*! this function calculates the Arc Tangent */ template ValueType ATan(ValueType x) { using namespace auxiliaryfunctions; ValueType one, result; one.SetOne(); bool change_sign = false; if( x.IsNan() ) return x; // if x is negative we're using the formula: // atan(-x) = -atan(x) if( x.IsSign() ) { change_sign = true; x.Abs(); } if( x.GreaterWithoutSignThan(one) ) result = ATanGreaterThanPlusOne(x); else result = ATan01(x); if( change_sign ) result.ChangeSign(); return result; } /*! this function calculates the Arc Tangent look at the description of ATan(...) (the abbreviation of Arc Tangent can be 'atg' as well) */ template ValueType ATg(const ValueType & x) { return ATan(x); } /*! this function calculates the Arc Cotangent we're using the formula: actan(x) = pi/2 - atan(x) */ template ValueType ACot(const ValueType & x) { ValueType result; result.Set05Pi(); result.Sub(ATan(x)); return result; } /*! this function calculates the Arc Cotangent look at the description of ACot(...) (the abbreviation of Arc Cotangent can be 'actg' as well) */ template ValueType ACtg(const ValueType & x) { return ACot(x); } /* * * hyperbolic functions * * */ /*! this function calculates the Hyperbolic Sine we're using the formula sinh(x)= ( e^x - e^(-x) ) / 2 */ template ValueType Sinh(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType ex, emx; uint c = 0; c += ex.Exp(x); c += emx.Exp(-x); c += ex.Sub(emx); c += ex.exponent.SubOne(); if( err ) *err = c ? err_overflow : err_ok; return ex; } /*! this function calculates the Hyperbolic Cosine we're using the formula cosh(x)= ( e^x + e^(-x) ) / 2 */ template ValueType Cosh(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType ex, emx; uint c = 0; c += ex.Exp(x); c += emx.Exp(-x); c += ex.Add(emx); c += ex.exponent.SubOne(); if( err ) *err = c ? err_overflow : err_ok; return ex; } /*! this function calculates the Hyperbolic Tangent we're using the formula tanh(x)= ( e^x - e^(-x) ) / ( e^x + e^(-x) ) */ template ValueType Tanh(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType ex, emx, nominator, denominator; uint c = 0; c += ex.Exp(x); c += emx.Exp(-x); nominator = ex; c += nominator.Sub(emx); denominator = ex; c += denominator.Add(emx); c += nominator.Div(denominator); if( err ) *err = c ? err_overflow : err_ok; return nominator; } /*! this function calculates the Hyperbolic Tangent look at the description of Tanh(...) (the abbreviation of Hyperbolic Tangent can be 'tgh' as well) */ template ValueType Tgh(const ValueType & x, ErrorCode * err = 0) { return Tanh(x, err); } /*! this function calculates the Hyperbolic Cotangent we're using the formula coth(x)= ( e^x + e^(-x) ) / ( e^x - e^(-x) ) */ template ValueType Coth(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } if( x.IsZero() ) { if( err ) *err = err_improper_argument; return ValueType(); // NaN is set by default } ValueType ex, emx, nominator, denominator; uint c = 0; c += ex.Exp(x); c += emx.Exp(-x); nominator = ex; c += nominator.Add(emx); denominator = ex; c += denominator.Sub(emx); c += nominator.Div(denominator); if( err ) *err = c ? err_overflow : err_ok; return nominator; } /*! this function calculates the Hyperbolic Cotangent look at the description of Coth(...) (the abbreviation of Hyperbolic Cotangent can be 'ctgh' as well) */ template ValueType Ctgh(const ValueType & x, ErrorCode * err = 0) { return Coth(x, err); } /* * * inverse hyperbolic functions * * */ /*! inverse hyperbolic sine asinh(x) = ln( x + sqrt(x^2 + 1) ) */ template ValueType ASinh(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType xx(x), one, result; uint c = 0; one.SetOne(); c += xx.Mul(x); c += xx.Add(one); one.exponent.SubOne(); // one=0.5 // xx is >= 1 c += xx.PowFrac(one); // xx=sqrt(xx) c += xx.Add(x); c += result.Ln(xx); // xx > 0 // here can only be a carry if( err ) *err = c ? err_overflow : err_ok; return result; } /*! inverse hyperbolic cosine acosh(x) = ln( x + sqrt(x^2 - 1) ) x in <1, infinity) */ template ValueType ACosh(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType xx(x), one, result; uint c = 0; one.SetOne(); if( x < one ) { if( err ) *err = err_improper_argument; return result; // NaN is set by default } c += xx.Mul(x); c += xx.Sub(one); // xx is >= 0 // we can't call a PowFrac when the 'x' is zero // if x is 0 the sqrt(0) is 0 if( !xx.IsZero() ) { one.exponent.SubOne(); // one=0.5 c += xx.PowFrac(one); // xx=sqrt(xx) } c += xx.Add(x); c += result.Ln(xx); // xx >= 1 // here can only be a carry if( err ) *err = c ? err_overflow : err_ok; return result; } /*! inverse hyperbolic tangent atanh(x) = 0.5 * ln( (1+x) / (1-x) ) x in (-1, 1) */ template ValueType ATanh(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType nominator(x), denominator, one, result; uint c = 0; one.SetOne(); if( !x.SmallerWithoutSignThan(one) ) { if( err ) *err = err_improper_argument; return result; // NaN is set by default } c += nominator.Add(one); denominator = one; c += denominator.Sub(x); c += nominator.Div(denominator); c += result.Ln(nominator); c += result.exponent.SubOne(); // here can only be a carry if( err ) *err = c ? err_overflow : err_ok; return result; } /*! inverse hyperbolic tantent */ template ValueType ATgh(const ValueType & x, ErrorCode * err = 0) { return ATanh(x, err); } /*! inverse hyperbolic cotangent acoth(x) = 0.5 * ln( (x+1) / (x-1) ) x in (-infinity, -1) or (1, infinity) */ template ValueType ACoth(const ValueType & x, ErrorCode * err = 0) { if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; // NaN } ValueType nominator(x), denominator(x), one, result; uint c = 0; one.SetOne(); if( !x.GreaterWithoutSignThan(one) ) { if( err ) *err = err_improper_argument; return result; // NaN is set by default } c += nominator.Add(one); c += denominator.Sub(one); c += nominator.Div(denominator); c += result.Ln(nominator); c += result.exponent.SubOne(); // here can only be a carry if( err ) *err = c ? err_overflow : err_ok; return result; } /*! inverse hyperbolic cotantent */ template ValueType ACtgh(const ValueType & x, ErrorCode * err = 0) { return ACoth(x, err); } /* * * functions for converting between degrees, radians and gradians * * */ /*! this function converts degrees to radians it returns: x * pi / 180 */ template ValueType DegToRad(const ValueType & x, ErrorCode * err = 0) { ValueType result, temp; uint c = 0; if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; } result = x; // it is better to make division first and then multiplication // the result is more accurate especially when x is: 90,180,270 or 360 temp = 180; c += result.Div(temp); temp.SetPi(); c += result.Mul(temp); if( err ) *err = c ? err_overflow : err_ok; return result; } /*! this function converts radians to degrees it returns: x * 180 / pi */ template ValueType RadToDeg(const ValueType & x, ErrorCode * err = 0) { ValueType result, delimiter; uint c = 0; if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; } result = 180; c += result.Mul(x); delimiter.SetPi(); c += result.Div(delimiter); if( err ) *err = c ? err_overflow : err_ok; return result; } /*! this function converts degrees in the long format into one value long format: (degrees, minutes, seconds) minutes and seconds must be greater than or equal zero result: if d>=0 : result= d + ((s/60)+m)/60 if d<0 : result= d - ((s/60)+m)/60 ((s/60)+m)/60 = (s+60*m)/3600 (second version is faster because there's only one division) for example: DegToDeg(10, 30, 0) = 10.5 DegToDeg(10, 24, 35.6)=10.4098(8) */ template ValueType DegToDeg( const ValueType & d, const ValueType & m, const ValueType & s, ErrorCode * err = 0) { ValueType delimiter, multipler; uint c = 0; if( d.IsNan() || m.IsNan() || s.IsNan() || m.IsSign() || s.IsSign() ) { if( err ) *err = err_improper_argument; delimiter.SetZeroNan(); // not needed, only to get rid of GCC warning about an uninitialized variable return delimiter; } multipler = 60; delimiter = 3600; c += multipler.Mul(m); c += multipler.Add(s); c += multipler.Div(delimiter); if( d.IsSign() ) multipler.ChangeSign(); c += multipler.Add(d); if( err ) *err = c ? err_overflow : err_ok; return multipler; } /*! this function converts degrees in the long format to radians */ template ValueType DegToRad( const ValueType & d, const ValueType & m, const ValueType & s, ErrorCode * err = 0) { ValueType temp_deg = DegToDeg(d,m,s,err); if( err && *err!=err_ok ) return temp_deg; return DegToRad(temp_deg, err); } /*! this function converts gradians to radians it returns: x * pi / 200 */ template ValueType GradToRad(const ValueType & x, ErrorCode * err = 0) { ValueType result, temp; uint c = 0; if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; } result = x; // it is better to make division first and then multiplication // the result is more accurate especially when x is: 100,200,300 or 400 temp = 200; c += result.Div(temp); temp.SetPi(); c += result.Mul(temp); if( err ) *err = c ? err_overflow : err_ok; return result; } /*! this function converts radians to gradians it returns: x * 200 / pi */ template ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0) { ValueType result, delimiter; uint c = 0; if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; } result = 200; c += result.Mul(x); delimiter.SetPi(); c += result.Div(delimiter); if( err ) *err = c ? err_overflow : err_ok; return result; } /*! this function converts degrees to gradians it returns: x * 200 / 180 */ template ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0) { ValueType result, temp; uint c = 0; if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; } result = x; temp = 200; c += result.Mul(temp); temp = 180; c += result.Div(temp); if( err ) *err = c ? err_overflow : err_ok; return result; } /*! this function converts degrees in the long format to gradians */ template ValueType DegToGrad( const ValueType & d, const ValueType & m, const ValueType & s, ErrorCode * err = 0) { ValueType temp_deg = DegToDeg(d,m,s,err); if( err && *err!=err_ok ) return temp_deg; return DegToGrad(temp_deg, err); } /*! this function converts degrees to gradians it returns: x * 180 / 200 */ template ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0) { ValueType result, temp; uint c = 0; if( x.IsNan() ) { if( err ) *err = err_improper_argument; return x; } result = x; temp = 180; c += result.Mul(temp); temp = 200; c += result.Div(temp); if( err ) *err = c ? err_overflow : err_ok; return result; } /* * * another functions * * */ /*! this function calculates the square root Sqrt(9) = 3 */ template ValueType Sqrt(ValueType x, ErrorCode * err = 0) { if( x.IsNan() || x.IsSign() ) { if( err ) *err = err_improper_argument; x.SetNan(); return x; } uint c = x.Sqrt(); if( err ) *err = c ? err_overflow : err_ok; return x; } namespace auxiliaryfunctions { template bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err) { if( index.IsSign() ) { // index cannot be negative if( err ) *err = err_improper_argument; x.SetNan(); return true; } return false; } template bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err) { if( index.IsZero() ) { if( x.IsZero() ) { // there isn't root(0;0) - we assume it's not defined if( err ) *err = err_improper_argument; x.SetNan(); return true; } // root(x;0) is 1 (if x!=0) x.SetOne(); if( err ) *err = err_ok; return true; } return false; } template bool RootCheckIndexOne(const ValueType & index, ErrorCode * err) { ValueType one; one.SetOne(); if( index == one ) { //root(x;1) is x // we do it because if we used the PowFrac function // we would lose the precision if( err ) *err = err_ok; return true; } return false; } template bool RootCheckIndexTwo(ValueType & x, const ValueType & index, ErrorCode * err) { if( index == 2 ) { x = Sqrt(x, err); return true; } return false; } template bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err) { if( !index.IsInteger() ) { // index must be integer if( err ) *err = err_improper_argument; x.SetNan(); return true; } return false; } template bool RootCheckXZero(ValueType & x, ErrorCode * err) { if( x.IsZero() ) { // root(0;index) is zero (if index!=0) // RootCheckIndexZero() must be called beforehand x.SetZero(); if( err ) *err = err_ok; return true; } return false; } template bool RootCheckIndex(ValueType & x, const ValueType & index, ErrorCode * err, bool * change_sign) { *change_sign = false; if( index.Mod2() ) { // index is odd (1,3,5...) if( x.IsSign() ) { *change_sign = true; x.Abs(); } } else { // index is even // x cannot be negative if( x.IsSign() ) { if( err ) *err = err_improper_argument; x.SetNan(); return true; } } return false; } template uint RootCorrectInteger(ValueType & old_x, ValueType & x, const ValueType & index) { if( !old_x.IsInteger() || x.IsInteger() || !index.exponent.IsSign() ) return 0; // old_x is integer, // x is not integer, // index is relatively small (index.exponent<0 or index.exponent<=0) // (because we're using a special powering algorithm Big::PowUInt()) uint c = 0; ValueType temp(x); c += temp.Round(); ValueType temp_round(temp); c += temp.PowUInt(index); if( temp == old_x ) x = temp_round; return (c==0)? 0 : 1; } } // namespace auxiliaryfunctions /*! indexth Root of x index must be integer and not negative <0;1;2;3....) if index==0 the result is one if x==0 the result is zero and we assume root(0;0) is not defined if index is even (2;4;6...) the result is x^(1/index) and x>0 if index is odd (1;2;3;...) the result is either -(abs(x)^(1/index)) if x<0 or x^(1/index)) if x>0 (for index==1 the result is equal x) */ template ValueType Root(ValueType x, const ValueType & index, ErrorCode * err = 0) { using namespace auxiliaryfunctions; if( x.IsNan() || index.IsNan() ) { if( err ) *err = err_improper_argument; x.SetNan(); return x; } if( RootCheckIndexSign(x, index, err) ) return x; if( RootCheckIndexZero(x, index, err) ) return x; if( RootCheckIndexOne ( index, err) ) return x; if( RootCheckIndexTwo (x, index, err) ) return x; if( RootCheckIndexFrac(x, index, err) ) return x; if( RootCheckXZero (x, err) ) return x; // index integer and index!=0 // x!=0 ValueType old_x(x); bool change_sign; if( RootCheckIndex(x, index, err, &change_sign ) ) return x; ValueType temp; uint c = 0; // we're using the formula: root(x ; n) = exp( ln(x) / n ) c += temp.Ln(x); c += temp.Div(index); c += x.Exp(temp); if( change_sign ) { // x is different from zero x.SetSign(); } c += RootCorrectInteger(old_x, x, index); if( err ) *err = c ? err_overflow : err_ok; return x; } /*! absolute value of x e.g. -2 = 2 2 = 2 */ template ValueType Abs(const ValueType & x) { ValueType result( x ); result.Abs(); return result; } /*! it returns the sign of the value e.g. -2 = -1 0 = 0 10 = 1 */ template ValueType Sgn(ValueType x) { x.Sgn(); return x; } /*! the remainder from a division e.g. mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6 mod(-12.6 ; 3) = -0.6 bacause -12.6 = 3*(-4) + (-0.6) mod( 12.6 ; -3) = 0.6 mod(-12.6 ; -3) = -0.6 */ template ValueType Mod(ValueType a, const ValueType & b, ErrorCode * err = 0) { if( a.IsNan() || b.IsNan() ) { if( err ) *err = err_improper_argument; a.SetNan(); return a; } uint c = a.Mod(b); if( err ) *err = c ? err_overflow : err_ok; return a; } namespace auxiliaryfunctions { /*! this function is used to store factorials in a given container 'more' means how many values should be added at the end e.g. std::vector fact; SetFactorialSequence(fact, 3); // now the container has three values: 1 1 2 SetFactorialSequence(fact, 2); // now the container has five values: 1 1 2 6 24 */ template void SetFactorialSequence(std::vector & fact, uint more = 20) { if( more == 0 ) more = 1; uint start = static_cast(fact.size()); fact.resize(fact.size() + more); if( start == 0 ) { fact[0] = 1; ++start; } for(uint i=start ; i ValueType SetBernoulliNumbersSum(CGamma & cgamma, const ValueType & n_, uint m, const volatile StopCalculating * stop = 0) { ValueType k_, temp, temp2, temp3, sum; sum.SetZero(); for(uint k=0 ; kWasStopSignal() ) return ValueType(); // NaN if( k>1 && (k & 1) == 1 ) // for that k the Bernoulli number is zero continue; k_ = k; temp = n_; // n_ is equal 2 temp.Pow(k_); // temp = 2^k temp2 = cgamma.fact[m]; temp3 = cgamma.fact[k]; temp3.Mul(cgamma.fact[m-k]); temp2.Div(temp3); // temp2 = (m k) = m! / ( k! * (m-k)! ) temp.Mul(temp2); temp.Mul(cgamma.bern[k]); sum.Add(temp); // sum += 2^k * (m k) * B(k) if( sum.IsNan() ) break; } return sum; } /*! an auxiliary function used to calculate Bernoulli numbers start is >= 2 we use the recurrence formula: B(m) = 1 / (2*(1 - 2^m)) * sum(m) where sum(m) is calculated by SetBernoulliNumbersSum() */ template bool SetBernoulliNumbersMore(CGamma & cgamma, uint start, const volatile StopCalculating * stop = 0) { ValueType denominator, temp, temp2, temp3, m_, sum, sum2, n_, k_; const uint n = 2; n_ = n; // start is >= 2 for(uint m=start ; mWasStopSignal() ) { cgamma.bern.resize(m); // valid numbers are in [0, m-1] return false; } cgamma.bern[m].Div(denominator); } } return true; } /*! this function is used to calculate Bernoulli numbers, returns false if there was a stop signal, 'more' means how many values should be added at the end e.g. typedef Big<1,2> MyBig; CGamma cgamma; SetBernoulliNumbers(cgamma, 3); // now we have three first Bernoulli numbers: 1 -0.5 0.16667 SetBernoulliNumbers(cgamma, 4); // now we have 7 Bernoulli numbers: 1 -0.5 0.16667 0 -0.0333 0 0.0238 */ template bool SetBernoulliNumbers(CGamma & cgamma, uint more = 20, const volatile StopCalculating * stop = 0) { if( more == 0 ) more = 1; uint start = static_cast(cgamma.bern.size()); cgamma.bern.resize(cgamma.bern.size() + more); if( start == 0 ) { cgamma.bern[0].SetOne(); ++start; } if( cgamma.bern.size() == 1 ) return true; if( start == 1 ) { cgamma.bern[1].Set05(); cgamma.bern[1].ChangeSign(); ++start; } // we should have sufficient factorials in cgamma.fact if( cgamma.fact.size() < cgamma.bern.size() ) SetFactorialSequence(cgamma.fact, static_cast(cgamma.bern.size() - cgamma.fact.size())); return SetBernoulliNumbersMore(cgamma, start, stop); } /*! an auxiliary function used to calculate the Gamma() function we calculate a sum: sum(n) = sum_{m=2} { B(m) / ( (m^2 - m) * n^(m-1) ) } = 1/(12*n) - 1/(360*n^3) + 1/(1260*n^5) + ... B(m) means a mth Bernoulli number the sum starts from m=2, we calculate as long as the value will not change after adding a next part */ template ValueType GammaFactorialHighSum(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) { ValueType temp, temp2, denominator, sum, oldsum; sum.SetZero(); for(uint m=2 ; mWasStopSignal() ) { err = err_interrupt; return ValueType(); // NaN } temp = (m-1); denominator = n; denominator.Pow(temp); // denominator = n ^ (m-1) temp = m; temp2 = temp; temp.Mul(temp2); temp.Sub(temp2); // temp = m^2 - m denominator.Mul(temp); // denominator = (m^2 - m) * n ^ (m-1) if( m >= cgamma.bern.size() ) { if( !SetBernoulliNumbers(cgamma, m - cgamma.bern.size() + 1 + 3, stop) ) // 3 more than needed { // there was the stop signal err = err_interrupt; return ValueType(); // NaN } } temp = cgamma.bern[m]; temp.Div(denominator); oldsum = sum; sum.Add(temp); if( sum.IsNan() || oldsum==sum ) break; } return sum; } /*! an auxiliary function used to calculate the Gamma() function we calculate a helper function GammaFactorialHigh() by using Stirling's series: n! = (n/e)^n * sqrt(2*pi*n) * exp( sum(n) ) where n is a real number (not only an integer) and is sufficient large (greater than TTMATH_GAMMA_BOUNDARY) and sum(n) is calculated by GammaFactorialHighSum() */ template ValueType GammaFactorialHigh(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) { ValueType temp, temp2, temp3, denominator, sum; temp.Set2Pi(); temp.Mul(n); temp2 = Sqrt(temp); // temp2 = sqrt(2*pi*n) temp = n; temp3.SetE(); temp.Div(temp3); temp.Pow(n); // temp = (n/e)^n sum = GammaFactorialHighSum(n, cgamma, err, stop); temp3.Exp(sum); // temp3 = exp(sum) temp.Mul(temp2); temp.Mul(temp3); return temp; } /*! an auxiliary function used to calculate the Gamma() function Gamma(x) = GammaFactorialHigh(x-1) */ template ValueType GammaPlusHigh(ValueType n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) { ValueType one; one.SetOne(); n.Sub(one); return GammaFactorialHigh(n, cgamma, err, stop); } /*! an auxiliary function used to calculate the Gamma() function we use this function when n is integer and a small value (from 0 to TTMATH_GAMMA_BOUNDARY] we use the formula: gamma(n) = (n-1)! = 1 * 2 * 3 * ... * (n-1) */ template ValueType GammaPlusLowIntegerInt(uint n, CGamma & cgamma) { TTMATH_ASSERT( n > 0 ) if( n - 1 < static_cast(cgamma.fact.size()) ) return cgamma.fact[n - 1]; ValueType res; uint start = 2; if( cgamma.fact.size() < 2 ) { res.SetOne(); } else { start = static_cast(cgamma.fact.size()); res = cgamma.fact[start-1]; } for(uint i=start ; i ValueType GammaPlusLowInteger(const ValueType & n, CGamma & cgamma) { sint n_; n.ToInt(n_); return GammaPlusLowIntegerInt(n_, cgamma); } /*! an auxiliary function used to calculate the Gamma() function we use this function when n is a small value (from 0 to TTMATH_GAMMA_BOUNDARY] we use a recurrence formula: gamma(z+1) = z * gamma(z) then: gamma(z) = gamma(z+1) / z e.g. gamma(3.89) = gamma(2001.89) / ( 3.89 * 4.89 * 5.89 * ... * 1999.89 * 2000.89 ) */ template ValueType GammaPlusLow(ValueType n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) { ValueType one, denominator, temp, boundary; if( n.IsInteger() ) return GammaPlusLowInteger(n, cgamma); one.SetOne(); denominator = n; boundary = TTMATH_GAMMA_BOUNDARY; while( n < boundary ) { n.Add(one); denominator.Mul(n); } n.Add(one); // now n is sufficient big temp = GammaPlusHigh(n, cgamma, err, stop); temp.Div(denominator); return temp; } /*! an auxiliary function used to calculate the Gamma() function */ template ValueType GammaPlus(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) { if( n > TTMATH_GAMMA_BOUNDARY ) return GammaPlusHigh(n, cgamma, err, stop); return GammaPlusLow(n, cgamma, err, stop); } /*! an auxiliary function used to calculate the Gamma() function this function is used when n is negative we use the reflection formula: gamma(1-z) * gamma(z) = pi / sin(pi*z) then: gamma(z) = pi / (sin(pi*z) * gamma(1-z)) */ template ValueType GammaMinus(const ValueType & n, CGamma & cgamma, ErrorCode & err, const volatile StopCalculating * stop) { ValueType pi, denominator, temp, temp2; if( n.IsInteger() ) { // gamma function is not defined when n is negative and integer err = err_improper_argument; return temp; // NaN } pi.SetPi(); temp = pi; temp.Mul(n); temp2 = Sin(temp); // temp2 = sin(pi * n) temp.SetOne(); temp.Sub(n); temp = GammaPlus(temp, cgamma, err, stop); // temp = gamma(1 - n) temp.Mul(temp2); pi.Div(temp); return pi; } } // namespace auxiliaryfunctions /*! this function calculates the Gamma function it's multithread safe, you should create a CGamma<> object and use it whenever you call the Gamma() e.g. typedef Big<1,2> MyBig; MyBig x=234, y=345.53; CGamma cgamma; std::cout << Gamma(x, cgamma) << std::endl; std::cout << Gamma(y, cgamma) << std::endl; in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers), and they will be reused in next calls to the function each thread should have its own CGamma<> object, and you can use these objects with Factorial() function too */ template ValueType Gamma(const ValueType & n, CGamma & cgamma, ErrorCode * err = 0, const volatile StopCalculating * stop = 0) { using namespace auxiliaryfunctions; ValueType result; ErrorCode err_tmp; if( n.IsNan() ) { if( err ) *err = err_improper_argument; return n; } if( cgamma.history.Get(n, result, err_tmp) ) { if( err ) *err = err_tmp; return result; } err_tmp = err_ok; if( n.IsSign() ) { result = GammaMinus(n, cgamma, err_tmp, stop); } else if( n.IsZero() ) { err_tmp = err_improper_argument; result.SetNan(); } else { result = GammaPlus(n, cgamma, err_tmp, stop); } if( result.IsNan() && err_tmp==err_ok ) err_tmp = err_overflow; if( err ) *err = err_tmp; if( stop && !stop->WasStopSignal() ) cgamma.history.Add(n, result, err_tmp); return result; } /*! this function calculates the Gamma function note: this function should be used only in a single-thread environment */ template ValueType Gamma(const ValueType & n, ErrorCode * err = 0) { // warning: this static object is not thread safe static CGamma cgamma; return Gamma(n, cgamma, err); } namespace auxiliaryfunctions { /*! an auxiliary function for calculating the factorial function we use the formula: x! = gamma(x+1) */ template ValueType Factorial2(ValueType x, CGamma * cgamma = 0, ErrorCode * err = 0, const volatile StopCalculating * stop = 0) { ValueType result, one; if( x.IsNan() || x.IsSign() || !x.IsInteger() ) { if( err ) *err = err_improper_argument; x.SetNan(); return x; } one.SetOne(); x.Add(one); if( cgamma ) return Gamma(x, *cgamma, err, stop); return Gamma(x, err); } } // namespace auxiliaryfunctions /*! the factorial from given 'x' e.g. Factorial(4) = 4! = 1*2*3*4 it's multithread safe, you should create a CGamma<> object and use it whenever you call the Factorial() e.g. typedef Big<1,2> MyBig; MyBig x=234, y=54345; CGamma cgamma; std::cout << Factorial(x, cgamma) << std::endl; std::cout << Factorial(y, cgamma) << std::endl; in the CGamma<> object the function stores some coefficients (factorials, Bernoulli numbers), and they will be reused in next calls to the function each thread should have its own CGamma<> object, and you can use these objects with Gamma() function too */ template ValueType Factorial(const ValueType & x, CGamma & cgamma, ErrorCode * err = 0, const volatile StopCalculating * stop = 0) { return auxiliaryfunctions::Factorial2(x, &cgamma, err, stop); } /*! the factorial from given 'x' e.g. Factorial(4) = 4! = 1*2*3*4 note: this function should be used only in a single-thread environment */ template ValueType Factorial(const ValueType & x, ErrorCode * err = 0) { return auxiliaryfunctions::Factorial2(x, (CGamma*)0, err, 0); } /*! this method prepares some coefficients: factorials and Bernoulli numbers stored in 'fact' and 'bern' objects we're defining the method here because we're using Gamma() function which is not available in ttmathobjects.h read the doc info in ttmathobjects.h file where CGamma<> struct is declared */ template void CGamma::InitAll() { ValueType x = TTMATH_GAMMA_BOUNDARY + 1; // history.Remove(x) removes only one object // we must be sure that there are not others objects with the key 'x' while( history.Remove(x) ) { } // the simplest way to initialize is to call the Gamma function with (TTMATH_GAMMA_BOUNDARY + 1) // when x is larger then fewer coefficients we need Gamma(x, *this); } } // namespace /*! this is for convenience for the user he can only use '#include ' even if he uses the parser */ #include "ttmathparser.h" #ifdef _MSC_VER //warning C4127: conditional expression is constant #pragma warning( default: 4127 ) //warning C4702: unreachable code #pragma warning( default: 4702 ) //warning C4800: forcing value to bool 'true' or 'false' (performance warning) #pragma warning( default: 4800 ) #endif #endif discoSnp/minia/OAHash.h0000644000000000000000000000265712305316340013716 0ustar rootroot#ifndef OAHash_h #define OAHash_h #include #include #include #ifdef _largeint #include "LargeInt.h" typedef LargeInt key_type; #else #ifdef _ttmath #include "ttmath/ttmath.h" typedef ttmath::UInt key_type; #else #if (! defined kmer_type) || (! defined _LP64) typedef uint64_t key_type; #else typedef kmer_type key_type; #endif #endif #endif class OAHash{ protected: struct element_pair { key_type key; //uint32_t value; int32_t value; }; uint64_t hash_size; uint64_t nb_inserted_keys; element_pair* data; #ifdef _largeint inline uint64_t hashcode(LargeInt elem); #endif #ifdef _ttmath inline uint64_t hashcode(ttmath::UInt elem); #endif #ifdef _LP64 uint64_t hashcode( __uint128_t elem); #endif uint64_t hashcode( uint64_t elem); bool is_occupied(element_pair *element); public: static int size_entry(); // iterator functions: element_pair *iterator; void start_iterator(); bool next_iterator(); OAHash(uint64_t max_elements); ~OAHash(); element_pair * find_slot(key_type key); void insert(key_type graine, int value); void increment(key_type graine); bool get( key_type graine, int * val); bool has_key(key_type graine); void printstat(); uint64_t memory_usage(); float load_factor(); }; #endif discoSnp/minia/Kmer.cpp0000644000000000000000000002300612316502726014042 0ustar rootroot#ifndef ASSERTS #define NDEBUG // disable asserts, they're computationnally intensive #endif #include #include #include // for min #include "Kmer.h" #include "lut.h" using namespace std; int sizeKmer; uint64_t nsolids = 0; kmer_type kmerMask; kmer_type kmerMaskm1; int NT2int(char nt) { int i; i = nt; i = (i>>1)&3; // that's quite clever, guillaume. return i; } int revcomp_int(int nt_int) { return (nt_int<2)?nt_int+2:nt_int-2; } unsigned char code4NT(char *seq) { int i; unsigned char x; x=0; for (i=0; i<4; ++i) { x = x*4 + NT2int(seq[i]); } return x; } unsigned char code_n_NT(char *seq, int nb) { int i; unsigned char x; x=0; for (i=0; i> 2) + ( ((kmer_type) comp_NT[NT2int(seq[sizeKmer-1])]) << (2*(sizeKmer-1)) ) ) & kmerMask; } // warning: only call this function for sequential enumeration of kmers (no arbitrary position) kmer_type extractKmerFromRead(char *readSeq, int position, kmer_type *graine, kmer_type *graine_revcomp) { return extractKmerFromRead(readSeq, position, graine, graine_revcomp, true); } kmer_type extractKmerFromRead(char *readSeq, int position, kmer_type *graine, kmer_type *graine_revcomp, bool sequential) { return extractKmerFromRead(readSeq, position, graine, graine_revcomp, sequential, sizeKmer, kmerMask); } kmer_type extractKmerFromRead(char *readSeq, int position, kmer_type *graine, kmer_type *graine_revcomp, bool sequential, int sizeKmer, kmer_type kmerMask) { assert(graine != graine_revcomp); // make sure two different pointers bool new_read = (position == 0) || (!sequential); // faster computation for immediately overlapping kmers *graine = codeSeedRight(&readSeq[position], *graine, new_read, sizeKmer, kmerMask); *graine_revcomp = codeSeedRight_revcomp(&readSeq[position], *graine_revcomp, new_read, sizeKmer, kmerMask); return min(*graine,*graine_revcomp); } int first_nucleotide(kmer_type kmer) { int result; #ifdef _largeint LargeInt t = kmer; result = t.toInt()&3; #else #ifdef _ttmath ttmath::UInt t = kmer&3; t.ToInt(result); #else result = kmer&3; #endif #endif return result; } int code2seq (kmer_type code, char *seq) { return code2seq (code, seq, sizeKmer, kmerMask); } int code2seq (kmer_type code, char *seq, int sizeKmer, kmer_type kmerMask) { int i; kmer_type temp = code; char bin2NT[4] = {'A','C','T','G'}; for (i=sizeKmer-1; i>=0; i--) { seq[i]=bin2NT[first_nucleotide(temp&3)]; temp = temp>>2; } //printf("sizeKmer = %d\n", sizeKmer); seq[sizeKmer]='\0'; return sizeKmer; } // return the i-th nucleotide of the kmer_type kmer int code2nucleotide( kmer_type code, int which_nucleotide) { kmer_type temp = code; temp = temp >> (2*(sizeKmer-1-which_nucleotide)); return first_nucleotide(temp&3); } uint64_t revcomp(uint64_t x, int size) { int i; uint64_t revcomp = x; // printf("x %x revcomp %x \n",x,revcomp); unsigned char * kmerrev = (unsigned char *) (&revcomp); unsigned char * kmer = (unsigned char *) (&x); for (i=0; i<8; ++i) { kmerrev[7-i] = revcomp_4NT[kmer[i]]; } return (revcomp >> (2*( 4*sizeof(uint64_t) - size)) ) ; } uint64_t revcomp(uint64_t x) { return revcomp(x,sizeKmer); } #ifdef _largeint LargeInt revcomp(LargeInt x, int size) { int i; kmer_type revcomp = x; // printf("x %x revcomp %x \n",x,revcomp); unsigned char * kmerrev = (unsigned char *) (&(revcomp.array[0])); unsigned char * kmer = (unsigned char *) (&(x.array[0])); for (i=0; i<8*KMER_PRECISION; ++i) { kmerrev[8*KMER_PRECISION-1-i] = revcomp_4NT[kmer[i]]; } return (revcomp >> (2*( 32*KMER_PRECISION - size)) ) ; } LargeInt revcomp(LargeInt x) { return revcomp(x,sizeKmer); } #endif #ifdef _ttmath ttmath::UInt revcomp(ttmath::UInt x, int size) { int i; kmer_type revcomp = x; // printf("x %x revcomp %x \n",x,revcomp); unsigned char * kmerrev = (unsigned char *) (&revcomp); unsigned char * kmer = (unsigned char *) (&x); for (i=0; i<4*KMER_PRECISION; ++i) { kmerrev[4*KMER_PRECISION-1-i] = revcomp_4NT[kmer[i]]; } return (revcomp >> (2*( 16*KMER_PRECISION - size)) ) ; } ttmath::UInt revcomp(ttmath::UInt x) { return revcomp(x,sizeKmer); } #endif #ifdef _LP64 __uint128_t revcomp(__uint128_t x, int size) { // ---64bits-- ---64bits-- // original kmer: [__high_nucl__|__low_nucl___] // // ex: [ AC | .......TG ] // //revcomp: [ CA | .......GT ] // \_low_nucl__/\high_nucl/ uint64_t high_nucl = (uint64_t)(x>>64); int nb_high_nucl = size>32?size - 32:0; __uint128_t revcomp_high_nucl = revcomp(high_nucl, nb_high_nucl); if (size<=32) revcomp_high_nucl = 0; // srsly dunno why this is needed. gcc bug? uint64_t x ---> (x>>64) != 0 uint64_t low_nucl = (uint64_t)(x&((((__uint128_t)1)<<64)-1)); int nb_low_nucl = size>32?32:size; __uint128_t revcomp_low_nucl = revcomp(low_nucl, nb_low_nucl); return (revcomp_low_nucl<<(2*nb_high_nucl)) + revcomp_high_nucl; } __uint128_t revcomp(__uint128_t x) { return revcomp(x,sizeKmer); } #endif // will be used by assemble() void revcomp_sequence(char s[], int len) { #define CHAR_REVCOMP(a,b) {switch(a){\ case 'A': b='T';break;case 'C': b='G';break;case 'G': b='C';break;case 'T': b='A';break;default: b=a;break;}} int i; unsigned char t; for (i=0;i> 2 ) + ( ((kmer_type)added_nt) << ((sizeKmer-1)*2)) ) & kmerMask; // previous kmer kmer_type revcomp_new_graine = revcomp(new_graine); if (strand != NULL) *strand = (new_graine < revcomp_new_graine)?0:1; return min(new_graine,revcomp_new_graine); } //////////////////////////funcs for binary reads kmer_type codeSeed_bin(char *seq) { int i; kmer_type x; x=0; for (i=0; i> 2) + ( ((kmer_type) comp_NT[(int)(seq[sizeKmer-1])]) << (2*(sizeKmer-1)) ) ) & kmerMask; } kmer_type extractKmerFromRead_bin(char *readSeq, int position, kmer_type *graine, kmer_type *graine_revcomp, bool use_compressed) { assert(graine != graine_revcomp); // make sure two different pointers bool new_read = (position == 0); if(!use_compressed) { *graine = codeSeedRight(&readSeq[position], *graine, new_read); *graine_revcomp = codeSeedRight_revcomp(&readSeq[position], *graine_revcomp, new_read); } else { *graine = codeSeedRight_bin(&readSeq[position], *graine, new_read); *graine_revcomp = codeSeedRight_revcomp_bin(&readSeq[position], *graine_revcomp, new_read); } return min(*graine,*graine_revcomp); } // debug only: convert a kmer_type to char* char debug_kmer_buffer[1024]; char* print_kmer(kmer_type kmer) { return print_kmer(kmer,sizeKmer,kmerMask); } char* print_kmer(kmer_type kmer, int sizeKmer, kmer_type kmerMask) { code2seq(kmer,debug_kmer_buffer, sizeKmer, kmerMask); return debug_kmer_buffer; } discoSnp/minia/Bank.h0000644000000000000000000001157512305316340013465 0ustar rootroot// // Bank.h // // Created by Guillaume Rizk on 28/11/11. // Modified by Rayan Chikhi on 16/2/13 // #ifndef Bank_h #define Bank_h #include #include "Kmer.h" #include // Added by Pierre Peterlongo on 02/08/2012. #define TAILLE_NOM 1024 #define MAX_NB_FILES 2000 #define BUFFER_SIZE 16384 // same as kseq.h #define WRITE_BUFFER 32768// 16384 //800000 #define KMERSBUFFER_MAX_READLEN 4096 // grows dynamically if needed #define BINREADS_BUFFER 100000 off_t fsize(const char *filename) ; // heavily inspired by kseq.h from Heng Li (https://github.com/attractivechaos/klib) typedef struct { gzFile stream; unsigned char *buffer; int buffer_start, buffer_end; bool eof; char last_char; char *fname; uint64_t estimated_filesize; } buffered_file_t; typedef struct { int length ,max; char *string; } variable_string_t; // supports opening multiple fasta/fastq files class Bank{ public: Bank(char *fname); Bank(char **fname, int nb_files_); void init(char **fname, int nb_files_); void close(); bool get_next_seq(char **nseq, int *len); bool get_next_seq_from_file(char **nseq, int *len, int file_id); bool get_next_seq_from_file(char **nseq, char **cheader, int *len, int *hlen, int file_id); bool get_next_seq(char **nseq, char **cheader, int *len, int *hlen); bool get_next_seq(char **nseq, char **cheader, int *len, int *hlen, int * id_file);//also return file id bool get_next_seq(char **nseq, int *len, int * id_file); //also return file id void open_stream(int i); // internal functions void close_stream(int i); void rewind_all(); variable_string_t *read, *dummy, *header; int nb_files; // total nb of files int index_file; // index of current file uint64_t filesizes; // estimate of total size for all files signed int buffered_gets(buffered_file_t *bf, variable_string_t *s, char *dret, bool append, bool allow_spaces); ~Bank(); uint64_t estimate_kmers_volume(int k); uint64_t estimate_nb_reads(); int estimate_max_readlen(); // functions that enable to read the same portion twice void save_position(); void load_position(); int restore_index_file; z_off_t restore_pos; buffered_file_t **buffered_file; }; class BinaryBank { protected: char filename[TAILLE_NOM]; FILE * binary_read_file; const int sizeElement; void * buffer; int cpt_buffer; int cpt_init_buffer; int buffer_size_nelem; public: BinaryBank(char *filename, int sizeElement, bool write); BinaryBank (); void write_element(void *element); size_t read_element(void *element); size_t read_element_buffered(void *element); void write( void *element, int size); void write_element_buffered(void *element); size_t read( void *element, int size); void rewind_all(); void close(); void open(bool write); off_t nb_elements(); ~BinaryBank(); }; class BinaryBankConcurrent : public BinaryBank { int * cpt_buffer_tid; // this counter is now in bytes int nthreads ; void * bufferT; public: BinaryBankConcurrent(char *given_filename, int given_sizeElement, bool write, int given_nthreads) ; void write_element_buffered(void *element, int tid); void write_buffered( void *element, int size, int tid); void write_buffered( void *element, int size, int tid, bool can_flush); void flush(int tid); void close(); ~BinaryBankConcurrent(); }; class BinaryReads { char filename[TAILLE_NOM]; // const int sizeElement; unsigned char * buffer; int cpt_buffer; unsigned int read_write_buffer_size; public: FILE * binary_read_file; BinaryReads(char *filename, bool write); // void write_element(void *element); //size_t read_element(void *element); void write_read(char * read, int readlen); void rewind_all(); void close(); void open(bool write); void mark_newfile(); ~BinaryReads(); }; class KmersBuffer { char * buffer; int cpt_buffer; int blocksize_toread; unsigned int read_write_buffer_size; int cpt_binSeq_read; int binSeq_toread; public: int max_read_length; BinaryReads * binfile; FILE * binary_read_file; int nkmers; //number of kmers in the buffer int nseq_step; int buffer_size; kmer_type * kmers_buffer; KmersBuffer(BinaryReads *bfile, int pbuffer_size, int nseq_task ); int readkmers(); char * binSeq;// [MAX_READ_LENGTH]; char * binSeq_extended;//[MAX_READ_LENGTH]; void reset_max_readlen(int read_length); ~KmersBuffer(); }; void compute_kmer_table_from_one_seq(int readlen, char * seq, kmer_type * kmer_table ) ; #endif discoSnp/minia/SortingCount.cpp0000644000000000000000000007220012424137004015573 0ustar rootroot#include "SortingCount.h" #include "inttypes.h" #include // for getrlimit() #if OMP #include "omp.h" #endif #define SINGLE_BAR 1 #define SEP bool clear_cache = false; // clear file cache from memory (for timing only) bool hybrid_mode = false; bool use_hashing = true; // use hashing instead of sorting (better control of memory) float load_factor = 0.7; bool separate_count = true ; // count separately the multiple read sets, only works with use_hashing, needs define SEP and use_hashing=true bool use_compressed_reads = true ; // true; // write compressed read file int optimism = 1; // optimism == 1 mean that we garantee worst case the memory usage, any value above assumes that, on average, a k-mer will be seen 'optimism' times bool output_histo; // main k-mer counting function, shared between minia and dsk // verbose == 0 : stderr progress bar // verbose >= 1 : print basic status // verbose >= 2 : print extra partition information // write_count == True: include kmer count in results file, in that form: // - save kmer count for each kmer in the resulting binary file // - the very first four bytes of the result file are the kmer length void sorting_count(Bank *Sequences, char *prefix, int max_memory, int max_disk_space, bool write_count, int verbose, bool skip_binary_conversion) { // create a temp dir from the prefix char temp_dir[1024]; sprintf(temp_dir,"%s_temp",prefix); // clear the temp folder (needs to be done before estimating disk space) DIR* dp; struct dirent* ep; char p_buf[512] = {0}; dp = opendir(temp_dir); while ( (dp != NULL) && ((ep = readdir(dp)) != NULL)) { sprintf(p_buf, "%s/%s", temp_dir, ep->d_name); remove(p_buf); } if(dp != NULL) closedir(dp); if (max_disk_space == 0) { // default max disk space struct statvfs buffer ; char current_path[1000]; getcwd(current_path,sizeof(current_path)); // int ret = statvfs(current_path, &buffer); uint32_t available = (uint32_t)(((double)buffer.f_bavail * (double)buffer.f_bsize) / 1024.0 / 1024.0); printf("Available disk space in %s: %d MB\n",current_path,available); // not working in osx (is that a TODO then?) uint32_t input_size = max(1, (int)(( (double)(Sequences->filesizes) ) / 1024.0 / 1024.0)); max_disk_space = min(available/2, input_size); } if (max_disk_space == 0) // still 0? max_disk_space = 10000; // = default for osx // estimate number of iterations uint64_t volume = Sequences->estimate_kmers_volume(sizeKmer); uint32_t nb_passes = ( volume / max_disk_space ) + 1; int nb_threads=1; #if OMP use_compressed_reads = true; nb_threads = 8; max_memory /= nb_threads; max_memory = max (max_memory,1); #endif // temp bugfix: don't use compressed reads for long reads if (Sequences->estimate_max_readlen() > 1000000) use_compressed_reads = false; uint64_t volume_per_pass; uint32_t nb_partitions; // loop to lower the number of partitions below the maximum number of simulatenously open files do { volume_per_pass = volume / nb_passes; nb_partitions = ( volume_per_pass / max_memory ) + 1; // if partitions are hashed instead of sorted, adjust for load factor // (as in the worst case, all kmers in the partition are distinct and partition may be slightly bigger due to hash-repartition) if (use_hashing) { nb_partitions = (uint32_t) ceil((float) nb_partitions / load_factor); nb_partitions = ((nb_partitions * OAHash::size_entry()) + sizeof(key_type)-1) / sizeof(key_type); // also adjust for hash overhead nb_partitions = max((int)(nb_partitions/optimism), 1); if (verbose) printf("Updated number of partitions for hash-based k-mer counting: %d\n",nb_partitions); } // round nb_partitions to mulitple of nthreads, for better perf // nb_partitions = ((nb_partitions + nb_threads - 1) / nb_threads) * nb_threads; if (verbose) printf("Estimate of number of partitions: %d, number of passes: %d\n",nb_partitions, nb_passes); // get max number of open files struct rlimit lim; int max_open_files = 1000; int err = getrlimit(RLIMIT_NOFILE, &lim); if (err == 0) max_open_files = lim.rlim_cur / 2; if (nb_partitions >= max_open_files) { if (verbose) printf("Number of partitions higher than max. number of open files (%d), need to increase the number of passes\n", max_open_files); nb_passes++; } else break; } while (1); // volume / (sizeof(kmer_type)*4) is approx size of read file stored in binary, read nb_passes -1 times uint64_t total_IO = volume * 2LL * 1024LL*1024LL ;// in bytes + nb_passes * ( volume / (sizeof(kmer_type)*4) ) ; // in bytes uint64_t temp_IO = 0; //if (nb_passes==1) use_compressed_reads=false; BinaryBankConcurrent * redundant_partitions_file[nb_partitions]; char redundant_filename[nb_partitions][256]; kmer_type kmer; int max_read_length = KMERSBUFFER_MAX_READLEN; kmer_type * kmer_table_seq = (kmer_type * ) malloc(sizeof(kmer_type)*max_read_length); ; fprintf(stderr,"Sequentially counting ~%llu MB of kmers with %d partition(s) and %d passes using %d thread(s), ~%d MB of memory and ~%d MB of disk space\n", (unsigned long long)volume, nb_partitions,nb_passes, nb_threads, max_memory * nb_threads, max_disk_space); STARTWALL(count); mkdir(temp_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); BinaryBankConcurrent * SolidKmers = new BinaryBankConcurrent(return_file_name(solid_kmers_file),sizeof(kmer),true,nb_threads); if (write_count) { // write k-mer nbits as the first 4 bytes; and actual k-mer size as the next 4 bits uint32_t kmer_nbits = sizeof(kmer) * 8; SolidKmers->write_buffered(&kmer_nbits, 4,0); SolidKmers->write_buffered(&sizeKmer, 4,0); SolidKmers->flush(0); } int64_t estimated_NbReads = Sequences->estimate_nb_reads(); // only used in progress prints char * rseq; int readlen; int64_t NbSolid = 0; int64_t * NbSolid_omp = (int64_t *) calloc(nb_threads,sizeof(int64_t)); #ifdef SEP long total_kmers_per_partition[nb_partitions]; //guillaume probably commented it because updating this variable would require synchronization for (int jj=0; jjclose(); } if(use_compressed_reads && (!skip_binary_conversion)) { char * pt_begin; int idx =0 ; int64_t NbRead = 0; Progress progress_conversion; // progress_conversion.timer_mode=1; // to switch to timer mode (show elapsed and estimated remaining time) progress_conversion.init(estimated_NbReads,"First step: Converting input file into Binary format"); binread = new BinaryReads(return_file_name(binary_read_file),true); #ifdef SEP int file_id =0; int prev_file_id =0; #endif Sequences->rewind_all(); while(1) { #ifdef SEP if(! Sequences->get_next_seq(&rseq,&readlen,&file_id)) break; // read original fasta file if(separate_count && (file_id != prev_file_id)) { //printf("new file \n"); prev_file_id = file_id; binread->mark_newfile(); } #else if(! Sequences->get_next_seq(&rseq,&readlen)) break; // read original fasta file #endif if(readlen > max_read_length) // realloc kmer_table_seq if needed { max_read_length = 2*readlen; kmer_table_seq = (kmer_type * ) realloc(kmer_table_seq,sizeof(kmer_type)*max_read_length); } pt_begin = rseq; //should be ok while (pt_begin < (rseq+ readlen)) { idx=0; // start a new read //skips NN while (*pt_begin =='N' && pt_begin < (rseq+ readlen)) { pt_begin ++; } // goes to next N or end of seq while ( (pt_begin[idx] !='N') && ((pt_begin +idx) < (rseq+ readlen)) ) { idx++; } //we have a seq beginning at pt_begin of size idx ,without any N, will be treated as a read: binread->write_read(pt_begin,idx); pt_begin += idx; } // binread->write_read(rseq,readlen); NbRead++; if ((NbRead%10000)==0) { progress_conversion.inc(10000); } } progress_conversion.finish(); binread->close(); } ///fin conversion if (clear_cache) { #ifdef OSX system("purge"); #else system("echo 3 > /proc/sys/vm/drop_caches"); #endif } #if SINGLE_BAR Progress progress; char message[1000]; sprintf(message,"Counting kmers"); progress.timer_mode=1; if (verbose == 0 ) progress.init(total_IO,message); #endif // nb_passes = how many times we will traverse the whole reads file (has an influence on temp disk space) for (uint32_t current_pass = 0; current_pass < nb_passes; current_pass ++) { #ifdef SEP if(separate_count) { for (int jj=0; jjopen(false); STARTWALL(debpass); STARTWALL(debw); for (uint32_t p=0;prewind_all(); #if !SINGLE_BAR Progress progress; progress.timer_mode=1; // to switch to timer mode (show elapsed and estimated remaining time) char message[1000]; sprintf(message,"Pass %d/%d, Step 1: partitioning",current_pass+1,nb_passes); if (verbose == 0 ) progress.init(estimated_NbReads,message); #endif int file_id=0; //current_pass> 0 && #if OMP #pragma omp parallel if(use_compressed_reads && ! separate_count) num_threads(nb_threads) #endif { int64_t nbkmers_written =0; int tid =0; int64_t NbRead = 0; int64_t nread =0; int64_t tempread =0; #if OMP tid = omp_get_thread_num(); #endif int nreads_in_buffer= 1000; KmersBuffer * kbuff =NULL; if(use_compressed_reads) { kbuff = new KmersBuffer (binread, 1000000, nreads_in_buffer); //buffer size (in nb of kmers), seq per task // the buffer is per thread kbuff->binary_read_file = binread->binary_read_file; } kmer_type * kmer_table ; while(1) { //read the fasta file if(use_compressed_reads) // && current_pass>0 { nread = kbuff->readkmers(); #ifdef SEP if(separate_count && (nread == -2)) { //printf("New file notified, filling parti\n"); for (int kk=0; kk< nb_partitions; kk++) { kmers_perparti_perfile[kk][file_id] = total_kmers_per_partition [kk]; //printf(".. total_kmers_per_partition[%i] = %li\n",kk, total_kmers_per_partition [kk]); } file_id++; continue; } #endif if(nread < 0) break; NbRead+= nread; tempread+= nread; } else { if(! Sequences->get_next_seq(&rseq,&readlen)) break; // read original fasta file if(readlen > max_read_length) // realloc kmer_table_seq if needed { max_read_length = 2*readlen; kmer_table_seq = (kmer_type * ) realloc(kmer_table_seq,sizeof(kmer_type)*max_read_length); } } // if(use_compressed_reads ) //write compressed read file at first pass //&& current_pass==0 // binread->write_read(rseq,readlen); int i; int nbkmers =readlen-sizeKmer+1; if( use_compressed_reads) //current_pass >0 && { nbkmers = kbuff->nkmers; kmer_table = kbuff->kmers_buffer; // printf("nb kmers read %lli \n",nbkmers); // NbRead+= nreads_in_buffer; } else //old fashion { compute_kmer_table_from_one_seq(readlen,rseq,kmer_table_seq); nbkmers =readlen-sizeKmer+1; kmer_table = kmer_table_seq; NbRead++; } //printf("Encountering empty block \n"); nbkmers_written= 0; //compute the kmers stored in the buffer kmer_table for (i=0; i> 14); kmer_hash = (~kmer_hash) + (kmer_hash << 18); kmer_hash = kmer_hash ^ (kmer_hash >> 31); kmer_hash = kmer_hash * 21; kmer_hash = kmer_hash ^ (kmer_hash >> 11); kmer_hash = kmer_hash + (kmer_hash << 6); kmer_hash = kmer_hash ^ (kmer_hash >> 22); // check if this kmer should be included in the current pass if ((kmer_hash % nb_passes ) != current_pass) continue; kmer_type reduced_kmer = kmer_hash / nb_passes; int p;// compute in which partition this kmer falls into #ifdef _ttmath (reduced_kmer % nb_partitions).ToInt(p); #else p = reduced_kmer % nb_partitions; #endif nbkmers_written++; redundant_partitions_file[p]->write_element_buffered(&lkmer,tid); // save this kmer to the right partition file #ifdef SEP if(separate_count) total_kmers_per_partition[p]++; // guillaume probably commented it because updating this variable would require synchronization #endif } //NbRead++; #if SINGLE_BAR if(verbose==0) { if (nb_threads == 1) progress.inc(nbkmers_written * sizeof(kmer_type)); else progress.inc(nbkmers_written * sizeof(kmer_type),tid); } #endif // if ((NbRead%10000)==0) if(tempread> 10000) { tempread -= 10000; if (verbose) fprintf (stderr,"%cPass %d/%d, loop through reads to separate (redundant) kmers into partitions, processed %lluM reads out of %lluM",13,current_pass+1,nb_passes,(unsigned long long)(NbRead/1000/1000),(unsigned long long)(estimated_NbReads/1000/1000)); #if !SINGLE_BAR else if (nb_threads == 1) progress.set(NbRead); else progress.inc(10000,tid); #endif } } //end while if(use_compressed_reads) delete kbuff; } // end OMP #if !SINGLE_BAR if (verbose == 0) { if (nb_threads == 1) progress.finish(); else progress.finish_threaded(); // here only one thread sprintf(message,"Pass %d/%d, Step 2: computing kmer count per partition",current_pass+1,nb_passes); progress.init(nb_partitions+1,message); } #endif if (verbose)fprintf(stderr,"\n"); if (verbose >= 2) { STOPWALL(debw,"Writing redundant kmers"); } STARTWALL(debtri); // close partitions and open them for reading for (uint32_t p=0;pclose(); redundant_partitions_file[p]->open(false); } // for better timing: clear the file cache, since the partitions may still be in memory, that's unfair to low mem machines if (clear_cache) { #ifdef OSX system("purge"); #else system("echo 3 > /proc/sys/vm/drop_caches"); #endif } //quick and dirty parall with omp, testing //todo if we want omp and histo : separate histo_count tab per thread that needs to be merged at the end // TODO to guillaume: remove that todo above, because it is done, right? #if OMP //omp_set_numthreads(2); //num_threads(2) //if(!output_histo) num_threads(nb_threads) #pragma omp parallel for if (! separate_count) private (p) num_threads(nb_threads) #endif // load, sort each partition to output solid kmers for (int p=0;pnb_elements()*sizeof(kmer_type))/1024LL/1024LL); if( (redundant_partitions_file[p]->nb_elements()*sizeof(kmer_type)) < (max_memory*1024LL*1024LL) ) use_hashing_for_this_partition = false; else use_hashing_for_this_partition = true; } int tid =0; #if OMP tid = omp_get_thread_num(); #endif if (use_hashing_for_this_partition) { // hash partition and save to solid file OAHash hash(max_memory*1024LL*1024LL); uint64_t nkmers_read=0; uint64_t nkmers_read_all=0; file_id = 0; while (redundant_partitions_file[p]->read_element_buffered (&lkmer)) { hash.increment(lkmer); nkmers_read++; #ifdef SEP nkmers_read_all++; if( separate_count && (kmers_perparti_perfile[p][file_id]==nkmers_read_all)) { //printf("Parsing parti .. detected end of file %i at %lli parti %i \n",file_id,nkmers_read_all,p); file_id++; //faire raz des cpts < seuil de la hash, devrait etre suffisant ... hash.start_iterator(); while (hash.next_iterator()) { if (hash.iterator->value < nks) { hash.iterator->value = -1 ; // 0 is not valid in oahash, emulate it with -1 } } } #endif #if SINGLE_BAR if(verbose==0 && nkmers_read==10000) { if (nb_threads == 1) progress.inc(nkmers_read*sizeof(kmer_type)); else progress.inc(nkmers_read*sizeof(kmer_type),tid); nkmers_read=0; } #endif } //single bar if (verbose >= 2) printf("Pass %d/%d partition %d/%d hash load factor: %0.3f\n",current_pass+1,nb_passes,p+1,nb_partitions,hash.load_factor()); hash.start_iterator(); while (hash.next_iterator()) { #ifdef SEP int value = hash.iterator->value; if(value==-1) value = 0; // desemulate -1 uint_abundance_t abundance = value; #else uint_abundance_t abundance = hash.iterator->value; #endif if(output_histo) { uint_abundance_t saturated_abundance; saturated_abundance = (abundance >= 10000) ? 10000 : abundance; #if OMP histo_count_omp[tid][saturated_abundance]++; #else //printf("histo_count 0 1 2 %i %i %i \n",histo_count[0],histo_count[1],histo_count[2]); histo_count[saturated_abundance]++; #endif } if (abundance >= nks && abundance <= max_couv) { SolidKmers->write_element_buffered(&(hash.iterator->key),tid); NbSolid_omp[tid]++; if (write_count) SolidKmers->write_buffered(&abundance, sizeof(abundance),tid, false); } distinct_kmers_per_partition[p]++; } } else { // sort partition and save to solid file vector < kmer_type > kmers; uint64_t nkmers_read=0; while (redundant_partitions_file[p]->read_element_buffered (&lkmer)) { kmers.push_back (lkmer); nkmers_read++; #if SINGLE_BAR if(verbose==0 && nkmers_read==10000) { if (nb_threads == 1) progress.inc(nkmers_read*sizeof(kmer_type)); else progress.inc(nkmers_read*sizeof(kmer_type),tid); nkmers_read=0; } #endif } sort (kmers.begin (), kmers.end ()); kmer_type previous_kmer = *(kmers.begin ()); uint_abundance_t abundance = 0; for (vector < kmer_type >::iterator it = kmers.begin (); it != kmers.end (); it++) { kmer_type current_kmer = *it; if (current_kmer == previous_kmer) abundance++; else { if(output_histo) { uint_abundance_t saturated_abundance; saturated_abundance = (abundance >= 10000) ? 10000 : abundance; #if OMP histo_count_omp[tid][saturated_abundance]++; #else histo_count[saturated_abundance]++; #endif } if (abundance >= nks && abundance <= max_couv) { NbSolid_omp[tid]++; SolidKmers->write_element_buffered(&previous_kmer,tid); if (write_count) SolidKmers->write_buffered(&abundance, sizeof(abundance),tid, false); } abundance = 1; distinct_kmers_per_partition[p]++; } previous_kmer = current_kmer; } //last kmer distinct_kmers_per_partition[p]++; if(output_histo) { uint_abundance_t saturated_abundance; saturated_abundance = (abundance >= 10000) ? 10000 : abundance; #if OMP histo_count_omp[tid][saturated_abundance]++; #else histo_count[saturated_abundance]++; #endif } if (abundance >= nks && abundance <= max_couv) { NbSolid_omp[tid]++; SolidKmers->write_element_buffered(&previous_kmer,tid); if (write_count) SolidKmers->write_buffered(&abundance, sizeof(abundance),tid, false); } } if (verbose >= 1) fprintf(stderr,"%cPass %d/%d, loaded and sorted partition %d/%d, found %lld solid kmers so far",13,current_pass+1,nb_passes,p+1,nb_partitions,(long long)(NbSolid_omp[tid])); if (verbose >= 2) printf("\nPass %d/%d partition %d/%d %ld distinct kmers\n",current_pass+1,nb_passes,p+1,nb_partitions,/*total_kmers_per_partition[p],*/distinct_kmers_per_partition[p]); #if !SINGLE_BAR if (verbose == 0 && nb_threads==1) progress.inc(1); else if (verbose == 0 && nb_threads>1) progress.inc(1,tid); #endif redundant_partitions_file[p]->close(); remove(redundant_filename[p]); } // end for partitions #if OMP //merge histo if(output_histo) { for (int cc=1; cc<10001; cc++) { uint64_t sum_omp = 0; for(int ii=0;ii 1 ) progress.finish_threaded(); #endif if (verbose) fprintf(stderr,"\n"); if (verbose >= 2) { STOPWALL(debtri,"Reading and sorting partitions"); STOPWALL(debpass,"Pass total"); } if(use_compressed_reads) binread->close(); //delete for (uint32_t p=0;p 1 ) progress.finish_threaded(); #endif if(output_histo) { FILE * histo_file = fopen(return_file_name(histo_file_name),"w"); for (int cc=1; cc<10001; cc++) { fprintf(histo_file,"%i\t%llu\n",cc,(unsigned long long)(histo_count[cc])); } fclose(histo_file); } free(histo_count); NbSolid = NbSolid_omp[0]; #if OMP NbSolid=0; for(int ii=0;iiclose(); printf("\nSaved %lld solid kmers\n",(long long)NbSolid); rmdir(temp_dir); STOPWALL(count,"Counted kmers"); fprintf(stderr,"\n------------------ Counted kmers and kept those with abundance >=%i, \n",nks); } discoSnp/minia/Pool.h0000644000000000000000000000313312062133074013513 0ustar rootroot// // Pool.h // memory pool for hashtable to avoid mallocs // // Created by Guillaume Rizk on 24/11/11. // #ifndef compress_Pool_h #define compress_Pool_h #include #include // for max/min #ifdef _ttmath #include "ttmath/ttmath.h" #endif #ifdef _largeint #include "LargeInt.h" #endif typedef unsigned int cell_ptr_t; template struct cell { graine_type graine; cell_ptr_t suiv; int val; }; #define TAI_POOL 4194304 //16777216//4194304 // 2^22 16 M cells *16 o blocs de 256 Mo #define N_POOL 1024 //256//1024 // 2^10 soit 4 G cells max /** * \class Pool, * \brief Cette class dÈfinit une pool memoire pour allocation rapide de la table de hachage utilisee quand seed >14 */ template class Pool{ public: /** * table de cell, pour usage courant, */ cell * pool_courante; /** * stockage de tous les pointeurs pool */ cell ** tab_pool; /** * nombre de piscines remplies */ unsigned int n_pools; /** * niveau de remplissage de la piscine courante */ unsigned int n_cells; /** * Constructeur par dÈfaut */ Pool(); /** * alloue une cellule dans la piscine */ cell * allocate_cell_in_pool(); // allocate cell, return internal pointer type ( 32bits) cell_ptr_t allocate_cell(); cell * internal_ptr_to_cell_pointer(cell_ptr_t internal_ptr); /** * vide toutes piscines * (garde juste une pool vide) */ void empty_all(); /** * Destructeur */ ~Pool(); }; #endif discoSnp/minia/LargeInt.cpp0000644000000000000000000001732712126546644014670 0ustar rootroot#ifndef ASSERTS #define NDEBUG // disable asserts; those asserts make sure that with PRECISION == [1 or 2], all is correct #endif // some 64-bit assert macros #if defined(_LP64) && defined(_largeint) #define assert128(x) assert(precision != 2 || (x)); #else #define assert128(x) ; #endif #include #include #include "LargeInt.h" using namespace std; template LargeInt::LargeInt() { } template LargeInt::LargeInt(const uint64_t &c) { array[0] = c; for (int i = 1; i < precision; i++) array[i] = 0; } template LargeInt LargeInt::operator+ (const LargeInt& other) const { LargeInt result; int carry = 0; for (int i = 0 ; i < precision ; i++) { result.array[i] = array[i] + other.array[i] + carry; carry = (result.array[i] < array[i]) ? 1 : 0; } assert(precision != 1 || (result == other.array[0] + array[0])); assert128(result.toInt128() == other.toInt128() + toInt128()); return result; } template LargeInt LargeInt::operator- (const LargeInt& other) const { LargeInt result; int carry = 0; for (int i = 0 ; i < precision ; i++) { result.array[i] = array[i] - other.array[i] - carry; carry = (result.array[i] > array[i]) ? 1 : 0; } assert(precision != 1 || (result == array[0] - other.array[0])); assert128(result.toInt128() == toInt128() - other.toInt128()); return result; } template LargeInt LargeInt::operator* (const int& coeff) const { LargeInt result (*this); // minia doesn't have that many multiplications cases if (coeff == 2 || coeff == 4) { result = result << (coeff / 2); } else { if (coeff == 21) { result = (result << 4) + (result << 2) + result; } else { printf("unsupported LargeInt multiplication: %d\n",coeff); exit(1); } } assert(precision != 1 || (result == array[0] * coeff)); assert128(result.toInt128() == toInt128() * coeff); return result; } template LargeInt LargeInt::operator/ (const uint32_t& divisor) const { LargeInt result; fill( result.array, result.array + precision, 0 ); // inspired by Divide32() from http://subversion.assembla.com/svn/pxcode/RakNet/Source/BigInt.cpp uint64_t r = 0; uint32_t mask32bits = ~0; for (int i = precision-1; i >= 0; --i) { for (int j = 1; j >= 0; --j) // [j=1: high-32 bits, j=0: low-32 bits] of array[i] { uint64_t n = (r << 32) | ((array[i] >> (32*j)) & mask32bits ); result.array[i] = result.array[i] | (((n / divisor) & mask32bits) << (32*j)); r = n % divisor; } } assert(precision != 1 || (result == array[0] / divisor)); assert128(result.toInt128() == toInt128() / divisor); return result; } template uint32_t LargeInt::operator% (const uint32_t& divisor) const { uint64_t r = 0; uint32_t mask32bits = ~0; for (int i = precision-1; i >= 0; --i) { for (int j = 1; j >= 0; --j) // [j=1: high-32 bits, j=0: low-32 bits] of array[i] { uint64_t n = (r << 32) | ((array[i] >> (32*j)) & mask32bits ); r = n % divisor; } } assert(precision != 1 || (r == array[0] % divisor)); assert128(r == toInt128() % divisor); return (uint32_t)r; } template LargeInt LargeInt::operator^ (const LargeInt& other) const { LargeInt result; for (int i=0 ; i < precision ; i++) result.array[i] = array[i] ^ other.array[i]; assert(precision != 1 || (result == (array[0] ^ other.array[0]))); assert128(result.toInt128() == (toInt128() ^ other.toInt128())); return result; } template LargeInt LargeInt::operator& (const LargeInt& other) const { LargeInt result; for (int i=0 ; i < precision ; i++) result.array[i] = array[i] & other.array[i]; assert(precision != 1 || (result == (array[0] & other.array[0]))); assert128(result.toInt128() == (toInt128() & other.toInt128())); return result; } template LargeInt LargeInt::operator~ () const { LargeInt result; for (int i=0 ; i < precision ; i++) result.array[i] = ~array[i]; assert(precision != 1 || (result == ~array[0])); assert128(result.toInt128() == ~toInt128()); return result; } template LargeInt LargeInt::operator<< (const int& coeff) const { LargeInt result (0); int large_shift = coeff / 64; int small_shift = coeff % 64; for (int i = large_shift ; i < precision-1; i++) { result.array[i] = result.array[i] | (array[i-large_shift] << small_shift); if (small_shift == 0) // gcc "bug".. uint64_t x; x>>64 == 1<<63, x<<64 == 1 result.array[i+1] = 0; else result.array[i+1] = array[i-large_shift] >> (64 - small_shift); } result.array[precision-1] = result.array[precision-1] | (array[precision-1-large_shift] << small_shift); assert(precision != 1 || (result == (array[0] << coeff))); assert128(result.toInt128() == (toInt128() << coeff)); return result; } template LargeInt LargeInt::operator>> (const int& coeff) const { LargeInt result (0); int large_shift = coeff / 64; int small_shift = coeff % 64; result.array[0] = (array[large_shift] >> small_shift); for (int i = 1 ; i < precision - large_shift ; i++) { result.array[i] = (array[i+large_shift] >> small_shift); if (small_shift == 0 && large_shift > 0) // gcc "bug".. uint64_t x; x>>64 == 1<<63, x<<64 == 1 { result.array[i-1] = result.array[i-1]; } else { result.array[i-1] = result.array[i-1] | (array[i+large_shift] << (64 - small_shift)); } } assert(precision != 1 || ( small_shift == 0 || (result == array[0] >> coeff))); assert128(small_shift == 0 || (result.toInt128() == (toInt128() >> coeff))); return result; } template bool LargeInt::operator!= (const LargeInt& c) const { for (int i = 0 ; i < precision ; i++) if( array[i] != c.array[i] ) return true; return false; } template bool LargeInt::operator== (const LargeInt& c) const { for (int i = 0 ; i < precision ; i++) if( array[i] != c.array[i] ) return false; return true; } template bool LargeInt::operator< (const LargeInt& c) const { for (int i = precision-1 ; i>=0 ; --i) if( array[i] != c.array[i] ) return array[i] < c.array[i]; return false; } template bool LargeInt::operator<=(const LargeInt& c) const { return operator==(c) || operator<(c); } template uint64_t LargeInt::toInt() const { return array[0]; } #ifdef _LP64 template __uint128_t LargeInt::toInt128() const { return ((__uint128_t)array[0]) + (((__uint128_t)array[1]) << ((__uint128_t)64)); } #endif #ifdef KMER_PRECISION template class LargeInt; // since we didn't define the functions in a .h file, that trick removes linker errors, see http://www.parashift.com/c++-faq-lite/separate-template-class-defn-from-decl.html #endif discoSnp/minia/Pool.cpp0000644000000000000000000000655512062133074014061 0ustar rootroot// // Pool.cpp // memory pool for hashtable to avoid mallocs // // Created by Guillaume Rizk on 24/11/11. // #include #include #include "Pool.h" #include /** * Constructeur par dÈfaut */ template Pool::Pool() { n_pools = 0; n_cells=0; //allocation table de pool : tab_pool = (cell**) malloc(N_POOL*sizeof(cell *) ); tab_pool[0]=NULL;n_pools++; // la premiere pool est NULL, pour conversion null_internal -> null //allocation de la premiere pool : pool_courante =(cell*) malloc(TAI_POOL*sizeof(cell) ); tab_pool[n_pools] = pool_courante; n_pools++; } /** * Destructeur */ template Pool::~Pool() { unsigned int i; for(i=1;i void Pool::empty_all() { unsigned int i; for(i=2;i cell * Pool::internal_ptr_to_cell_pointer(cell_ptr_t internal_ptr) { unsigned int numpool = internal_ptr & 1023; unsigned int numcell = internal_ptr >> 10; return (tab_pool[numpool] + numcell); } template cell_ptr_t Pool::allocate_cell() { cell_ptr_t internal_adress = 0; // ncells = nb de cells deja utilisees if (n_cells = N_POOL) { fprintf(stderr,"Internal memory allocator is full!\n"); return 0; // will happen when 4G cells are allocated, representing 64 Go } pool_courante =(cell*) malloc(TAI_POOL*sizeof(cell) ); tab_pool[n_pools] = pool_courante; n_pools++; n_cells = 1; internal_adress = n_pools -1; // low 8 bits : pool number // 22 high bits are 0 return internal_adress; } } // trick to avoid linker errors: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.15 template class Pool; #ifdef _LP64 template class Pool<__uint128_t>; #endif #ifdef _ttmath template class Pool >; #endif #ifdef _largeint template class Pool >; #endif discoSnp/minia/MultiConsumer.h0000644000000000000000000000273112126546644015427 0ustar rootroot#include #include #include #include #include #include #ifndef MultiConsumer_H #define MultiConsumer_H using namespace std; #define NB_PACKETS 5 #define MAX_NUCL_IN_PACKET 10000000 template class MultiConsumer { Task *buffer[NB_PACKETS]; int maxSizeBuffer; pthread_mutex_t *mutex; pthread_mutex_t *mutex2; pthread_cond_t *notFull; pthread_cond_t *notEmpty; bool allDone; public: int sizeBuffer; MultiConsumer(); void produce(Task *task); Task *consume(); void setAllDone(); bool isAllDone(); }; // a producer that group reads struct reads_packet { vector reads; }; class MultiReads { protected: reads_packet *current_packet; int packetOffset; int nbRead; int nbNucleotides; int thread_id; void new_packet(); public: MultiConsumer *mc; MultiReads(int thread_id); void produce(char *read, int readlen); void setAllDone(); }; // a consumer for the above producer class MultiReadsConsumer { reads_packet *current_packet; int packetOffset; int nbRead; int thread_id; bool has_packet; MultiConsumer *mc; public: MultiReadsConsumer(MultiReads m, int thread_id) : has_packet(false), mc(m.mc), current_packet(NULL), thread_id(thread_id) {} bool is_finished_packet(); void consume(char* &read, int &readlen); }; #endif discoSnp/minia/Terminator.cpp0000644000000000000000000003241612365451556015305 0ustar rootroot// // Terminator.cpp // #ifndef ASSERTS #define NDEBUG // disable asserts, they're computationnally intensive #endif #include #include #include #include #include #include // for max #include "Terminator.h" #include "Traversal.h" // for extensions() using namespace::std; bool Terminator::verbose = true; // common terminator functions (actually, more like Kmer64 + bloom + debloom) // we define a structure 2x4 bits which indicates which nucleotides correspond to in- and out-branching of a kmer // let's see an example (bidirected debruijn graph): // // ACT [G] -\/-> [C] CAG [T] <-- [C] CCA // --- X --- --- //[C] AGT -/\- > [A] CTG [G] --> TGG [G] // // structure for the node CAG/CTG: (forward:)0010(reverse:)0001 (the order is ACTG); T forward (to the right) and G reverse (to the right) unsigned char Terminator::branching_structure(kmer_type graine) { assert(graine<=revcomp(graine)); kmer_type new_graine; unsigned char result = 0; int nt; int strand; for(nt=0; nt<4; nt++) { // forward right extensions strand=0; new_graine = next_kmer(graine,nt,&strand); if(bloom_solid_kmers->contains(new_graine) && !debloom->contains(new_graine)){ result|=1<contains(new_graine) && !debloom->contains(new_graine)){ result|=1<<(nt+4); } } return result; } // determines if a kmer is branching or not bool Terminator::is_branching(kmer_type graine) { assert(graine<=revcomp(graine)); // method specific to order=0 (remember that order>0 is never used) if (order == 0) { // cannot really be optimized, because most kmers will be non-branching, hence computing branching_structure() takes optimal time int nb_forward_links = 0, nb_reverse_links = 0; int i; unsigned char branching = branching_structure(graine); for (i=0;i<4;i++) nb_forward_links += (branching>>i)&1; for (i=4;i<8;i++) nb_reverse_links += (branching>>i)&1; return !(nb_forward_links == 1 && nb_reverse_links == 1); } else { if (order==1 && is_tip(graine,bloom_solid_kmers,debloom))// algo fixme-order>0: order=1, tips are ignored as branching kmers. should find a more general code for order>1 return false; // any order>=0: check that this node really yields a true branching, as opposed to branching yielding tips for (int strand=0;strand<2;strand++) { int osef; int nb_extensions = traversal_extensions(graine,strand,osef, bloom_solid_kmers, debloom); if (nb_extensions != 1) return true; } } return false; } // [branching kmers]-based terminator // most kmers should have 1 in-neighbor and 1 out-neighbor // this terminator indexes all the other kmers (ie., branching or dead-end kmers) // it will miss circular regions tho.. // mark a kmer (the kmer has to be a branching kmer or a neighbor of one, else no effect) void BranchingTerminator::mark(kmer_type graine) { assert(graine<=revcomp(graine)); bool could_mark = false; // if it is a branching kmer, mark it directly (it may have no branching neighbor) if (is_indexed(graine)) { set_value_t val; branching_kmers->get(graine,&val); branching_kmers->set(graine,val|(1<<8)); could_mark = true; } // enumerate all the neighbors for (int strand=0; strand < 2; strand++) { for(int nt=0; nt<4; nt++) { // test if the neighbor is a branching kmer int neighbor_strand = strand; kmer_type neighbor = next_kmer(graine,nt,&neighbor_strand); if( (!bloom_solid_kmers->contains(neighbor)) || debloom->contains(neighbor) ) continue; if (!is_indexed(neighbor)) continue; // mark the kmer in that neighbor int revStrand ; int revNT; revStrand = 1-neighbor_strand; if (strand == 0) revNT = revcomp_int(code2nucleotide(graine,0)); else revNT = code2nucleotide(graine,sizeKmer-1); mark(neighbor,revNT,revStrand); could_mark = true; } } if (could_mark) assert(is_marked(graine)); } // record info into a branching kmer void BranchingTerminator::mark(kmer_type graine, char nt, int strand) { assert(nt<4); assert(strand<2); assert(graine<=revcomp(graine)); // BranchingTerminator ignores non-branching kmers if (!is_indexed(graine)) return; //int val = 0; set_value_t val=0; branching_kmers->get(graine,&val); // set a 1 at the right NT & strand position if (strand==0) val|=1<<(nt); else val|=1<<(nt+4); // printf ("mark, graine = %llx val: %x branching structure: %x\n",graine,val,branching_structure(graine)); branching_kmers->set(graine,val); //was insert for Hash16 assert(is_marked(graine,nt,strand)); } // test if a kmer is marked, providing that the kmer is a branching kmer or a neighbor of one (else, considered unmarked) bool BranchingTerminator::is_marked(kmer_type graine) { assert(graine<=revcomp(graine)); // if it is a branching kmer, read marking directly (it may have no branching neighbor) if (is_indexed(graine)) return is_marked_branching(graine); // enumerate all the neighbors for (int strand=0; strand < 2; strand++) { for(int nt=0; nt<4; nt++) { // test if the neighbor is a branching kmer int neighbor_strand = strand; kmer_type neighbor = next_kmer(graine,nt,&neighbor_strand); if( (!bloom_solid_kmers->contains(neighbor)) || debloom->contains(neighbor) ) continue; if ( !is_indexed(neighbor) ) continue; // test the kmer w.r.t that neighbor int revStrand ; int revNT; revStrand = 1-neighbor_strand; if (strand == 0) revNT = revcomp_int(code2nucleotide(graine,0)); else revNT = code2nucleotide(graine,sizeKmer-1); if ( is_marked(neighbor,revNT,revStrand) ) return true; } } return false; } // test if a branching kmer is marked (using the special marker for branching kmers only) bool BranchingTerminator::is_marked_branching(kmer_type graine) { assert(graine<=revcomp(graine)); assert(is_branching(graine)); assert(is_indexed(graine)); set_value_t val; branching_kmers->get(graine,&val); return (val&(1<<8)) != 0; } // that function returns false for non-indexed kmers bool BranchingTerminator::is_marked(kmer_type graine, char nt, int strand) { assert(nt<4); assert(strand<2); assert(graine<=revcomp(graine)); set_value_t val = 0; int is_present = branching_kmers->get(graine,&val); if (!is_present) return false; //printf ("is_marked, graine = %llx val: %x branching structure: %x\n",graine,val,branching_structure(graine)); int extension_nucleotide_marked; if (strand==0) extension_nucleotide_marked = (val>>nt)&1; else extension_nucleotide_marked = (val>>(nt+4))&1; return extension_nucleotide_marked == 1; } bool BranchingTerminator::is_indexed(kmer_type graine) { return branching_kmers->contains(graine); } BranchingTerminator::BranchingTerminator(BinaryBank *given_SolidKmers, uint64_t genome_size, Bloom *given_bloom, Set *given_debloom) : Terminator(given_SolidKmers,given_bloom,given_debloom) { // estimate, from the first million of kmers, the number of branching kmers, extrapolating given the estimated genome size // TODO: erwan noticed that this code isn't useful anymore with AssocSet, feel free to remove it sometimes uint64_t nb_extrapolation = 3000000; SolidKmers->rewind_all(); uint64_t nb_kmers = 0; nb_branching_kmers = 0; kmer_type kmer; uint64_t previous_estimated_nb_branching_kmers, estimated_nb_branching_kmers; while (SolidKmers->read_element(&kmer)) { if (is_branching(kmer)) nb_branching_kmers++; if ((nb_branching_kmers%1000)==0 && nb_branching_kmers>0) { previous_estimated_nb_branching_kmers = estimated_nb_branching_kmers; estimated_nb_branching_kmers = (uint64_t)((1.0*nb_branching_kmers)/nb_kmers * genome_size); // minor todo: stop when previous_.. - estimated < threshold (pourquoi pas = 10% estimated) fprintf (stderr,"%cExtrapolating the number of branching kmers from the first %dM kmers: %lld",13,(int)ceilf(nb_extrapolation/1024.0/1024.0),estimated_nb_branching_kmers); } if (nb_kmers++ == nb_extrapolation) break; } estimated_nb_branching_kmers = (uint64_t)((1.0*nb_branching_kmers)/nb_kmers * genome_size); // final estimation int estimated_NBITS_TERMINATOR = max( (int)ceilf(log2f(estimated_nb_branching_kmers)), 1); fprintf (stderr,"\n"); // call Hash16 constructor // branching_kmers = new Hash16(estimated_NBITS_TERMINATOR); branching_kmers = new AssocSet(); // index, once and for all, all the branching solid kmers SolidKmers->rewind_all(); nb_branching_kmers = 0; uint64_t nb_solid_kmers = 0; while (SolidKmers->read_element(&kmer)) { if (is_branching(kmer)) { // branching_kmers->insert(kmer,0); branching_kmers->insert(kmer); nb_branching_kmers++; } nb_solid_kmers++; if ((nb_branching_kmers%500)==0) fprintf (stderr,"%cIndexing branching kmers %lld / ~%lld",13,nb_branching_kmers,estimated_nb_branching_kmers); } if (nb_branching_kmers == 0) printf("\n**** Warning\n\nNo branching kmers were found in this dataset (it is either empty or a tiny circular genome) - Minia will not assemble anything.\n\n****\n\n"); branching_kmers->finalize(); // branching_kmers->print_total_size(); // fprintf (stderr,"\n\nAllocated memory for marking: %lld branching kmers x (%lu+%lu) B \n",nb_branching_kmers,sizeof(kmer_type),sizeof(set_value_t)); // fprintf (stderr," actual implementation: (sizeof(kmer_type) = %lu B) + (sizeof(set_value_t) = %lu B) per entry: %.2f bits / solid kmer\n",sizeof(kmer_type),sizeof(set_value_t),(nb_branching_kmers*((sizeof(kmer_type)+sizeof(set_value_t))*8.0))/nb_solid_kmers); // init branching_kmers iterator for what happens next branching_kmers->start_iterator(); } // constructor that simply loads a dump of branching kmers BranchingTerminator::BranchingTerminator(BinaryBank *branchingKmers, BinaryBank *given_SolidKmers, Bloom *given_bloom, Set *given_debloom) : Terminator(given_SolidKmers,given_bloom,given_debloom) { nb_branching_kmers = branchingKmers->nb_elements(); int NBITS_TERMINATOR = max( (int)ceilf(log2f(nb_branching_kmers)), 1); // call Hash16 constructor // branching_kmers = new Hash16(NBITS_TERMINATOR); branching_kmers = new AssocSet(); // load branching kmers branchingKmers->rewind_all(); kmer_type kmer; while (branchingKmers->read_element(&kmer)) branching_kmers->insert(kmer); //,0 for Hash16 branching_kmers->finalize(); if (verbose) fprintf (stderr,"\nLoaded %lld branching kmers x %lu B = %.1f MB\n",nb_branching_kmers,sizeof(cell),((1<)*1.0)/1024.0/1024.0); // init branching_kmers iterator for what happens next branching_kmers->start_iterator(); } BranchingTerminator::~BranchingTerminator() { delete branching_kmers; } bool BranchingTerminator::next(kmer_type *kmer) { if (branching_kmers->next_iterator()) { //*kmer = branching_kmers->iterator.cell_ptr->graine; //for Hash16 *kmer = *(branching_kmers->iterator); return true; } return false; } void BranchingTerminator::dump_branching_kmers(BinaryBank *BranchingKmers) { // init branching_kmers iterator for what happens next branching_kmers->start_iterator(); while (branching_kmers->next_iterator()) { //kmer_type kmer = branching_kmers->iterator.cell_ptr->graine;//for Hash16 kmer_type kmer = *( branching_kmers->iterator); BranchingKmers->write_element(&kmer); } fprintf (stderr,"Dumped branching kmers\n"); } // reset all marking information: everything is now unmarked void BranchingTerminator::reset() { branching_kmers->clear(); } //-------------------------------------------------------- // bloom-based terminator (untested, totally unused) BloomTerminator::BloomTerminator(int tai_Bloom) { bloo2 = new Bloom(tai_Bloom); // to mark kmers already used for assembly ... taille a changer } void BloomTerminator::mark(kmer_type graine, char nt, int strand) { bloo2->add(graine); } bool BloomTerminator::is_marked(kmer_type graine, char nt, int strand) { return bloo2->contains(graine); } bool BloomTerminator::is_fully_marked(kmer_type graine) { return is_marked(graine,0,0); } bool BloomTerminator::next(kmer_type *kmer) { return SolidKmers->read_element(kmer); } discoSnp/minia/LICENSE0000644000000000000000000005433112062133074013444 0ustar rootroot FREE SOFTWARE LICENSING AGREEMENT CeCILL ======================================== Notice ------ This Agreement is a free software license that is the result of discussions between its authors in order to ensure compliance with the two main principles guiding its drafting: - firstly, its conformity with French law, both as regards the law of torts and intellectual property law, and the protection that it offers to authors and the holders of economic rights over software. - secondly, compliance with the principles for the distribution of free software: access to source codes, extended user-rights. The following bodies are the authors of this license CeCILL (Ce : CEA, C : CNRS, I : INRIA, LL : Logiciel Libre): Commissariat à l'Energie Atomique - CEA, a public scientific, technical and industrial establishment, having its principal place of business at 31-33 rue de la Fédération, 75752 PARIS cedex 15, France. Centre National de la Recherche Scientifique - CNRS, a public scientific and technological establishment, having its principal place of business at 3 rue Michel-Ange 75794 Paris cedex 16, France. Institut National de Recherche en Informatique et en Automatique - INRIA, a public scientific and technological establishment, having its principal place of business at Domaine de Voluceau, Rocquencourt, BP 105, 78153 Le Chesnay cedex. PREAMBLE -------- The purpose of this Free Software Licensing Agreement is to grant users the right to modify and redistribute the software governed by this license within the framework of an "open source" distribution model. The exercising of these rights is conditional upon certain obligations for users so as to ensure that this status is retained for subsequent redistribution operations. As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors only have limited liability. In this respect, it is brought to the user's attention that the risks associated with loading, using, modifying and/or developing or reproducing the software by the user given its nature of Free Software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the Software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions of security. This Agreement may be freely reproduced and published, provided it is not altered, and that no Articles are either added or removed herefrom. This Agreement may apply to any or all software for which the holder of the economic rights decides to submit the operation thereof to its provisions. Article 1 - DEFINITIONS ------------------------ For the purposes of this Agreement, when the following expressions commence with a capital letter, they shall have the following meaning: Agreement: means this Licensing Agreement, and any or all of its subsequent versions. Software: means the software in its Object Code and/or Source Code form and, where applicable, its documentation, "as is" at the time when the Licensee accepts the Agreement. Initial Software: means the Software in its Source Code and/or Object Code form and, where applicable, its documentation, "as is" at the time when it is distributed for the first time under the terms and conditions of the Agreement. Modified Software: means the Software modified by at least one Contribution. Source Code: means all the Software's instructions and program lines to which access is required so as to modify the Software. Object Code: means the binary files originating from the compilation of the Source Code. Holder: means the holder of the economic rights over the Initial Software. Licensee(s): mean(s) the Software user(s) having accepted the Agreement. Contributor: means a Licensee having made at least one Contribution. Licensor: means the Holder, or any or all other individual or legal entity, that distributes the Software under the Agreement. Contributions: mean any or all modifications, corrections, translations, adaptations and/or new functionalities integrated into the Software by any or all Contributor, and the Static Modules. Module: means a set of sources files including their documentation that, once compiled in executable form, enables supplementary functionalities or services to be developed in addition to those offered by the Software. Dynamic Module: means any or all module, created by the Contributor, that is independent of the Software, so that this module and the Software are in two different executable forms that are run in separate address spaces, with one calling the other when they are run. Static Module: means any or all module, created by the Contributor and connected to the Software by a static link that makes their object codes interdependent. This module and the Software to which it is connected, are combined in a single executable. Parties: mean both the Licensee and the Licensor. These expressions may be used both in singular and plural form. Article 2 - PURPOSE ------------------- The purpose of the Agreement is to enable the Licensor to grant the Licensee a free, non-exclusive, transferable and worldwide License for the Software as set forth in Article 5 hereinafter for the whole term of protection of the rights over said Software. Article 3 - ACCEPTANCE ---------------------- 3.1. The Licensee shall be deemed as having accepted the terms and conditions of this Agreement by the occurrence of the first of the following events: - (i) loading the Software by any or all means, notably, by downloading from a remote server, or by loading from a physical medium; - (ii) the first time the Licensee exercises any of the rights granted hereunder. 3.2. One copy of the Agreement, containing a notice relating to the specific nature of the Software, to the limited warranty, and to the limitation to use by experienced users has been provided to the Licensee prior to its acceptance as set forth in Article 3.1 hereinabove, and the Licensee hereby acknowledges that it is aware thereof. Article 4 - EFFECTIVE DATE AND TERM ----------------------------------- 4.1. EFFECTIVE DATE The Agreement shall become effective on the date when it is accepted by the Licensee as set forth in Article 3.1. 4.2. TERM The Agreement shall remain in force during the whole legal term of protection of the economic rights over the Software. Article 5 - SCOPE OF THE RIGHTS GRANTED --------------------------------------- The Licensor hereby grants to the Licensee, that accepts such, the following rights as regards the Software for any or all use, and for the term of the Agreement, on the basis of the terms and conditions set forth hereinafter. Otherwise, the Licensor grants to the Licensee free of charge exploitation rights on the patents he holds on whole or part of the inventions implemented in the Software. 5.1. RIGHTS OF USE The Licensee is authorized to use the Software, unrestrictedly, as regards the fields of application, with it being hereinafter specified that this relates to: - permanent or temporary reproduction of all or part of the Software by any or all means and in any or all form. - loading, displaying, running, or storing the Software on any or all medium. - entitlement to observe, study or test the operation thereof so as to establish the ideas and principles that form the basis for any or all constituent elements of said Software. This shall apply when the Licensee carries out any or all loading, displaying, running, transmission or storage operation as regards the Software, that it is entitled to carry out hereunder. 5.2. entitlement to make CONTRIBUTIONS The right to make Contributions includes the right to translate, adapt, arrange, or make any or all modification to the Software, and the right to reproduce the resulting Software. The Licensee is authorized to make any or all Contribution to the Software provided that it explicitly mentions its name as the author of said Contribution and the date of the development thereof. 5.3. DISTRIBUTION AND PUBLICATION RIGHTS In particular, the right of distribution and publication includes the right to transmit and communicate the Software to the general public on any or all medium, and by any or all means, and the right to market, either in consideration of a fee, or free of charge, a copy or copies of the Software by means of any or all process. The Licensee is further authorized to redistribute copies of the modified or unmodified Software to third parties according to the terms and conditions set forth hereinafter. 5.3.1. REDISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION The Licensee is authorized to redistribute true copies of the Software in Source Code or Object Code form, provided that said redistribution complies with all the provisions of the Agreement and is accompanied by: - a copy of the Agreement, - a notice relating to the limitation of both the Licensor's warranty and liability as set forth in Articles 8 and 9, and that, in the event that only the Software's Object Code is redistributed, the Licensee allows future Licensees unhindered access to the Software's full Source Code by providing them with the terms and conditions for access thereto, it being understood that the additional cost of acquiring the Source Code shall not exceed the cost of transferring the data. 5.3.2. REDISTRIBUTION OF MODIFIED SOFTWARE When the Licensee makes a Contribution to the Software, the terms and conditions for the redistribution of the Modified Software shall then be subject to all the provisions hereof. The Licensee is authorized to redistribute the Modified Software, in Source Code or Object Code form, provided that said redistribution complies with all the provisions of the Agreement and is accompanied by: - a copy of the Agreement, - a notice relating to the limitation of both the Licensor's warranty and liability as set forth in Articles 8 and 9, and that, in the event that only the Modified Software's Object Code is redistributed, the Licensee allows future Licensees unhindered access to the Modified Software's full Source Code by providing them with the terms and conditions for access thereto, it being understood that the additional cost of acquiring the Source Code shall not exceed the cost of transferring the data. 5.3.3. redistribution OF DYNAMIC MODULES When the Licensee has developed a Dynamic Module, the terms and conditions hereof do not apply to said Dynamic Module, that may be distributed under a separate Licensing Agreement. 5.3.4. COMPATIBILITY WITH THE GPL LICENSE In the event that the Modified or unmodified Software is included in a code that is subject to the provisions of the GPL License, the Licensee is authorized to redistribute the whole under the GPL License. In the event that the Modified Software includes a code that is subject to the provisions of the GPL License, the Licensee is authorized to redistribute the Modified Software under the GPL License. Article 6 - INTELLECTUAL PROPERTY ---------------------------------- 6.1. OVER THE INITIAL SOFTWARE The Holder owns the economic rights over the Initial Software. Any or all use of the Initial Software is subject to compliance with the terms and conditions under which the Holder has elected to distribute its work and no one shall be entitled to and it shall have sole entitlement to modify the terms and conditions for the distribution of said Initial Software. The Holder undertakes to maintain the distribution of the Initial Software under the conditions of the Agreement, for the duration set forth in article 4.2.. 6.2. OVER THE CONTRIBUTIONS The intellectual property rights over the Contributions belong to the holder of the economic rights as designated by effective legislation. 6.3. OVER THE DYNAMIC MODULES The Licensee having developed a Dynamic Module is the holder of the intellectual property rights over said Dynamic Module and is free to choose the agreement that shall govern its distribution. 6.4. JOINT PROVISIONS 6.4.1. The Licensee expressly undertakes: - not to remove, or modify, in any or all manner, the intellectual property notices affixed to the Software; - to reproduce said notices, in an identical manner, in the copies of the Software. 6.4.2. The Licensee undertakes not to directly or indirectly infringe the intellectual property rights of the Holder and/or Contributors and to take, where applicable, vis-à-vis its staff, any or all measures required to ensure respect for said intellectual property rights of the Holder and/or Contributors. Article 7 - RELATED SERVICES ----------------------------- 7.1. Under no circumstances shall the Agreement oblige the Licensor to provide technical assistance or maintenance services for the Software. However, the Licensor is entitled to offer this type of service. The terms and conditions of such technical assistance, and/or such maintenance, shall then be set forth in a separate instrument. Only the Licensor offering said maintenance and/or technical assistance services shall incur liability therefor. 7.2. Similarly, any or all Licensor shall be entitled to offer to its Licensees, under its own responsibility, a warranty, that shall only be binding upon itself, for the redistribution of the Software and/or the Modified Software, under terms and conditions that it shall decide upon itself. Said warranty, and the financial terms and conditions of its application, shall be subject to a separate instrument executed between the Licensor and the Licensee. Article 8 - LIABILITY ---------------------- 8.1. Subject to the provisions of Article 8.2, should the Licensor fail to fulfill all or part of its obligations hereunder, the Licensee shall be entitled to claim compensation for the direct loss suffered as a result of a fault on the part of the Licensor, subject to providing evidence of it. 8.2. The Licensor's liability is limited to the commitments made under this Licensing Agreement and shall not be incurred as a result , in particular: (i) of loss due the Licensee's total or partial failure to fulfill its obligations, (ii) direct or consequential loss due to the Software's use or performance that is suffered by the Licensee, when the latter is a professional using said Software for professional purposes and (iii) consequential loss due to the Software's use or performance. The Parties expressly agree that any or all pecuniary or business loss (i.e. loss of data, loss of profits, operating loss, loss of customers or orders, opportunity cost, any disturbance to business activities) or any or all legal proceedings instituted against the Licensee by a third party, shall constitute consequential loss and shall not provide entitlement to any or all compensation from the Licensor. Article 9 - WARRANTY --------------------- 9.1. The Licensee acknowledges that the current situation as regards scientific and technical know-how at the time when the Software was distributed did not enable all possible uses to be tested and verified, nor for the presence of any or all faults to be detected. In this respect, the Licensee's attention has been drawn to the risks associated with loading, using, modifying and/or developing and reproducing the Software that are reserved for experienced users. The Licensee shall be responsible for verifying, by any or all means, the product's suitability for its requirements, its due and proper functioning, and for ensuring that it shall not cause damage to either persons or property. 9.2. The Licensor hereby represents, in good faith, that it is entitled to grant all the rights on the Software (including in particular the rights set forth in Article 5 hereof over the Software). 9.3. The Licensee acknowledges that the Software is supplied "as is" by the Licensor without any or all other express or tacit warranty, other than that provided for in Article 9.2 and, in particular, without any or all warranty as to its market value, its secured, innovative or relevant nature. Specifically, the Licensor does not warrant that the Software is free from any or all error, that it shall operate continuously, that it shall be compatible with the Licensee's own equipment and its software configuration, nor that it shall meet the Licensee's requirements. 9.4. The Licensor does not either expressly or tacitly warrant that the Software does not infringe any or all third party intellectual right relating to a patent, software or to any or all other property right. Moreover, the Licensor shall not hold the Licensee harmless against any or all proceedings for infringement that may be instituted in respect of the use, modification and redistribution of the Software. Nevertheless, should such proceedings be instituted against the Licensee, the Licensor shall provide it with technical and legal assistance for its defense. Such technical and legal assistance shall be decided upon on a case-by-case basis between the relevant Licensor and the Licensee pursuant to a memorandum of understanding. The Licensor disclaims any or all liability as regards the Licensee's use of the Software's name. No warranty shall be provided as regards the existence of prior rights over the name of the Software and as regards the existence of a trademark. Article 10 - TERMINATION ------------------------- 10.1. In the event of a breach by the Licensee of its obligations hereunder, the Licensor may automatically terminate this Agreement thirty (30) days after notice has been sent to the Licensee and has remained ineffective. 10.2. The Licensee whose Agreement is terminated shall no longer be authorized to use, modify or distribute the Software. However, any or all licenses that it may have granted prior to termination of the Agreement shall remain valid subject to their having been granted in compliance with the terms and conditions hereof. Article 11 - MISCELLANEOUS PROVISIONS -------------------------------------- 11.1. EXCUSABLE EVENTS Neither Party shall be liable for any or all delay, or failure to perform the Agreement, that may be attributable to an event of force majeure, an act of God or an outside cause, such as, notably, defective functioning, or interruptions affecting the electricity or telecommunications networks, blocking of the network following a virus attack, the intervention of the government authorities, natural disasters, water damage, earthquakes, fire, explosions, strikes and labor unrest, war, etc. 11.2. The fact that either Party may fail, on one or several occasions, to invoke one or several of the provisions hereof, shall under no circumstances be interpreted as being a waiver by the interested Party of its entitlement to invoke said provision(s) subsequently. 11.3. The Agreement cancels and replaces any or all previous agreement, whether written or oral, between the Parties and having the same purpose, and constitutes the entirety of the agreement between said Parties concerning said purpose. No supplement or modification to the terms and conditions hereof shall be effective as regards the Parties unless it is made in writing and signed by their duly authorized representatives. 11.4. In the event that one or several of the provisions hereof were to conflict with a current or future applicable act or legislative text, said act or legislative text shall take precedence, and the Parties shall make the necessary amendments so as to be in compliance with said act or legislative text. All the other provisions shall remain effective. Similarly, the fact that a provision of the Agreement may be null and void, for any reason whatsoever, shall not cause the Agreement as a whole to be null and void. 11.5. LANGUAGE The Agreement is drafted in both French and English. In the event of a conflict as regards construction, the French version shall be deemed authentic. Article 12 - NEW VERSIONS OF THE AGREEMENT ------------------------------------------- 12.1. Any or all person is authorized to duplicate and distribute copies of this Agreement. 12.2. So as to ensure coherence, the wording of this Agreement is protected and may only be modified by the authors of the License, that reserve the right to periodically publish updates or new versions of the Agreement, each with a separate number. These subsequent versions may address new issues encountered by Free Software. 12.3. Any or all Software distributed under a given version of the Agreement may only be subsequently distributed under the same version of the Agreement, or a subsequent version, subject to the provisions of article 5.3.4. Article 13 - GOVERNING LAW AND JURISDICTION ------------------------------------------- 13.1. The Agreement is governed by French law. The Parties agree to endeavor to settle the disagreements or disputes that may arise during the performance of the Agreement out-of-court. 13.2. In the absence of an out-of-court settlement within two (2) months as from their occurrence, and unless emergency proceedings are necessary, the disagreements or disputes shall be referred to the Paris Courts having jurisdiction, by the first Party to take action. Version 1.1 of 10/26/2004 discoSnp/minia/Set.h0000644000000000000000000000634312156551472013355 0ustar rootroot#ifndef Set_h #define Set_h #include #include #include #include "Hash16.h" #include // for log2f #include // for max/min #include // didn't want to "typedef kmer_type set_elem" because Set is an independent file #ifdef _largeint #include "LargeInt.h" typedef LargeInt set_elem; #else #ifdef _ttmath #include "ttmath/ttmath.h" typedef ttmath::UInt set_elem; #else #if (! defined kmer_type) || (! defined _LP64) typedef uint64_t set_elem; #else typedef kmer_type set_elem; #endif #endif #endif using namespace std; // abstract class class Set{ public: virtual void insert(set_elem elem) = 0; virtual void finalize() = 0; virtual bool contains(set_elem elemn) = 0; }; class HashSet : public Set{ Hash16 *hash; public: void insert(set_elem elem); void finalize(); bool contains(set_elem elemn); static int bits_per_element ; HashSet(uint64_t taille_approx); }; class ListSet : public Set{ protected: vector liste; public: void insert(set_elem elem); void finalize(); bool contains(set_elem elemn); //Raluca bool containsNotBinary(set_elem elem); uint64_t capacity() {return (uint64_t)liste.capacity();} static int bits_per_element ; ListSet(uint64_t taille_approx); ListSet(); }; //typedef unsigned char set_value_t; typedef unsigned short int set_value_t; // need 9 bits for Terminator now class AssocSet : public ListSet { vector liste_value; public: int get( set_elem elem, set_value_t * val); int set(set_elem graine, set_value_t val); void finalize(); AssocSet(); void print_total_size(); void clear(); void start_iterator(); bool next_iterator(); vector::iterator iterator; }; //Raluca typedef struct nt_kmer{ char nt; kmer_type prev_kmer; }nt_kmer_t; typedef struct pair_nt_kmer{ nt_kmer_t nk1, nk2; }pair_nt_kmer_t; void copy_nt_kmer (nt_kmer_t from, nt_kmer_t* to); void copy_pair_nt_kmer (pair_nt_kmer_t from, pair_nt_kmer_t* to); class AssocPairedSet : public ListSet { vector liste_value; public: int get(set_elem elem, pair_nt_kmer_t * val); int set(set_elem graine, pair_nt_kmer_t val); void finalize(); AssocPairedSet(); void print_total_size(); void start_iterator(); bool next_iterator(); void load_branching(BinaryBank * branches); void load(char * filename); void dump(char * filename); vector::iterator iterator; void print(); }; class FPSetCascading4 : public Set{ public: Bloom *bloom2, *bloom3, *bloom4; ListSet *false_positives; bool contains(set_elem elemn) { if (bloom2->contains(elemn)) { if (!bloom3->contains(elemn)) return true; else if (bloom4->contains(elemn) && !false_positives->contains(elemn)) return true; } return false; }; void insert(set_elem elem) {fprintf (stderr, "Error can't insert in FPSetCascading!\n"); exit(0); }; void finalize() {fprintf (stderr, "Error can't finalize in FPSetCascading!\n"); exit(0);}; bool is_false_positive(set_elem elemn) {return contains(elemn);}; }; #endif discoSnp/minia/SortingCount.h0000644000000000000000000000122312230165070015234 0ustar rootroot#include #include #include #include #include #include #include // for S_IRWXU etc #include #include // to determine available disk space #include // to clear the temp directory #ifndef SORTINGCOUNT_H #define SORTINGCOUNT_H #include "Bank.h" #include "Kmer.h" #include "Utils.h" #include "OAHash.h" using namespace std; typedef uint32_t uint_abundance_t; void sorting_count(Bank *Sequences, char *prefix, int max_memory, int max_disk_space, bool write_count, int verbose, bool skip_binary_conversion = false); extern int optimism; #endif discoSnp/minia/Bank.cpp0000644000000000000000000007633112305316340014021 0ustar rootroot// // Bank.cpp // // Created by Guillaume Rizk on 28/11/11. // //TEST #define _LARGEFILE_SOURCE #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include // for log2f #include "Bank.h" #include "Kmer.h" // Bank (almost) doesn't need Kmer.h, but KmersBuffer certainly does #include "lut.h" #include using namespace std; off_t fsize(const char *filename) { struct stat st; if (stat(filename, &st) == 0) return st.st_size; return -1; } // just a macro to open file indexed by i void Bank::open_stream(int i) { buffered_file[i]->stream = gzopen(buffered_file[i]->fname,"r"); if (buffered_file[i]->stream == NULL) { printf("error opening file: %s\n",buffered_file[i]->fname); exit(1); } } // and close it void Bank::close_stream(int i) { gzclose(buffered_file[i]->stream); buffered_file[i]->stream = NULL; } // the following functions are adapted from kseq.h by Heng Li (https://github.com/attractivechaos/klib) inline bool rebuffer(buffered_file_t *bf) { if (bf->eof) return false; bf->buffer_start = 0; bf->buffer_end = gzread(bf->stream, bf->buffer, BUFFER_SIZE); if (bf->buffer_end < BUFFER_SIZE) bf->eof = 1; if (bf->buffer_end == 0) return false; return true; } inline signed char buffered_getc(buffered_file_t *bf) { if (bf->buffer_start >= bf->buffer_end) if (! rebuffer(bf)) return -1; return (signed char) ( bf->buffer[bf->buffer_start++] ); } #define nearest_power_of_2(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) inline signed int Bank::buffered_gets(buffered_file_t *bf, variable_string_t *s, char *dret, bool append, bool allow_spaces) { if (dret) *dret = 0; if (!append) s->length = 0; if (bf->buffer_start >= bf->buffer_end && bf->eof) return -1; while (1) { int i; if (bf->buffer_start >= bf->buffer_end) if (! rebuffer(bf)) break; if (allow_spaces) { for (i = bf->buffer_start; i < bf->buffer_end ; i++) if (bf->buffer[i] == '\n') break; } else { for (i = bf->buffer_start; i < bf->buffer_end ; i++) // isspace() answers yes for ' ', \t, \n, \v, \f, \r if (isspace(bf->buffer[i])) break; } if (s->max - s->length < (i - bf->buffer_start + 1)) { s->max = s->length + (i - bf->buffer_start + 1); nearest_power_of_2(s->max); s->string = (char*)realloc(s->string,s->max); } memcpy(s->string + s->length, bf->buffer + bf->buffer_start, i - bf->buffer_start); s->length += i - bf->buffer_start; bf->buffer_start = i + 1; if (i < bf->buffer_end) { if (dret) *dret = bf->buffer[i]; break; } } if (s->string == NULL) { s->max = 256; s->string = (char*)calloc(256,1); } else if ( allow_spaces && s->length > 1 && s->string[s->length-1] == '\r') s->length--; s->string[s->length]= '\0'; return s->length; } void Bank::rewind_all() { for (int i=0; istream != NULL) { gzclose(buffered_file[i]->stream); buffered_file[i]->stream = NULL; } buffered_file[i]->last_char = buffered_file[i]->eof = buffered_file[i]->buffer_start = buffered_file[i]->buffer_end = 0; } index_file = 0; open_stream(index_file); } // THIS READS FASTQ or FASTA, compressed with gzip or not // no limit on read length, allows multi-line reads // returns true if a read was successfuly read // false if end of file // adapted from kseq.h by Heng Li (https://github.com/attractivechaos/klib) bool Bank::get_next_seq_from_file(char **nseq, char **cheader, int *len, int *hlen, int file_id) { signed char c; buffered_file_t *bf = buffered_file[file_id]; if (bf->last_char == 0) { while ( (c = buffered_getc(bf)) != -1 && c != '>' && c != '@'); // go to next header if (c == -1) return false; // eof bf->last_char = c; } read->length = dummy->length = 0; if (buffered_gets(bf, header, (char *)&c, false, false) < 0) //ici return false; // eof if (c != '\n') buffered_gets(bf, dummy, NULL, true, true); // read header //dummy instead of header to stop before first space if (read->string == NULL) { read->max = 256; read->string = (char*) malloc(read->max); } while ( (c = buffered_getc(bf)) != -1 && c != '>' && c != '+' && c != '@') { if (c == '\n') continue; // empty line read->string[read->length++] = c; buffered_gets(bf, read, NULL, true, true); } if (c == '>' || c == '@') bf->last_char = c; if (read->length + 1 >= read->max) { read->max = read->length + 2; nearest_power_of_2(read->max); read->string = (char*) realloc(read->string, read->max); } read->string[read->length] = '\0'; if (c == '+') // fastq { if (dummy->max < read->max) // resize quality to match read length { dummy->max = read->max; dummy->string = (char*)realloc(dummy->string, dummy->max); } while ( (c = buffered_getc(bf)) != -1 && c != '\n'); // read rest of quality comment while (buffered_gets(bf, dummy, NULL, true, true) >= 0 && dummy->length < read->length); // read rest of quality bf->last_char = 0; } *len = read->length; *nseq = read->string; if (cheader && hlen) { *cheader = header->string; *hlen = header->length; } return true; } // wrapper bool Bank::get_next_seq_from_file(char **nseq, int *len, int file_id) { return get_next_seq_from_file(nseq,NULL,len,NULL,file_id); } //wrapper with notif when changing file bool Bank::get_next_seq(char **nseq, char **cheader, int *len, int *hlen, int * id_file) { * id_file = index_file ; bool success = get_next_seq_from_file(nseq,cheader,len,hlen,index_file); if (success) return true; // cycle to next file if possible if ( index_file < nb_files-1 ) { close_stream(index_file); index_file++; open_stream(index_file); return get_next_seq(nseq,cheader, len,hlen, id_file); } return false; } // wrapper bool Bank::get_next_seq(char **nseq, char **cheader, int *len, int *hlen) { bool success = get_next_seq_from_file(nseq,cheader,len,hlen,index_file); if (success) return true; // cycle to next file if possible if ( index_file < nb_files-1 ) { close_stream(index_file); index_file++; open_stream(index_file); return get_next_seq(nseq,cheader, len,hlen); } return false; } // wrapper bool Bank::get_next_seq(char **nseq, int *len) { return get_next_seq(nseq,NULL,len,NULL); } // wrapper bool Bank::get_next_seq(char **nseq, int *len, int * id_file) { return get_next_seq(nseq,NULL,len,NULL,id_file); } // had to move the Bank(x,x) constructor to an init() to avoid calling a constructor inside the Bank(x) constructor void Bank::init(char **fname, int nb_files_) { int64_t i; nb_files = nb_files_; filesizes = 0; // open the reads file, don't know if it is a fasta/q file or a list of file names yet gzFile tempfile = gzopen(fname[0],"r"); if (tempfile == NULL) { char *buffer = (char*)malloc(BUFSIZ); strerror_r( errno, buffer, BUFSIZ ); // get string message from errno printf("error during fopen, filename: %s (buffer: %p) \n", fname[0], buffer); free(buffer); exit(1); } char deb=(char)gzgetc(tempfile); char **nfname;// [MAX_NB_FILES][TAILLE_NOM]; nfname = (char**) malloc(sizeof(char*)*MAX_NB_FILES); for(int jj=0; jj' || deb=='@' || deb==EOF) { // file is a fasta/q file gzclose(tempfile); } else // file contains a list of file names { char* ret; gzungetc(deb,tempfile); printf("File %s starts with character \"%c\", hence is interpreted as a list of file names\n",fname[0],deb ); int ii; // get the filenames for (ii=0; iibuffer = (unsigned char*) malloc(BUFFER_SIZE); buffered_file[i]->fname = strdup(fname[i]); } // estimate total size of files for (i=0; iestimated_filesize = estimated_filesize; filesizes += estimated_filesize; } rewind_all(); // initialize the get_next_seq iterator to the first file // init read and dummy (for readname and quality) read = (variable_string_t*) calloc(1,sizeof(variable_string_t)); dummy = (variable_string_t*) calloc(1,sizeof(variable_string_t)); header = (variable_string_t*) calloc(1,sizeof(variable_string_t)); for(int jj=0; jjstring) free(to_free[i]->string); free(to_free[i]); } } for (int i=0; ibuffer); free(buffered_file[i]); } } void Bank::close() { for (int i=0; istream); } // estimate the volume of all redundant kmers in the reads, if they were to be stored in 2bits // from the first 100k reads of each file uint64_t Bank::estimate_kmers_volume(int k) { char * rseq; int readlen; int kmer_nbits = sizeof(kmer_type)*8; rewind_all(); uint64_t total_volume = 0; while ( index_file < nb_files ) { open_stream(index_file); int NbRead = 0; uint64_t volume_for_file = 0; while (get_next_seq_from_file(&rseq,NULL,&readlen,NULL,index_file)) { if (readlen >= k) volume_for_file += (readlen-k+1) * (uint64_t) kmer_nbits; if (NbRead++ == 100000) // somehow less than 100000 is bad for our ion torrent tag1.fasta file break; } if ( gztell(buffered_file[index_file]->stream) != 0) // would be empty file { volume_for_file = (uint64_t) ( ( (float) volume_for_file ) * ( ( (float)(buffered_file[index_file]->estimated_filesize)) / ((float) gztell(buffered_file[index_file]->stream)) ) ); total_volume += volume_for_file; } close_stream(index_file); index_file++; } total_volume = total_volume / 1024 /1024 /8; // put it in MB if (total_volume == 0) // tiny files fix total_volume = 1; rewind_all(); return total_volume; } // estimate the number of reads uint64_t Bank::estimate_nb_reads() { char * rseq; int readlen; int NbRead = 0; rewind_all(); uint64_t volume = 0; while (get_next_seq(&rseq,&readlen)) { volume += 1; if (NbRead++ == 1000) break; } if ( gztell(buffered_file[index_file]->stream) == 0) // empty file return 1; volume = (volume * filesizes) / gztell(buffered_file[index_file]->stream); // linear extrapolation from the first 1k reads rewind_all(); return volume; } // estimate maximum read length // from the first 10000 reads of each file int Bank::estimate_max_readlen() { char * rseq; int readlen; rewind_all(); int max_readlen = 0; uint64_t volume = 0; while ( index_file < nb_files ) { open_stream(index_file); int NbRead = 0; while (get_next_seq_from_file(&rseq,NULL,&readlen,NULL,index_file)) { max_readlen = max(readlen, max_readlen); if (NbRead++ == 10000) break; } close_stream(index_file); index_file++; } rewind_all(); return max_readlen; } void Bank::save_position() { restore_index_file = index_file; restore_pos = gztell(buffered_file[index_file]->stream) - buffered_file[index_file]->buffer_end + buffered_file[index_file]->buffer_start; } void Bank::load_position() { close_stream(index_file); index_file = restore_index_file; open_stream(index_file); gzseek(buffered_file[index_file]->stream, restore_pos, SEEK_SET); buffered_file[index_file]->eof = false; rebuffer(buffered_file[index_file]); } // BinaryBank: a binary file containing kmers BinaryBank::BinaryBank(char *given_filename, int given_sizeElement, bool write) : sizeElement(given_sizeElement) { strcpy(filename,given_filename); open(write); buffer_size_nelem= (WRITE_BUFFER/given_sizeElement); buffer = (void *) malloc(given_sizeElement * buffer_size_nelem); cpt_buffer=0; } BinaryBankConcurrent::BinaryBankConcurrent(char *given_filename, int given_sizeElement, bool write, int given_nthreads) : BinaryBank(given_filename,given_sizeElement,write) { nthreads = given_nthreads; //free(buffer); buffer =NULL; //cannot do that bufferT = (void **) malloc(sizeof(void*) * nthreads); for (int i= 0; i< nthreads; i++) { ((void ** )bufferT)[i]= (void *) malloc( WRITE_BUFFER); } cpt_buffer_tid = (int *)malloc(sizeof(int) * nthreads); memset (cpt_buffer_tid,0,sizeof(int) * nthreads); } void BinaryBankConcurrent::write_element_buffered( void *element, int tid) { write_buffered(element, sizeElement, tid); } void BinaryBankConcurrent::write_buffered( void *element, int size, int tid) { write_buffered( element, size, tid, true); } void BinaryBankConcurrent::write_buffered( void *element, int size, int tid, bool can_flush) { if(cpt_buffer_tid[tid]>= WRITE_BUFFER -100 && can_flush) { flush(tid); } char * buf_pt = ((char**) bufferT)[tid]; memcpy(buf_pt + cpt_buffer_tid[tid] , element, size); cpt_buffer_tid[tid]+=size; // cpt_buffer_tid[tid]++; } void BinaryBankConcurrent::flush(int tid) { flockfile(binary_read_file); if (!fwrite( ((void **)bufferT)[tid], 1, cpt_buffer_tid[tid], binary_read_file)) { printf("error: can't fwrite (disk full?)\n"); funlockfile(binary_read_file); exit(1); } cpt_buffer_tid[tid]=0; funlockfile(binary_read_file); } //should be called by only one of the threads void BinaryBankConcurrent::close() { //flush buffer // if close Bank in read mode with data in the readbuffer, will result in error for(int ii=0; ii< nthreads; ii++) { if(cpt_buffer_tid[ii]) { if (!fwrite(((void **)bufferT)[ii], 1, cpt_buffer_tid[ii], binary_read_file)) // if (!fwrite(((void **)bufferT)[ii], sizeElement, cpt_buffer_tid[ii], binary_read_file)) { printf("error: can't fwrite (disk full?)\n"); exit(1); } } cpt_buffer_tid[ii]=0; } fclose(binary_read_file); } void BinaryBank::write_element( void *element) { // flockfile(binary_read_file); // fprintf(stderr,"write elem %lli \n",*(int64_t *)element); if (!fwrite(element, sizeElement, 1, binary_read_file)) { // funlockfile(binary_read_file); printf("error: can't fwrite (disk full?)\n"); exit(1); } // funlockfile(binary_read_file); } void BinaryBank::write_element_buffered( void *element) { if(cpt_buffer==buffer_size_nelem) { if (!fwrite(buffer, sizeElement, buffer_size_nelem, binary_read_file)) { printf("error: can't fwrite (disk full?)\n"); exit(1); } cpt_buffer=0; } //((kmer_type *)buffer)[cpt_buffer]= *((kmer_type *)element); memcpy((unsigned char *)buffer + (cpt_buffer * sizeElement), element, sizeElement); cpt_buffer++; } size_t BinaryBank::read_element( void *element) { return fread(element, sizeElement,1, binary_read_file); } size_t BinaryBank::read_element_buffered( void *element) { if(cpt_buffer==0) { cpt_buffer=fread(buffer, sizeElement,buffer_size_nelem, binary_read_file); if (cpt_buffer==0) return 0; cpt_init_buffer = cpt_buffer; } //memcpy(element, (unsigned char *)buffer + (cpt_buffer-1) * sizeElement, sizeElement);//ca les depile en sens inverse de la lecture memcpy(element, (unsigned char *)buffer + (cpt_init_buffer -1 - (cpt_buffer-1)) * sizeElement, sizeElement);//ca les depile dans le meme sens que la lecture cpt_buffer --; return cpt_buffer+1; // nb remaining before read } // used to read/write raw information to the binary file (e.g. kmer count) void BinaryBank::write( void *element, int size) { if (!fwrite(element, size, 1, binary_read_file)) { printf("error: can't fwrite (disk full?)\n"); exit(1); } } size_t BinaryBank::read( void *element, int size) { return fread(element, size,1, binary_read_file); } void BinaryBank::rewind_all() { rewind(binary_read_file); } void BinaryBank::close() { //flush buffer // if close Bank in read mode with data in the readbuffer, will result in error if(cpt_buffer) { if (!fwrite(buffer, sizeElement, cpt_buffer, binary_read_file)) { printf("error: can't fwrite (disk full?)\n"); exit(1); } } cpt_buffer=0; fclose(binary_read_file); } void BinaryBank::open(bool write) { binary_read_file = fopen(filename,write?"wb":"rb"); if( binary_read_file == NULL ) { char *buffer = (char*)malloc(BUFSIZ); strerror_r( errno, buffer, BUFSIZ ); // get string message from errno printf("error during fopen: %s write %i %s\n",buffer,write,filename); free(buffer); exit(1); } } off_t BinaryBank::nb_elements() { return fsize(filename)/sizeElement; } BinaryBank::~BinaryBank() { if(buffer!=NULL) { free (buffer); //buffer =NULL; } } BinaryBankConcurrent::~BinaryBankConcurrent() { for (int i= 0; i< nthreads; i++) { free(((void ** )bufferT)[i]); ((void ** )bufferT)[i]=NULL; } free(bufferT); } /////////////class BinaryReads a file containing reads BinaryReads::~BinaryReads() { free (buffer); buffer = NULL; } BinaryReads::BinaryReads(char *given_filename, bool write) { read_write_buffer_size = BINREADS_BUFFER; strcpy(filename,given_filename); open(write); buffer = (unsigned char *) malloc(read_write_buffer_size*sizeof(unsigned char)); cpt_buffer = 0; } void BinaryReads::rewind_all() { rewind(binary_read_file); } void BinaryReads::close() { unsigned int block_size =0; //flush buffer if(cpt_buffer) { //printf("close :write block %i \n",cpt_buffer); block_size = cpt_buffer; fwrite(&block_size, sizeof(unsigned int), 1, binary_read_file); // block header if (!fwrite(buffer, 1, cpt_buffer, binary_read_file)) { printf("error: can't fwrite (disk full?)\n"); exit(1); } } cpt_buffer=0; fclose(binary_read_file); } void BinaryReads::open(bool write) { binary_read_file = fopen(filename,write?"wb":"rb"); if( binary_read_file == NULL ) { char *buffer = (char*)malloc(BUFSIZ); strerror_r( errno, buffer, BUFSIZ ); // get string message from errno printf("error during fopen: %s write %i %s\n",buffer,write,filename); free(buffer); exit(1); } } void BinaryReads::mark_newfile() { unsigned int block_size =0; //flush previous buffer if(cpt_buffer) { //printf("close :write block %i \n",cpt_buffer); block_size = cpt_buffer; fwrite(&block_size, sizeof(unsigned int), 1, binary_read_file); // block header if (!fwrite(buffer, 1, cpt_buffer, binary_read_file)) { printf("error: can't fwrite (disk full?)\n"); exit(1); } } cpt_buffer=0; //then write empty block == mark of a new file block_size =0; fwrite(&block_size, sizeof(unsigned int), 1, binary_read_file); // block header with 0 } //format is // 32 bit integer = readlen, then seq in binary // then next read.. //32 bit len is overkill but simpler //also makes buffer then write block with header : size of block to read, with n reads .... will allow large fread when reading this file ... void BinaryReads::write_read(char * read, int readlen) { int tai = readlen; unsigned char rbin; char * pt = read; unsigned int block_size = 0; // printf("write read %i / %i readlen %i \n",cpt_buffer,read_write_buffer_size,readlen); //todo : also flush to disk sometimes (ie if very large buffer, to create smaller blocks..) if((cpt_buffer && cpt_buffer >= (read_write_buffer_size-readlen)) || cpt_buffer > 10000000 ) ////not enough space to store next read true space is 4 + readlen/4 + rem //flush buffer to disk { block_size = cpt_buffer; //printf("write block %i\n",block_size); if(block_size) fwrite(&block_size, sizeof(unsigned int), 1, binary_read_file); // block header if (!fwrite(buffer, 1, cpt_buffer, binary_read_file)) // write a block, it ends at end of a read { printf("error: can't fwrite (disk full?)\n"); exit(1); } cpt_buffer=0; } //check if still not enough space in empty buffer : can happen if large read, then enlarge buffer if(read_write_buffer_size < readlen) { read_write_buffer_size = 2*readlen; // too large but ok buffer = (unsigned char *) realloc(buffer,sizeof(unsigned char) * read_write_buffer_size); } memcpy(buffer+cpt_buffer,&readlen,sizeof(int)); cpt_buffer+= sizeof(int); //fwrite( (void *) &readlen, sizeof(int), 1, binary_read_file); for (tai=readlen; tai>=4 ; tai-=4) { rbin = code4NT(pt); // fwrite((void *) &rbin, 1,1,binary_read_file ); buffer[cpt_buffer]=rbin; cpt_buffer++; pt +=4; } //then remaining if(tai) { rbin = code_n_NT(pt,tai); // fwrite( (void *) &rbin,1,1,binary_read_file); buffer[cpt_buffer]=rbin; cpt_buffer++; } } void compute_kmer_table_from_one_seq(int readlen, char * seq, kmer_type * kmer_table ) //,char * pkmer_table //pour remplissage table loc { kmer_type graine = codeSeed(seq); kmer_type graine_revcomp = revcomp(graine); kmer_table[0] = min(graine,graine_revcomp); seq++; for (int i=1; i> 2) + ( ((kmer_type) comp_NT[NT2int(seq[sizeKmer-1])]) << (2*(sizeKmer-1)) ) ) & kmerMask ; kmer_table[i] = min(graine,graine_revcomp); seq++; } } ////kmers buffer KmersBuffer::KmersBuffer(BinaryReads *bfile, int pbuffer_size, int nseq_task ) { read_write_buffer_size = BINREADS_BUFFER; buffer = ( char *) malloc(read_write_buffer_size*sizeof( char)); cpt_buffer = 0; cpt_binSeq_read =0; binSeq_toread =0; max_read_length = KMERSBUFFER_MAX_READLEN; binfile = bfile; buffer_size = pbuffer_size; kmers_buffer = (kmer_type *) malloc(sizeof(kmer_type) * buffer_size); // binSeq = (char *) malloc(sizeof(char) * max_read_length); // no need to alloc ram for binse : will points to buffer binSeq_extended = (char *) malloc(sizeof(char) * max_read_length); blocksize_toread =0; nseq_step = nseq_task; binary_read_file = bfile->binary_read_file; } void KmersBuffer::reset_max_readlen(int read_length) { max_read_length = read_length; // binSeq = (char *) realloc(binSeq,sizeof(char) * max_read_length); binSeq_extended = (char *) realloc(binSeq_extended,sizeof(char) * max_read_length); } KmersBuffer::~KmersBuffer() { free (kmers_buffer); free(buffer); //free(binSeq); free(binSeq_extended); } //now returns number of kmers read int KmersBuffer::readkmers() { int llen; int * len = & llen ; unsigned int block_size =0; //////reading new block from disk if needed // cpt_buffer == blocksize_toread tells we finished reading previous buffer // (binSeq_toread <= cpt_binSeq_read) tells we finished reading the last sequence if(cpt_buffer == blocksize_toread && (binSeq_toread <= cpt_binSeq_read)) { flockfile(binary_read_file); if( ! fread(&block_size,sizeof(unsigned int),1, binary_read_file)) //read block header { funlockfile(binary_read_file); return -1; // no more blocks to read } // block_size = 0 is a marker to indicate new read file, when it happens return -2 if(block_size==0) { return -2 ; } /// if(block_size >= read_write_buffer_size) // block buffer need to be enlarged { read_write_buffer_size = 2*block_size; buffer = ( char *) realloc(buffer,sizeof( char) * read_write_buffer_size); } fread(buffer,sizeof( char),block_size, binary_read_file); // read a block of sequences into the buffer funlockfile(binary_read_file); cpt_buffer = 0; blocksize_toread = block_size; } /////////////////////// //now parse the whole block in ram int i,j; int nchar; unsigned char fournt; nkmers = 0; int nseq_lues = 0; //cpt_buffer : how much we have already read in the buffer //blocksize_toread : how much there is to read in the buffer while(cpt_buffer < blocksize_toread || ( binSeq_toread > cpt_binSeq_read)) //while work to do { if( binSeq_toread <= cpt_binSeq_read)// read new sequence if needed //we will put one sequence into binSeq_extended { memcpy(len,buffer+cpt_buffer,sizeof(int)); // the sequence length cpt_buffer += sizeof(int); nseq_lues ++; if( (*len) > max_read_length) reset_max_readlen((int)(1.2*(*len))); // resize memory for sequence if needed nchar = ((*len)+3)/4; // number of bytes used to encode the sequence in its binary format (4 nt per byte) binSeq = buffer + cpt_buffer; // point binseq to correct place //cpt_buffer == where we are now in the buffer cpt_buffer += nchar; // on disk data was encoded with 4 nucleotides per bytes, // here we expand one sequence to one nucl per byte into binSeq_extended //nucleotides are still encoded in [0-3] j=0; for(i=0; i> 2; binSeq_extended[j+2]=fournt & 3; fournt = fournt >> 2; binSeq_extended[j+1]=fournt & 3; fournt = fournt >> 2; binSeq_extended[j+0]=fournt & 3; j+=4; } binSeq_toread = *len-sizeKmer+1; // binSeq_toread tells how many kmers there are in this sequence cpt_binSeq_read = 0; // tells how many kmers we have currently parsed in this sequence } { // binSeq_extended = beginning of the sequence, // cpt_binSeq_read = how much we have already read in this sequence (when kmers_buffer is full, we can halt parsing kmers (see below) in the middle of a sequence, so this value is not necessarily 0) char *seq = binSeq_extended+cpt_binSeq_read; kmer_type graine; kmer_type graine_revcomp; if( binSeq_toread > cpt_binSeq_read) // there are still unread kmers in this sequence, here we read the first one, // we put it in graine / graine_revcomp and store it in the kmers_buffer { graine = codeSeed_bin(seq); graine_revcomp = revcomp(graine); if(nkmers>=buffer_size) { return nkmers; } kmers_buffer[nkmers] = min(graine,graine_revcomp); nkmers++; cpt_binSeq_read ++; seq++; } while( binSeq_toread > cpt_binSeq_read) //while there remains kmers to be read in this sequence { graine = (graine * 4 + (seq[sizeKmer-1])) & kmerMask ; //parse next nucleotide to construc the next kmer graine_revcomp = ((graine_revcomp >> 2) + ( ((kmer_type) comp_NT[(int)(seq[sizeKmer-1])]) << (2*(sizeKmer-1)) ) ) & kmerMask; kmers_buffer[nkmers] = min(graine,graine_revcomp); nkmers ++; cpt_binSeq_read ++; //we store the kmer in the kmers_buffer seq++; if(nkmers>=buffer_size) //the kmers_buffer is full, we stop { return nkmers; } } } } // we stop when we finished one block, or when kmers_buffer is full, // it can happen in the middle of a sequence : the next time we call readkmers we will have to continue // from where we stopped in this sequence (counter cpt_binSeq_read tells us that) //while buffer is non empty, we 'expand' a sequence into binSeq_extended //then we parse binSeq_extended to store kmers in the kmers_buffer return nkmers; } discoSnp/minia/MultiConsumer.cpp0000644000000000000000000000611012126546644015755 0ustar rootroot#include "MultiConsumer.h" template MultiConsumer::MultiConsumer() : sizeBuffer(0), maxSizeBuffer(NB_PACKETS), allDone(false) { mutex = new pthread_mutex_t; mutex2 = new pthread_mutex_t; pthread_mutex_init(mutex, NULL); pthread_mutex_init(mutex2, NULL); notFull = new pthread_cond_t; notEmpty = new pthread_cond_t; pthread_cond_init(notFull, NULL); pthread_cond_init(notEmpty, NULL); } template void MultiConsumer::produce(Task *task) { pthread_mutex_lock(mutex); while (sizeBuffer == maxSizeBuffer) { pthread_cond_wait(notFull, mutex); } buffer[sizeBuffer++] = task; pthread_cond_signal(notEmpty); pthread_mutex_unlock(mutex); } template Task *MultiConsumer::consume() { Task *task; pthread_mutex_lock(mutex); while (sizeBuffer == 0) { if (isAllDone()) { pthread_mutex_unlock(mutex); return NULL; } pthread_cond_wait(notEmpty, mutex); } task = buffer[--sizeBuffer]; pthread_cond_signal(notFull); pthread_mutex_unlock(mutex); return task; } template void MultiConsumer::setAllDone() { pthread_mutex_lock(mutex2); allDone = true; pthread_cond_signal(notEmpty); pthread_mutex_unlock(mutex2); } template bool MultiConsumer::isAllDone() { bool res; pthread_mutex_lock(mutex2); res = allDone; pthread_mutex_unlock(mutex2); return res; } // wrapper around MultiConsumer to bundle 10 MB of reads together MultiReads::MultiReads(int thread_id) : thread_id(thread_id) { mc = new MultiConsumer(); new_packet(); } void MultiReads::new_packet() { current_packet = new reads_packet; nbRead = 0; nbNucleotides = 0; } void MultiReads::produce(char *read, int readlen) { if (nbRead > 0 && nbNucleotides > MAX_NUCL_IN_PACKET) { mc->produce(current_packet); //printf("%d - produced (%d in stack)\n", thread_id, mc->sizeBuffer); new_packet(); } current_packet->reads.push_back(read); nbRead++; nbNucleotides += readlen; } void MultiReads::setAllDone() { if (nbRead > 0) // produce that last packet { mc->produce(current_packet); } mc->setAllDone(); } bool MultiReadsConsumer::is_finished_packet() { return nbRead == current_packet->reads.size(); } void MultiReadsConsumer::consume(char* &read, int &readlen) { if (!has_packet || is_finished_packet()) { if (current_packet != NULL) { delete current_packet; } //printf("%d - attempting to consume (%d remaining)\n", thread_id, mc->sizeBuffer); current_packet = mc->consume(); //printf("%d - consumed (%d remaining)\n", thread_id, mc->sizeBuffer); nbRead = 0; has_packet = true; if (current_packet == NULL) // no more reads, all done { readlen = 0; return; } } readlen = current_packet->reads[nbRead].length(); read = (char *)current_packet->reads[nbRead].c_str(); nbRead++; } discoSnp/minia/Debloom.cpp0000644000000000000000000003627512365451510014537 0ustar rootroot#include "Debloom.h" // GUS: the false positive set can be either FPSet or FPSetCascading4, // both inheriting from Set. The choice is made by the function called // to load the false positives: load_false_positives() or // load_false_positives_cascading4(). Set *false_positives; FILE * F_debloom_read; FILE * F_debloom_write; uint64_t n_false_positives=0; Hash16 * hasht1; void end_debloom_partition(bool last_partition) { int value; char false_positive_kmer_char[sizeKmer+1]; FILE *file_false_positive_kmers =NULL; kmer_type graine; /////////////////////////begin write files rewind (F_debloom_read); rewind (F_debloom_write); #ifndef MINGW ftruncate(fileno(F_debloom_write), 0); //erase previous file #else // tempfix? fileno is not accepted by mingw fclose(F_debloom_write); F_debloom_write = fopen(return_file_name("debloom2"),"wb+"); #endif if (last_partition) { // write false positive kmers to fasta file file_false_positive_kmers = fopen(return_file_name(false_positive_kmers_file),"wb"); } n_false_positives = 0; while(fread(&graine, sizeof(graine),1, F_debloom_read)){ if(hasht1->get(graine,&value)==0) //kmer not present == kmer not solid { n_false_positives ++; if (!fwrite(&graine, sizeof(graine), 1, F_debloom_write)) { printf("error: can't fwrite (disk full?)\n"); exit(1); } if (last_partition) { code2seq(graine,false_positive_kmer_char); fprintf(file_false_positive_kmers,">fp\n"); fputs(false_positive_kmer_char,file_false_positive_kmers); fprintf(file_false_positive_kmers,"\n"); } } //else kmer is a true positive, do nothing } if (last_partition) fclose(file_false_positive_kmers); } int debloom(int order, int max_memory) { // read bloo1 from disk dump Bloom *bloo1 = bloom_create_bloo1((BloomCpt *)NULL); STARTWALL(pos); FILE * debloom_file = fopen(return_file_name("debloom"),"wb+"); FILE * debloom_file_2 = fopen(return_file_name("debloom2"),"wb+"); FILE * F_tmp; F_debloom_read = debloom_file; F_debloom_write = debloom_file_2; BinaryBank *SolidKmers = new BinaryBank(return_file_name(solid_kmers_file),sizeof(kmer_type),0); uint64_t cc=0; kmer_type new_graine, kmer; int nt; uint64_t NbSolidKmer =0; // write all positive extensions in disk file while (SolidKmers->read_element(&kmer)) { //8 right extensions (4F and 4R); left extensions are redundant by revcomplementation for(nt=0; nt<4; nt++) { int strand; for (strand = 0; strand < 2 ; strand++) { int current_strand = strand; new_graine = next_kmer(kmer,nt, ¤t_strand); if(bloo1->contains(new_graine)){ // extension is positive // maybe do more lax deblooming; if it's a dead-end, it's no big deal, don't pass it to the false positive test // what would have been needed if i decided to enable order>0 (but actually this won't happen): // - better estimate of structure size in the presence of order>0 deblooming if (order == 1) // this case just detects tips { bool is_linked = false; for(int tip_nt=0; tip_nt<4; tip_nt++) { int new_strand = current_strand; kmer_type kmer_after_possible_tip = next_kmer(new_graine,tip_nt, &new_strand); if(bloo1->contains(kmer_after_possible_tip)) { is_linked = true; break; } } if (!is_linked) continue; // it's a tip, because it's linked to nothing } if (order > 1) // general case. should work for order = 1, but i coded an optimized version above { Frontline frontline( new_graine, current_strand, bloo1, NULL, NULL, NULL); while (frontline.depth < order) { frontline.go_next_depth(); if (frontline.size() == 0) break; // don't allow a breadth too large anywqy if (frontline.size()> 10) break; } if (frontline.size() == 0) continue; // it's a deadend } if (!fwrite(&new_graine, sizeof(new_graine), 1, debloom_file)) { printf("error: can't fwrite (disk full?)\n"); exit(1); } cc++; } } } NbSolidKmer++; if ((NbSolidKmer%10000)==0) fprintf (stderr,"%c Writing positive Bloom Kmers %lld",13,NbSolidKmer); } nbkmers_solid = NbSolidKmer; // GUS: it's global now fprintf(stderr,"\n%lli kmers written\n",cc); STOPWALL(pos,"Write all positive kmers"); STARTWALL(deb); double bl1tai = (double)bloo1->tai ; delete bloo1; // now that bloo1 is deleted, initialize hasht1 int NBITS_HT = max( (int)ceilf(log2f((0.1*max_memory*1024L*1024L)/sizeof(cell_ptr_t))), 1); // set hasht1 cells to occupy 0.1 * [as much mem as poss] hasht1 =new Hash16(NBITS_HT); //////////////////////////////////////////////////////////////// --find false positive, with hash table partitioning uint64_t max_kmer_per_part = (uint64_t) (0.8*max_memory*1024LL*1024LL /sizeof(cell)); //adapter taille ht en fonction printf("%d partitions will be needed\n",(int)(nbkmers_solid/max_kmer_per_part)); NbSolidKmer =0; int numpart = 0; SolidKmers->rewind_all(); // deblooming: // read the list of (non-redundant) solid kmers and load it, in chunks, into a hash table // at each pass, check all the positive extensions and keep those which are not indicated, by the current chunk, as solid kmers // at the end, only the positive extensions which are not solid are kept while (SolidKmers->read_element(&kmer)) { hasht1->add(kmer); NbSolidKmer++; if ((NbSolidKmer%10000)==0) fprintf (stderr,"%cBuild Hash table %lld",13,NbSolidKmer); if(hasht1->nb_elem >max_kmer_per_part) //end partition, find false positives { fprintf(stderr,"End of debloom partition %lli / %lld \n",hasht1->nb_elem,max_kmer_per_part); end_debloom_partition(false); //swap file pointers F_tmp = F_debloom_read; F_debloom_read = F_debloom_write; F_debloom_write = F_tmp; /////////end write files //reset hash table hasht1->empty_all(); fprintf(stderr,"\n%lli false positives written , partition %i \n",n_false_positives,numpart); numpart++; } ///end partition } //fprintf(stderr,"Nb kmers stored in the bloom table %lld\n",nbkmers_solid); ///////////////////////// last partition, will write all the FP's to the good file end_debloom_partition(true); /////////end write files fprintf(stderr,"Total nb false positives stored in the Debloom hashtable %lli \n",n_false_positives); delete hasht1; STOPWALL(deb,"Debloom"); // GUS: will use to output summary later b1_size = (uint64_t) bl1tai; fclose(debloom_file); fclose(debloom_file_2); SolidKmers->close(); return 1; } uint64_t countFP(Bank *FalsePositives) { char * rseq; int readlen; uint64_t nbFP = 0; while (FalsePositives->get_next_seq(&rseq,&readlen)) nbFP++; FalsePositives->rewind_all(); return nbFP; } Set *load_false_positives() { int64_t NbInsertedKmers = 0; char * rseq; int readlen; kmer_type kmer, graine, graine_revcomp; Bank *FalsePositives = new Bank(return_file_name(false_positive_kmers_file)); // alloc false positives with the just the right estimated size uint64_t nbFP = countFP(FalsePositives); FPSet *fp = new FPSet(nbFP); while (FalsePositives->get_next_seq(&rseq,&readlen)) { kmer = extractKmerFromRead(rseq,0,&graine,&graine_revcomp); fp->insert(kmer); NbInsertedKmers++; if ((NbInsertedKmers%10000)==0) fprintf (stderr,(char*)"%cInsert false positive Kmers in hash table %lld",13,NbInsertedKmers); } fp->finalize(); // always call this when finishing to create a FPSet fprintf (stderr,"\nInserted %lld false positive kmers in the hash structure.\n\n",NbInsertedKmers); // print_size_summary(fp); return fp; } Set *dummy_false_positives() { FPSet *fp = new FPSet((uint64_t)1); return fp; } Set *load_false_positives_cascading4() { int64_t NbInsertedKmers; char * rseq; int readlen; kmer_type kmer, graine, graine_revcomp; // **** Initialize B2, B3, B4 and T4 **** Bank *FalsePositives = new Bank(return_file_name(false_positive_kmers_file)); uint64_t nbFP = countFP(FalsePositives); FPSetCascading4 *fp = new FPSetCascading4; fp->bloom2 = new Bloom((uint64_t)(nbFP * NBITS_PER_KMER)); fp->bloom2->set_number_of_hash_func((int)floorf(0.7*NBITS_PER_KMER)); uint64_t estimated_T2_size = max((int)ceilf(nbkmers_solid * (double)powf((double)0.62, (double)NBITS_PER_KMER)), 1); uint64_t estimated_T3_size = max((int)ceilf(nbFP * (double)powf((double)0.62, (double)NBITS_PER_KMER)) ,1); fp->bloom3 = new Bloom((uint64_t)(estimated_T2_size * NBITS_PER_KMER)); fp->bloom3->set_number_of_hash_func((int)floorf(0.7*NBITS_PER_KMER)); fp->bloom4 = new Bloom((uint64_t)(estimated_T3_size * NBITS_PER_KMER)); fp->bloom4->set_number_of_hash_func((int)floorf(0.7*NBITS_PER_KMER)); // **** Insert the false positives in B2 **** NbInsertedKmers = 0; while (FalsePositives->get_next_seq(&rseq,&readlen)) { kmer = extractKmerFromRead(rseq,0,&graine,&graine_revcomp); fp->bloom2->add(kmer); NbInsertedKmers++; // if ((NbInsertedKmers%10000)==0) // fprintf (stderr,"%cInsert false positive B2 %lld",13,NbInsertedKmers); } //fprintf (stderr,"%cInsert false positive B2 %lld", 13,NbInsertedKmers); FalsePositives->close(); DEBUGE(("\nInserted %lld (estimated, %lld) kmers in B2.\n", NbInsertedKmers, nbFP)); // **** Insert false positives in B3 and write T2 int addKmers = 0; NbInsertedKmers = 0; FILE *T2_file = fopen(return_file_name("t2_kmers"), "w+"); // We will read this file later, when filling T4 BinaryBank *SolidKmers = new BinaryBank(return_file_name(solid_kmers_file),sizeof(kmer),0); while(SolidKmers->read_element(&kmer)) { if (fp->bloom2->contains(kmer)) { if (!fwrite(&kmer, sizeof(kmer), 1, T2_file)) { printf("error: can't fwrite (disk full?)\n"); exit(1); } fp->bloom3->add(kmer); addKmers++; } NbInsertedKmers++; //if ((NbInsertedKmers%10000)==0) //fprintf (stderr,(char*)"%cInsert false positive B3 %lld",13,NbInsertedKmers); } // fprintf (stderr,(char*)"%cInsert false positive B3 %lld",13,NbInsertedKmers); SolidKmers->close(); DEBUGE(("\nInserted %d (estimated, %llu) kmers in B3.\n", addKmers, estimated_T2_size)); // **** Insert false positives in B4 (we could write T3, but it's not necessary) FalsePositives = new Bank(return_file_name(false_positive_kmers_file)); NbInsertedKmers = 0; addKmers = 0; while (FalsePositives->get_next_seq(&rseq,&readlen)) { kmer = extractKmerFromRead(rseq,0,&graine,&graine_revcomp); if (fp->bloom3->contains(kmer)) { fp->bloom4->add(kmer); addKmers++; } NbInsertedKmers++; //if ((NbInsertedKmers%10000)==0) //fprintf (stderr,"%cInsert false positive B4 %lld",13,NbInsertedKmers); } //fprintf (stderr,"%cInsert false positive B4 %lld", 13,NbInsertedKmers); FalsePositives->close(); DEBUGE(("\nInserted %d (estimated, %lld) kmers in B4.\n", addKmers, estimated_T3_size)); // **** Count and insert false positives in T4 rewind(T2_file); addKmers = 0; while (fread(&kmer, sizeof(kmer), 1, T2_file)) if (fp->bloom4->contains(kmer)) addKmers++; fp->false_positives = new FPSet(addKmers); rewind(T2_file); addKmers = 0; NbInsertedKmers = 0; while (fread(&kmer, sizeof(kmer), 1, T2_file)) { if (fp->bloom4->contains(kmer)) { fp->false_positives->insert(kmer); addKmers++; } NbInsertedKmers++; // if ((NbInsertedKmers%10000)==0) // fprintf (stderr,"%cInsert false positive T4 %lld",13,NbInsertedKmers); } fp->false_positives->finalize(); // fprintf (stderr,"%cInsert false positive T4 %lld", 13,NbInsertedKmers); fclose(T2_file); DEBUGE(("\nInserted %d (estimated, %lld) kmers in T4.\n\n", addKmers, (uint64_t)fp->false_positives->capacity())); // print_size_summary(fp); return fp; } double toMB(double value) { return value / 8LL/1024LL/1024LL; } void print_size_summary(FPSet *fp) { int bits_per_FP_element = FPSet::bits_per_element; uint64_t size_B1 = b1_size, size_T1 = fp->capacity() * FPSet::bits_per_element; double total_size = (double)(size_B1 + size_T1); fprintf(stderr,"Size of the Bloom table : %.2lf MB\n", toMB(size_B1) ); fprintf(stderr," %.2lf bits / solid kmer\n", b1_size/(double)(nbkmers_solid) ); fprintf(stderr, "Size of the FP table : %lli FP x %d bits = %.2lf MB \n", fp->capacity(), bits_per_FP_element, toMB((double)(size_T1)) ); fprintf(stderr," actual implementation : %.2lf bits / solid kmer\n", size_T1/(double)nbkmers_solid); fprintf(stderr," assuming list of kmers, i.e. sizeof(kmer_type) bits / FP : %.2lf bits / solid kmer \n\n",(fp->capacity()*sizeof(kmer_type)*8LL)/(double)(nbkmers_solid)); fprintf(stderr," Total %.2lf MB for %lld solid kmers ==> %.2lf bits / solid kmer\n\n", toMB(total_size), nbkmers_solid, total_size / nbkmers_solid); } void print_size_summary(FPSetCascading4 *fp) { uint64_t size_B1 = b1_size, size_B2 = fp->bloom2->tai, size_B3 = fp->bloom3->tai, size_B4 = fp->bloom4->tai, size_T4 = fp->false_positives->capacity() * FPSet::bits_per_element; double total_size = (double)(size_B1 + size_B2 + size_B3 + size_B4 + size_T4); DEBUGE((stderr,"Size of the Bloom table (B1) : %.2lf MB\n", toMB((double)size_B1))); DEBUGE((stderr,"Size of the Bloom table (B2) : %.2lf MB\n", toMB((double)size_B2))); DEBUGE((stderr,"Size of the Bloom table (B3) : %.2lf MB\n", toMB((double)size_B3))); DEBUGE((stderr,"Size of the Bloom table (B4) : %.2lf MB\n", toMB((double)size_B4))); DEBUGE((stderr,"Size of the FP table (T4) : %.2lf MB\n", toMB((double)size_T4))); fprintf(stderr," Total %.2lf MB for %lld solid kmers ==> %.2lf bits / solid kmer\n\n", toMB(total_size), nbkmers_solid, total_size / nbkmers_solid); } discoSnp/minia/makefile0000644000000000000000000000327212365446234014150 0ustar rootrootCFLAGS+= -O4 -D_FILE_OFFSET_BITS=64 # needed to handle files > 2 GB on 32 bits systems SRC=Pool.cpp Bank.cpp Bloom.cpp Hash16.cpp LargeInt.cpp Kmer.cpp Terminator.cpp Traversal.cpp LinearCounter.cpp Set.cpp Utils.cpp SortingCount.cpp Debloom.cpp OAHash.cpp EXEC=minia OBJ= $(SRC:.cpp=.o) ifeq ($(prof),1) CFLAGS+= -pg endif ifeq ($(unitig),1) CFLAGS+= -DUNITIG endif ifeq ($(deb),1) CFLAGS+= -O0 -DASSERTS -g endif ifeq ($(omp),1) CFLAGS=-O4 -fopenmp -DOMP=1 endif k := 0$(k) # dummy k if not specified K_BELOW_32 := $(shell echo $(k)\<=32 | bc) K_BELOW_64 := $(shell echo $(k)\<=64 | bc) ARCH := $(shell getconf LONG_BIT) # detects sizeof(int) USING_UINT128 := 0 largeintlib := 0 ifeq ($(K_BELOW_32),0) # use uint128 when k<=64 and 64-bit architecture ifeq ($(K_BELOW_64),1) ifeq ($(strip $(ARCH)),64) CFLAGS += -Dkmer_type=__uint128_t USING_UINT128 := 1 endif endif # use a bigint library otherwise ifeq ($(USING_UINT128),0) largeintlib := largeint#ttmath endif endif # ttmath (now, largeint) is used when you type "make k=[kmer size]" with a kmer size longer than supported integer type, ifeq ($(largeintlib),ttmath) KMER_PRECISION := $(shell echo \($(k)+15\)/16 | bc) endif ifeq ($(largeintlib),largeint) KMER_PRECISION := $(shell echo \($(k)+31\)/32 | bc) endif ifneq ($(largeintlib),0) CFLAGS += -D_$(largeintlib) -DKMER_PRECISION=$(KMER_PRECISION) endif all: $(MAKE) clean $(MAKE) $(EXEC) minia: $(OBJ) Minia.cpp $(CXX) -o $@ $(OBJ) Minia.cpp $(CFLAGS) -lz %.o: %.cpp %.h $(CXX) -o $@ -c $< $(CFLAGS) %.o: %.c %.h $(CXX) -o $@ -c $< $(CFLAGS) clean: rm -rf *.o install: cp minia /usr/local/bin discoSnp/minia/Terminator.h0000644000000000000000000000440212115050446014726 0ustar rootroot// // Terminator.h #ifndef Terminator_h #define Terminator_h #include #include #include #include // for log2f #include "Bloom.h" #include "Kmer.h" #include "Set.h" #include "Bank.h" class Terminator{ protected: BinaryBank *SolidKmers; Bloom *bloom_solid_kmers; Set *debloom; unsigned char branching_structure(kmer_type graine); public: static bool verbose; virtual void mark(kmer_type graine, char nt, int strand){ return; }; virtual bool is_marked(kmer_type graine, char nt, int strand){ return (1); }; virtual void mark(kmer_type graine){ return; }; virtual bool is_marked(kmer_type graine){ return (1); }; virtual bool is_marked_branching(kmer_type graine) {return 1;}; virtual void reset() {return;}; bool is_branching(kmer_type graine); bool next(kmer_type *kmer); Terminator(BinaryBank *given_SolidKmers, Bloom *given_bloom, Set *given_debloom) : SolidKmers(given_SolidKmers), bloom_solid_kmers(given_bloom), debloom(given_debloom) { } }; class BloomTerminator { protected: Bloom * bloo2; BinaryBank *SolidKmers; public: // is there a way to not repeat the declaration of Terminator functions? bool is_fully_marked(kmer_type graine); void mark(kmer_type graine, char nt, int strand); bool is_marked(kmer_type graine, char nt, int strand); bool next(kmer_type *kmer); BloomTerminator(int tai_Bloom); ~BloomTerminator(); }; class BranchingTerminator: public Terminator{ bool is_indexed(kmer_type graine); int genome_size; // Hash16 *branching_kmers; AssocSet *branching_kmers; public: bool is_fully_marked(kmer_type graine); void mark(kmer_type graine, char nt, int strand); bool is_marked(kmer_type graine, char nt, int strand); void mark(kmer_type graine); bool is_marked(kmer_type graine); bool is_marked_branching(kmer_type graine); bool next(kmer_type *kmer); int64_t nb_branching_kmers; void dump_branching_kmers(BinaryBank *BranchingKmers); void reset(); BranchingTerminator(BinaryBank *given_SolidKmers, uint64_t genome_size, Bloom *given_bloom, Set *given_debloom); BranchingTerminator(BinaryBank *branchingKmers, BinaryBank *given_SolidKmers, Bloom *given_bloom, Set *given_debloom); ~BranchingTerminator(); }; #endif discoSnp/minia/GraphOutput.h0000644000000000000000000001361312405617254015100 0ustar rootroot#if __cplusplus > 199711L //#if __clang__ #include #include #else #include #include #endif #include #include // for exit() #include #include #include #include #include #include #include #include "../minia/Kmer.h" #include "../minia/Bank.h" #ifndef _GRAPHOUTPUT_H #define _GRAPHOUTPUT_H using namespace std; #if __cplusplus <= 199711L //#if ! __clang__ using namespace tr1; #endif // hash functions for unordered_map with various kmer_type's namespace std { //structure for print id nodes and edges in graph output struct id_els{ long node; long edge; }; #if __cplusplus <= 199711L //#if ! __clang__ namespace tr1 { #endif #ifdef _LP64 template <> struct hash<__uint128_t> : public unary_function<__uint128_t, size_t> { size_t operator()(const __uint128_t& elem) const { hash hash_func; return hash_func((uint64_t)(elem>>64)) ^ hash_func((uint64_t)(elem&((((__uint128_t)1)<<64)-1))); } }; #endif #ifdef _ttmath template <> struct hash > : public unary_function, size_t> { size_t operator()(const ttmath::UInt& elem) const { hash hash_func; // hash = XOR_of_series[hash(i-th chunk iof 64 bits) uint64_t result = 0, to_hash; ttmath::UInt intermediate = elem; uint32_t mask=~0, chunk; int i; for (i=0;i>= 32; (intermediate & mask).ToInt(chunk); to_hash |= ((uint64_t)chunk) << 32 ; intermediate >>= 32; result ^= hash_func(to_hash); } return result; } }; #endif #ifdef _largeint template <> struct hash > : public unary_function, size_t> { size_t operator()(const LargeInt& elem) const { hash hash_func; // hash = XOR_of_series[hash(i-th chunk iof 64 bits) uint64_t result = 0, to_hash; LargeInt intermediate = elem; uint32_t mask=~0, chunk; int i; for (i=0;i> 32; chunk = (intermediate & mask).toInt(); to_hash |= ((uint64_t)chunk) << 32 ; intermediate = intermediate >> 32; result ^= hash_func(to_hash,num_hash); } return result; } }; #endif #if __cplusplus <= 199711L //#if ! __clang__ } #endif } class GraphOutput { public: string prefix; string graph_file_name; string nodes_file_name; string edges_file_name; string json_starters_file_name; string xml_file_name; string json_nodes_file_name; string json_edges_file_name; string json_file_name; int graph_format; id_els first_id_els; long edge_id; // the json format needs an id on the nodes. static const string graph_file_suffix; static const string starters_file_suffix; static const string nodes_file_suffix; static const string edges_file_suffix; static const string xml_file_suffix; static const string json_starters_file_suffix; static const string json_nodes_file_suffix; static const string json_edges_file_suffix; static const string json_file_suffix; bool original; // The extended kmer comes originally from the starter (true), or (false) if is it a degenerated kmer (one substitution or one indel). FILE *graph_file,*nodes_file,*edges_file,*starters_file; GraphOutput(string prefix, int graph_format); GraphOutput(string prefix, int graph_format, id_els first_id_els); //PIERRE GraphOutput(string prefix); GraphOutput(string prefix, id_els first_id_els); //PIERRE void close(); long sequence_length(string line); void print_node(long index, char *ascii_node); void print_edge(long index, long id, long id2, string label); void print_edge(long index, long id, long id2, string label, string comment); void print_starter_head(int index, char* sequence); void print_starter_end(); enum LeftOrRight { LEFT=0, RIGHT=1 }; enum Strand { FW=0, RC=1 }; struct node_strand { long node; Strand strand; LeftOrRight left_or_right; node_strand(long node, Strand strand, LeftOrRight left_or_right) : node(node), strand(strand), left_or_right(left_or_right) {} bool operator<(const node_strand &other) const { if (node != other.node) return (node < other.node); if (left_or_right != other.left_or_right) return left_or_right < other.left_or_right; return (strand < other.strand); } }; #if __cplusplus > 199711L //#if __clang__ std::unordered_map > kmer_links; #else std::tr1::unordered_map > kmer_links; #endif id_els construct_graph(string linear_seqs_name, const string direction); // PIERRE: added the return value id_els construct_graph(string linear_seqs_name); // PIERRE: added the return value void load_nodes_extremities(string linear_seqs_name); private: void init(bool erase); // PIERRE }; #endif //_GRAPHOUTPUT_H discoSnp/minia/Minia.cpp0000644000000000000000000002776712365446234014230 0ustar rootroot#include #include #include #include #include #include #include #include #include // for max/min #include // for sorting_kmers #include #define NNKS 4 // default minimal abundance for solidity #define MIN_CONTIG_SIZE (2*sizeKmer+1) int max_memory; // the most memory one should alloc at any time, in MB int order = 0; // deblooming order; 0 = debloom everything; 1 = don't debloom 1-node tips (experimental, untested, shouldn't work);// (made extern int in Traversal.h) #include "Bank.h" #include "Hash16.h" #include "Set.h" #include "Pool.h" #include "Bloom.h" #include "Debloom.h" #include "Utils.h" #include "SortingCount.h" #include "Terminator.h" #include "Kmer.h" #include "Traversal.h" #include "rvalues.h" // for 4bloom int64_t genome_size; Bloom * bloo1; inline void assemble() { //////------------------------------------------------------------------------------------------- fprintf (stderr,"______________________________________________________ \n"); fprintf (stderr,"___________ Assemble from bloom filter _______________ \n"); fprintf (stderr,"______________________________________________________ \n\n"); //////------------------------------------------------------------------------------------------- long long len_left = 0; long long len_right = 0; long long contig_len =0; long long maxlen=10000000; char *left_traversal = (char *) malloc(maxlen*sizeof(char)); char *right_traversal = (char *) malloc(maxlen*sizeof(char)); char *contig = (char *) malloc(2*(maxlen+sizeKmer)*sizeof(char)); kmer_type kmer; long long nbContig =0; long long nbSmallContig =0; long long totalnt=0; long long max_contig_len=0; long long mlenleft=0,mlenright=0; int64_t NbBranchingKmer=0; char kmer_seq[sizeKmer+1]; FILE * file_assembly = fopen(return_file_name(assembly_file),"w+"); BinaryBank *SolidKmers = new BinaryBank(return_file_name(solid_kmers_file),sizeof(kmer_type),0); STARTWALL(assembly); char *assemble_only_one_region = NULL; // debugging, set to a ASCII kmer to activate, NULL to desactivate bool LOAD_BRANCHING_KMERS=false; // debugging bool DUMP_BRANCHING_KMERS=false; BranchingTerminator *terminator; if (LOAD_BRANCHING_KMERS) { BinaryBank *BranchingKmers = new BinaryBank(return_file_name(branching_kmers_file),sizeof(kmer_type),false); terminator = new BranchingTerminator(BranchingKmers,SolidKmers, bloo1,false_positives); BranchingKmers->close(); } else terminator = new BranchingTerminator(SolidKmers,genome_size, bloo1,false_positives); if (DUMP_BRANCHING_KMERS) { BinaryBank *BranchingKmers = new BinaryBank(return_file_name(branching_kmers_file),sizeof(kmer_type),true); terminator->dump_branching_kmers(BranchingKmers); BranchingKmers->close(); } #ifdef UNITIG SimplePathsTraversal *traversal = new SimplePathsTraversal(bloo1,false_positives,terminator); fprintf (stderr,"_________________Assembling in Unitig mode ..._____________________ \n\n"); #else MonumentTraversal *traversal = new MonumentTraversal(bloo1,false_positives,terminator); #endif //RandomBranchingTraversal *traversal = new RandomBranchingTraversal(bloo1,false_positives,terminator); traversal->set_maxlen(maxlen); traversal->set_max_depth(500); traversal->set_max_breadth(20); while (terminator->next(&kmer)) { // keep looping while a starting kmer is available from this kmer // everything will be marked during the traversal()'s kmer_type starting_kmer; #ifdef UNITIG while (traversal->get_new_starting_node_improved(kmer,starting_kmer)) #else while (traversal->find_starting_kmer(kmer,starting_kmer)) #endif { code2seq(starting_kmer,kmer_seq); // convert starting kmer to nucleotide seq traversal->revert_stats(); // set stats from the last commit (discard stats from find_starting_kmer / small contigs) if (assemble_only_one_region != NULL) { kmer_type dummy; starting_kmer = extractKmerFromRead(assemble_only_one_region,0,&kmer,&dummy,false); } // right extension len_right = traversal->traverse(starting_kmer,right_traversal,0); mlenright= max(len_right,mlenright); // left extension, is equivalent to right extension of the revcomp len_left = traversal->traverse(starting_kmer,left_traversal,1); mlenleft= max(len_left,mlenleft); // form the contig revcomp_sequence(left_traversal,len_left); strcpy(contig,left_traversal); // contig = revcomp(left_traversal) strcat(contig,kmer_seq);// + starting_kmer strcat(contig,right_traversal);// + right_traversal contig_len=len_left+len_right+sizeKmer; // save the contig if(contig_len >= MIN_CONTIG_SIZE) { max_contig_len = max(max_contig_len,contig_len); fprintf(file_assembly,">%lli__len__%lli \n",nbContig,contig_len); fprintf(file_assembly,"%s\n",contig); nbContig++; totalnt+=contig_len; traversal->commit_stats(); } else { traversal->revert_stats(); nbSmallContig++; } if (assemble_only_one_region != NULL) break; } NbBranchingKmer++; if ((NbBranchingKmer%300)==0) fprintf (stderr,"%cLooping through branching kmer n° %lld / %lld total nt %lld ",13,(long long int) NbBranchingKmer,(long long int) terminator->nb_branching_kmers, (long long int)totalnt ); if (nbContig > 0 && assemble_only_one_region != NULL) break; } fclose(file_assembly); fprintf (stderr,"\n Total nt assembled %lli nbContig %lli\n",totalnt,nbContig); fprintf (stderr," Max contig len %lli (debug: max len left %lli, max len right %lli)\n",max_contig_len,mlenleft,mlenright); fprintf (stderr,"\n Debug traversal stats: %ld ends of contigs (%lld unsaved small contigs), among them:\n",traversal->final_stats.ended_traversals,nbSmallContig); fprintf (stderr," %ld couldn't validate consensuses\n",traversal->final_stats.couldnt_validate_consensuses); fprintf (stderr," %ld large bubble breadth, %ld large bubble depth, %ld marked kmer, %ld no extension\n",traversal->final_stats.couldnt_traverse_bubble_breadth,traversal->final_stats.couldnt_traverse_bubble_depth,traversal->final_stats.couldnt_because_marked_kmer,traversal->final_stats.couldnt_find_extension); fprintf (stderr," %ld in-branchin large depth, %ld in-branching large breadth, %ld in-branching other\n",traversal->final_stats.couldnt_inbranching_depth,traversal->final_stats.couldnt_inbranching_breadth,traversal->final_stats.couldnt_inbranching_other); STOPWALL(assembly,"Assembly"); free(left_traversal); free(right_traversal); free(contig); SolidKmers->close(); } int main(int argc, char *argv[]) { if(argc < 6) { fprintf (stderr,"usage:\n"); fprintf (stderr," %s input_file kmer_size min_abundance estimated_genome_size prefix\n",argv[0]); fprintf (stderr,"hints:\n min_abundance ~ 3\n estimated_genome_size is in bp, does not need to be accurate, only controls memory usage\n prefix is any name you want the results to start with\n"); return 1; } bool FOUR_BLOOM_VERSION = true; // shortcuts to go directly to assembly using serialized bloom and serialized hash int START_FROM_SOLID_KMERS=0; // if = 0, construct the fasta file of solid kmers, if = 1, start directly from that file int LOAD_FALSE_POSITIVE_KMERS=0; // if = 0, construct the fasta file of false positive kmers (debloom), if = 1, load that file into the hashtable int NO_FALSE_POSITIVES_AT_ALL=0; // if = 0, normal behavior, if = 1, don't load false positives (will be a probabilistic de bruijn graph) int max_disk_space = 0;// let dsk decide for (int n_a = 6; n_a < argc ; n_a++) { if (strcmp(argv[n_a],"--original") == 0) FOUR_BLOOM_VERSION = false; if (strcmp(argv[n_a],"--dont-count")==0) START_FROM_SOLID_KMERS = 1; if (strcmp(argv[n_a],"--dont-debloom")==0) LOAD_FALSE_POSITIVE_KMERS = 1; if (strcmp(argv[n_a],"--just-assemble")==0) { START_FROM_SOLID_KMERS = 1; LOAD_FALSE_POSITIVE_KMERS = 1; } if (strcmp(argv[n_a],"--titus-mode")==0) NO_FALSE_POSITIVES_AT_ALL = 1; if (strcmp(argv[n_a],"-d")==0) max_disk_space = atoi(argv[n_a+1]); if (strcmp(argv[n_a],"-maxc")==0) max_couv = atoi(argv[n_a+1]); if (strcmp(argv[n_a],"--le-changement")==0) {printf("c'est maintenant!\n");exit(0);} } // kmer size sizeKmer=27; // let's make it even for now, because i havnt thought of how to handle palindromes (dont want to stop on them) if(argc >= 3) { sizeKmer = atoi(argv[2]); if (sizeKmer%2==0) { sizeKmer-=1; printf("Need odd kmer size to avoid palindromes. I've set kmer size to %d.\n",sizeKmer); } if (sizeKmer>((int)sizeof(kmer_type)*4)) { printf("Max kmer size on this compiled version is %lu\n",sizeof(kmer_type)*4); exit(1); } } if (sizeKmer == (int)(sizeof(kmer_type)*4)) kmerMask = -1; else kmerMask=(((kmer_type)1)<<(sizeKmer*2))-1; double lg2 = log(2); if (sizeKmer > 128) { FOUR_BLOOM_VERSION = false; printf("Reverted to single Bloom filter implementation for k>128\n"); } if (!FOUR_BLOOM_VERSION) NBITS_PER_KMER = log(16*sizeKmer*(lg2*lg2))/(lg2*lg2); // needed to process argv[5] else NBITS_PER_KMER = rvalues[sizeKmer][1]; // solidity nks =NNKS; if(argc >= 4) { nks = atoi(argv[3]); if (nks==0) nks=1; // min abundance can't be 0 } if(argc >= 5) { genome_size = atoll(argv[4]); // int estimated_bloom_size = max( (int)ceilf(log2f(genome_size * NBITS_PER_KMER )), 1); uint64_t estimated_bloom_size = (uint64_t) (genome_size * NBITS_PER_KMER); uint64_t estimated_nb_FP = (uint64_t)(genome_size * 4 * powf(0.6,11)); // just indicative //max_memory = max( (1LL << estimated_bloom_size)/8LL /1024LL/1024LL, 1LL ); max_memory = max((int64_t) estimated_bloom_size/8LL /1024LL/1024LL,1LL); printf("estimated values: nbits Bloom %lli, nb FP %lld, max memory %i MB\n",estimated_bloom_size,estimated_nb_FP,max_memory); } // output prefix if(argc >= 6) { strcpy(prefix,argv[5]); } fprintf (stderr,"taille cell %lu \n", sizeof(cell)); STARTWALL(0); Bank *Reads = new Bank(argv[1]); // counter kmers, write solid kmers to disk if (!START_FROM_SOLID_KMERS) { int verbose = 0; bool write_count = false; bool skip_binary_conversion = false; sorting_count(Reads,prefix,max_memory,max_disk_space,write_count,verbose, skip_binary_conversion); } // debloom, write false positives to disk, insert them into false_positives if (! LOAD_FALSE_POSITIVE_KMERS) { debloom(order, max_memory); } bloo1 = bloom_create_bloo1((BloomCpt *)NULL, false); if (! NO_FALSE_POSITIVES_AT_ALL) { // load false positives from disk into false_positives if (!FOUR_BLOOM_VERSION) false_positives = load_false_positives(); else false_positives = load_false_positives_cascading4(); } else { // titus mode: no FP's false_positives = dummy_false_positives(); } // return 1; assemble(); STOPWALL(0,"Total"); delete Reads; return 0; } discoSnp/minia/Bloom.h0000644000000000000000000001133112062133074013651 0ustar rootroot// // Bloom.h // // Created by Guillaume Rizk on 9/02/12. // #ifndef Bloom_h #define Bloom_h #include #include #include // not using kmer_type from Kmer.h because I don't want this class to depend on Kmer.h #ifdef _largeint #include "LargeInt.h" typedef LargeInt bloom_elem; #else #ifdef _ttmath #include "ttmath/ttmath.h" typedef ttmath::UInt bloom_elem; #else #if (! defined kmer_type) || (! defined _LP64) typedef uint64_t bloom_elem; #else typedef kmer_type bloom_elem; #endif #endif #endif #define NSEEDSBLOOM 10 #define CUSTOMSIZE 1 static const int bits_per_char = 0x08; // 8 bits in 1 char(unsigned) static const unsigned char bit_mask[bits_per_char] = { 0x01, //00000001 0x02, //00000010 0x04, //00000100 0x08, //00001000 0x10, //00010000 0x20, //00100000 0x40, //01000000 0x80 //10000000 }; static const int cpt_per_char = 2; static const unsigned char cpt_mask[cpt_per_char] = { 0x0F, //00001111 0xF0, //11110000 }; static const uint64_t cpt_mask21[21] = { 0x0000000000000007ULL,//00000....00000111 0x0000000000000038ULL, 0x00000000000001C0ULL, 0x0000000000000E00ULL, 0x0000000000007000ULL, 0x0000000000038000ULL, 0x00000000001C0000ULL, 0x0000000000E00000ULL, 0x0000000007000000ULL, 0x0000000038000000ULL, 0x00000001C0000000ULL, 0x0000000E00000000ULL, 0x0000007000000000ULL, 0x0000038000000000ULL, 0x00001C0000000000ULL, 0x0000E00000000000ULL, 0x0007000000000000ULL, 0x0038000000000000ULL, 0x01C0000000000000ULL, 0x0E00000000000000ULL, 0x7000000000000000ULL }; static const uint64_t cpt_mask32[32] = { 0x0000000000000003ULL,//00000....00000011 0x000000000000000CULL, 0x0000000000000030ULL,//00000....000110000 0x00000000000000C0ULL, 0x0000000000000300ULL, 0x0000000000000C00ULL, 0x0000000000003000ULL, 0x000000000000C000ULL, 0x0000000000030000ULL, 0x00000000000C0000ULL, 0x0000000000300000ULL, 0x0000000000C00000ULL, 0x0000000003000000ULL, 0x000000000C000000ULL, 0x0000000030000000ULL, 0x00000000C0000000ULL, 0x0000000300000000ULL, 0x0000000C00000000ULL, 0x0000003000000000ULL, 0x000000C000000000ULL, 0x0000030000000000ULL, 0x00000C0000000000ULL, 0x0000300000000000ULL, 0x0000C00000000000ULL, 0x0003000000000000ULL, 0x000C000000000000ULL, 0x0030000000000000ULL, 0x00C0000000000000ULL, 0x0300000000000000ULL, 0x0C00000000000000ULL, 0x3000000000000000ULL, 0xC000000000000000ULL }; /* static const unsigned char incr_cpt_table[2][255] = { {1, 2,3}, {3, 4,3}, }; */ static const uint64_t rbase[NSEEDSBLOOM] = { 0xAAAAAAAA55555555ULL, 0x33333333CCCCCCCCULL, 0x6666666699999999ULL, 0xB5B5B5B54B4B4B4BULL, 0xAA55AA5555335533ULL, 0x33CC33CCCC66CC66ULL, 0x6699669999B599B5ULL, 0xB54BB54B4BAA4BAAULL, 0xAA33AA3355CC55CCULL, 0x33663366CC99CC99ULL }; /* 0x2E7E5A8996F99AA5, 0x74B2E1FB222EFD24, 0x8BBE030F6704DC29, 0x6D8FD7E91C11A014, 0xFC77642FF9C4CE8C, 0x318FA6E7C040D23D, 0xF874B1720CF914D5, 0xC569F575CDB2A091, */ //static uint64_t pri1=0x5AF3107A401FULL; //static uint64_t pri2 =0x78C27CE77ULL; class Bloom{ protected: #ifdef _largeint inline uint64_t hash_func(LargeInt elem, int num_hash); #endif #ifdef _ttmath inline uint64_t hash_func(ttmath::UInt elem, int num_hash); #endif #ifdef _LP64 inline uint64_t hash_func(__uint128_t key, int num_hash); #endif inline uint64_t hash_func(uint64_t key, int num_hash); inline void generate_hash_seed(); uint64_t user_seed; uint64_t seed_tab[NSEEDSBLOOM]; int n_hash_func; uint64_t nchar; public: unsigned char * blooma; void setSeed(uint64_t seed) ; void set_number_of_hash_func(int i) ; void add(bloom_elem elem); int contains(bloom_elem elem); uint64_t tai; uint64_t nb_elem; void dump(char * filename); void load(char * filename); long weight(); Bloom(int tai_bloom); Bloom(uint64_t tai_bloom); Bloom(); ~Bloom(); }; class BloomCpt: public Bloom { public : BloomCpt(int tai_bloom); BloomCpt(); void add(bloom_elem elem); int contains_n_occ(bloom_elem elem, int nks); }; class BloomCpt3: public BloomCpt { public : BloomCpt3(int tai_bloom); ~BloomCpt3(); uint64_t * blooma3; void add(bloom_elem elem); int contains_n_occ(bloom_elem elem, int nks); }; class BloomCpt2: public BloomCpt { public : BloomCpt2(int tai_bloom); ~BloomCpt2(); uint64_t * blooma2; void add(bloom_elem elem); int contains_n_occ(bloom_elem elem, int nks); }; #endif discoSnp/minia/GraphOutput.cpp0000644000000000000000000003527512405617254015443 0ustar rootroot#include "GraphOutput.h" const string GraphOutput::graph_file_suffix = ".graph"; const string GraphOutput::nodes_file_suffix = ".nodes"; const string GraphOutput::edges_file_suffix = ".edges"; const string GraphOutput::xml_file_suffix = ".xgmml"; const string GraphOutput::json_nodes_file_suffix = ".json_nodes"; const string GraphOutput::json_edges_file_suffix = ".json_edges"; const string GraphOutput::json_file_suffix = ".json"; /************************************************************************************************************************/ /* init function initialize the files need to construct graph file or sequences file */ /* */ /************************************************************************************************************************/ void GraphOutput::init(bool erase){ //printf("create a graph erase=%s graph_format=%d first_id_nodes=%d first_id_edges=%d\n"", erase?"true":"false", graph_format, first_id_els.node, first_id_els.edge); graph_file_name=(prefix+graph_file_suffix); nodes_file_name=(prefix+nodes_file_suffix); edges_file_name=(prefix+edges_file_suffix); xml_file_name=(prefix+xml_file_suffix); json_nodes_file_name=(prefix+json_nodes_file_suffix); json_edges_file_name=(prefix+json_edges_file_suffix); json_file_name=(prefix+json_file_suffix); switch (graph_format){ case 0:// FORMAT .GRAPH graph_file = fopen(graph_file_name.c_str(),erase?"w":"a"); fprintf(graph_file,"digraph dedebruijn {\n"); break; case 1: // FORMAT .NODES AND .EDGES nodes_file = fopen(nodes_file_name.c_str(),erase?"w":"a"); edges_file = fopen(edges_file_name.c_str(),erase?"w":"a"); break; case 2 :// FORMAT .XGMML graph_file = fopen(xml_file_name.c_str(),erase?"w":"a"); //fprintf(graph_file,"\n\n\n"); fprintf(graph_file,"\n"); break; case 3: // FORMAT .json nodes_file = fopen(json_nodes_file_name.c_str(),erase?"w":"a"); edges_file = fopen(json_edges_file_name.c_str(),erase?"w":"a"); graph_file = fopen(json_file_name.c_str(),erase?"w":"a"); break; } } /************************************************************************************************************************/ /* printf GraphOutput and initialize files (files are not erasing) */ /* */ /************************************************************************************************************************/ GraphOutput::GraphOutput(string prefix, int graph_format, id_els first_id_els) : prefix(prefix), graph_format(graph_format), first_id_els(first_id_els) { // PIERRE: need something different than 0 for the first node printf("graph_format=%d first_id_nodes=%d first_id_edges=%d\n", graph_format, first_id_els.node, first_id_els.edge); init(true); } /************************************************************************************************************************/ /* Initialize first elements and files (files are erasing) */ /* */ /************************************************************************************************************************/ GraphOutput::GraphOutput(string prefix, int graph_format) : prefix(prefix), graph_format(graph_format) { first_id_els.node=0; first_id_els.edge=0; printf("graph_format=%d first_id_nodes=%d first_id_edges=%d\n", graph_format, first_id_els.node, first_id_els.edge); init(true); } /************************************************************************************************************************/ /* write graph file or sequence file */ /* */ /************************************************************************************************************************/ void GraphOutput::close() { switch (graph_format){ case 0: fprintf(graph_file,"}\n"); fclose(graph_file); break; case 1: fclose(nodes_file); fclose(edges_file); break; case 2: fprintf(graph_file,"\n"); fclose(graph_file); break; case 3: // We need to store all nodes and then all edges in the final .json file fclose(nodes_file); fclose(edges_file); ifstream nodes(json_nodes_file_name.c_str(), ios::in); ifstream edges(json_edges_file_name.c_str(), ios::in); if(!edges || !nodes){fprintf(stderr,"Cannot open file %s, %s or %s, exit\n", json_edges_file_suffix.c_str(), json_nodes_file_suffix.c_str()); exit(1);} string line; fprintf(graph_file,"{\n \"Starter\":[\n{"); fprintf(graph_file,"\n \"nodes\": [\n"); getline(nodes,line); fprintf(graph_file,"%s",line.c_str()); // prints the first node without comma before //for each node while(getline(nodes,line)){ fprintf(graph_file,",\n%s",line.c_str()); // prints the other nodes }; fprintf(graph_file,"\n],\n"); fprintf(graph_file,"\"edges\": [\n"); getline(edges,line); fprintf(graph_file,"%s",line.c_str()); // prints the first edge without comma before //for each edge while(getline(edges,line)) { fprintf(graph_file,",\n%s",line.c_str()); // prints the others edges }; //end of graph file en close file fprintf(graph_file,"\n]\n}\n"); nodes.close(); remove(json_nodes_file_name.c_str()); edges.close(); remove(json_edges_file_name.c_str()); fclose(graph_file); } } /************************************************************************************************************************/ /* recalculate length for a node (more efficient than capture length in string and convert the in integer) */ /* */ /************************************************************************************************************************/ long GraphOutput::sequence_length(string line) { string seq_char; int err,match,start, end; regex_t preg; long seq_len=0; size_t nmatch, size; const char *str_regex ="([A-Z]+)"; //regex capture sequences characters const char *line_c =NULL; line_c = line.c_str(); err = regcomp (&preg, str_regex, REG_EXTENDED); if (err == 0)//security for error string snapshot and if regex match { nmatch = 0; nmatch = preg.re_nsub; regmatch_t *pmatch=NULL; pmatch = (regmatch_t*) malloc (sizeof (*pmatch) * nmatch); if (pmatch) { match = regexec (&preg, line_c, nmatch, pmatch, 0); regfree (&preg); if (match == 0) { char *seq_char =NULL; start = pmatch[0].rm_so; end = pmatch[0].rm_eo; size = end - start; seq_len = sizeof(line_c[start])*(size); } } } else { fprintf (stderr, "LOW MEMORY !\n"); exit (EXIT_FAILURE); } return seq_len; } /************************************************************************************************************************/ /* output a single node to a file */ /* */ /************************************************************************************************************************/ void GraphOutput::print_node(long index, char *ascii_node) // output a single node to a file { int len; switch (graph_format){ case 0: // DOT format fprintf(graph_file,"%ld [label=\"%s\"];\n",index,ascii_node); break; case 1: // kissplice format fprintf(nodes_file,"%ld\t%s\n",index,ascii_node); break; case 2: // XGMML format fprintf(graph_file,"\n\n",index,ascii_node); break; case 3: // json format string seq = ascii_node; len = seq.size(); fprintf(nodes_file," { \"data\": { \"id\":\"%ld\", \"length\":%d, \"sequence\":\"%s\"}}\n",index,len,ascii_node); break; } } /************************************************************************************************************************/ /* output a single edges to a file */ /* */ /************************************************************************************************************************/ void GraphOutput::print_edge(long index, long id, long id2, string label) { switch (graph_format){ case 0: // DOT format fprintf(graph_file,"%ld -> %ld [label=\"%s\"];\n",id,id2,label.c_str()); break; case 1: // kissplice format fprintf(edges_file,"%ld\t%ld\t%s\n",id,id2,label.c_str()); break; case 2: // XGMML format fprintf(graph_file,"\n\n",id,id2,label.c_str()); break; case 3: // json format fprintf(edges_file,"{ \"data\":{ \"id\": \"%ld\", \"source\": \"%ld\",\"target\": \"%ld\",\"direction\": \"%s\"}}\n",index, id,id2,label.c_str()); //fprintf(edges_file,"{ \"data\":{ \"source\": %ld,\"target\": %ld,\"direction\": \"%s\"}}\n",id,id2,label.c_str()); break; } } /************************************************************************************************************************/ /* load nodes extremities */ /* */ /************************************************************************************************************************/ void GraphOutput::load_nodes_extremities(string linear_seqs_name) { kmer_links.clear(); // PIERRE: reset previous stored kmer links Bank *Nodes = new Bank((char *)linear_seqs_name.c_str()); long nb_nodes = first_id_els.node; //PIERRE; char * rseq; int readlen; sizeKmer--; // nodes extremities overlap by (k-1)-mers, so let's extract (k-1)-mers while (Nodes->get_next_seq(&rseq,&readlen)) { kmer_type left_kmer, right_kmer, left_kmer_fw, left_kmer_rc, right_kmer_fw, right_kmer_rc; left_kmer = extractKmerFromRead(rseq,0,&left_kmer_fw,&left_kmer_rc, false); right_kmer = extractKmerFromRead(rseq,readlen-sizeKmer,&right_kmer_fw,&right_kmer_rc, false); Strand left_strand = (left_kmer == left_kmer_fw)?FW:RC; Strand right_strand = (right_kmer == right_kmer_fw)?FW:RC; kmer_links[left_kmer].insert(node_strand(nb_nodes, left_strand, LEFT)); kmer_links[right_kmer].insert(node_strand(nb_nodes, right_strand, RIGHT)); nb_nodes++; } Nodes->close(); delete Nodes; sizeKmer++; // make sure to restore k } /************************************************************************************************************************/ /* construct node file and edge file for graph file */ /* */ /************************************************************************************************************************/ id_els GraphOutput::construct_graph(string linear_seqs_name) // PIERRE: i need to know the last nb_nodes { Bank *Nodes = new Bank((char *)linear_seqs_name.c_str()); id_els nb_els = first_id_els; //Alexan: stucture for print id elements in graph output char * rseq; int readlen; Nodes->rewind_all(); sizeKmer--; // nodes extremities overlap by (k-1)-mers, so let's extract (k-1)-mers // for each node, output all the out-edges (in-edges will correspond to out-edges of neighbors) while (Nodes->get_next_seq(&rseq,&readlen)) { kmer_type left_kmer, right_kmer, left_kmer_fw, left_kmer_rc, right_kmer_fw, right_kmer_rc; set::iterator it; left_kmer = extractKmerFromRead(rseq,0,&left_kmer_fw,&left_kmer_rc, false); right_kmer = extractKmerFromRead(rseq,readlen-sizeKmer,&right_kmer_fw,&right_kmer_rc, false); Strand left_strand = (left_kmer == left_kmer_fw)?FW:RC; Strand right_strand = (right_kmer == right_kmer_fw)?FW:RC; // left edges (are revcomp extensions) for (it = kmer_links[left_kmer].begin(); it != kmer_links[left_kmer].end(); it++) { long cur_node = it->node; Strand cur_strand = it->strand; LeftOrRight cur_left_or_right = it->left_or_right; if (cur_node ==nb_els.node) // prevent self loops on same kmer if (readlen == sizeKmer) continue; string label = "R"; if (cur_left_or_right == LEFT) { if (cur_strand != left_strand) label+=(string)"F"; else continue; } else { if (cur_strand == left_strand) label+=(string)"R"; else continue; } print_edge(nb_els.edge, nb_els.node,cur_node,label); nb_els.edge++; } // right edges for (it = kmer_links[right_kmer].begin(); it != kmer_links[right_kmer].end(); it++) { long cur_node = it->node; Strand cur_strand = it->strand; LeftOrRight cur_left_or_right = it->left_or_right; if (cur_node == nb_els.node) // prevent self loops on same kmer if (readlen == sizeKmer) continue; string label = "F"; if (cur_left_or_right == LEFT) { if (cur_strand == right_strand) label+=(string)"F"; else continue; } else { if (cur_strand != right_strand) label+=(string)"R"; else continue; } print_edge(nb_els.edge, nb_els.node,cur_node,label); nb_els.edge++; } //nodes print_node(nb_els.node, rseq); nb_els.node++; } sizeKmer++; // make sure to restore k Nodes->close(); delete Nodes; return nb_els; } discoSnp/minia/Utils.cpp0000644000000000000000000005611112424137004014240 0ustar rootroot#include "Utils.h" #include "Bank.h" // some globals that don't really belong anywhere int nks; // min abundance uint32_t max_couv = 2147483646; // note: uint_abundance_t is 32 bits in SortingCount.cpp struct timeval tim; uint64_t nbkmers_solid = 0, b1_size = 0; const char *solid_kmers_file = (char *)"solid_kmers_binary"; const char *false_positive_kmers_file = (char *)"false_positive_kmers"; const char *bloom_file = (char *)"bloom_data"; const char *assembly_file = (char *)"contigs.fa"; const char *branching_kmers_file = (char *)"branching_kmers"; // (only useful for multiple assemblies with same bloom&debloom structure (ie debugging)) const char *binary_read_file = (char *)"reads_binary"; const char *histo_file_name = (char *)"histo"; const char *breakpoints_file_name = (char *)"breakpoints"; const char *assoc_kmer_file = (char *)"paired_kmer"; // prefix-based output files naming char prefix[1024]; char fileName[1024]; char *return_file_name(const char *suffix) { if (strlen(prefix)>0) sprintf(fileName,"%s.%s",prefix,suffix); else sprintf(fileName,"%s",suffix); return fileName; } int readlen; #ifndef NO_BLOOM_UTILS template // T can be Bloom, BloomCpt, BloomCpt3 or LinearCounter (just needs to support add(kmer_type) and possibly contains(kmer_type)) // U can be BloomCpt or BloomCpt3 void bloom_pass_reads(Bank *Sequences, T *bloom_to_insert, U *bloom_counter, char *stderr_message) { int64_t NbRead = 0; int64_t NbInsertedKmers = 0; Sequences->rewind_all(); char * rseq; long i; kmer_type kmer, graine, graine_revcomp; while (Sequences->get_next_seq(&rseq,&readlen)) { for (i=0; icontains_n_occ(kmer,nks)) continue; } bloom_to_insert->add(kmer); NbInsertedKmers++; } NbRead++; if ((NbRead%10000)==0) fprintf (stderr,stderr_message,13,NbRead); } // fprintf (stderr,"\nInserted %lld %s kmers in the bloom structure.\n",(long long)NbInsertedKmers,"(redundant)"); } template // T can be Bloom, BloomCpt or BloomCpt3 void bloom_pass_reads_binary(T *bloom_to_insert, BloomCpt *bloom_counter, char *stderr_message) { //fprintf(stderr,"binary pass \n"); int64_t NbRead = 0; int64_t NbInsertedKmers = 0; kmer_type kmer; // read solid kmers from disk BinaryBank * SolidKmers = new BinaryBank(return_file_name(solid_kmers_file),sizeof(kmer),0); while(SolidKmers->read_element(&kmer)) { // printf("kmer %lld\n",kmer); bloom_to_insert->add(kmer); NbInsertedKmers++; NbRead++; if ((NbRead%10000)==0) fprintf (stderr,stderr_message,13,(long long)NbRead); } // fprintf (stderr,"\nInserted %lld %s kmers in the bloom structure.\n",(long long)NbInsertedKmers,"solid"); SolidKmers->close(); } int estimated_BL1; uint64_t estimated_BL1_freesize; float NBITS_PER_KMER = 11 ; // number of bits per kmer that optimizes bloo1 size // loading bloom from disk template //bloocpt or bloocpt3 Bloom *bloom_create_bloo1(T *bloom_counter, bool from_dump) { BinaryBank * SolidKmers ; if(from_dump && nsolids) // from dump and known number of solid kmers { //nsolids is sotred in a config file //number of solid kmers cannot be computed precisely from bloom file, imprecision of 0-7 estimated_BL1 = max( (int)ceilf(log2f(nsolids*NBITS_PER_KMER)), 1); estimated_BL1_freesize = (uint64_t)(nsolids*NBITS_PER_KMER); b1_size = (uint64_t) estimated_BL1_freesize; nbkmers_solid = nsolids ; // for correct printf in print_size_summary printf("load bloom from dump, containing %lli solid kmers b1_size %lli\n",nsolids,b1_size); } else { // get true number of solid kmers, in order to precisely size the bloom filter SolidKmers = new BinaryBank(return_file_name(solid_kmers_file),sizeof(kmer_type),0); estimated_BL1 = max( (int)ceilf(log2f(SolidKmers->nb_elements()*NBITS_PER_KMER)), 1); estimated_BL1_freesize = (uint64_t)(SolidKmers->nb_elements()*NBITS_PER_KMER); //printf("nelem %lli nbits %g \n",(long long)(SolidKmers->nb_elements()),NBITS_PER_KMER); } //printf("Allocating %0.1f MB of memory for the main Bloom structure (%g bits/kmer)\n",(1LL<set_number_of_hash_func((int)floorf(0.7*NBITS_PER_KMER)); if (from_dump) bloo1->load(return_file_name(bloom_file)); // just load the dump else { bloom_pass_reads_binary(bloo1, bloom_counter, (char*)"%cInsert solid Kmers in Bloom %lld"); // use the method reading SolidKmers binary file, was useful when varying Bloom size (!= dumped size) //bloo1->dump(return_file_name(bloom_file)); // create bloom dump SolidKmers->close(); } return bloo1; } // wrapper for default behavior: don't load from dump template //bloocpt or bloocpt3 Bloom *bloom_create_bloo1(T *bloom_counter) { return bloom_create_bloo1(bloom_counter, false); } template Bloom *bloom_create_bloo1(BloomCpt *bloom_counter); // trick to avoid linker errors: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13 template Bloom *bloom_create_bloo1(BloomCpt *bloom_counter, bool from_dump); // -------------------------------------------------------------------------------- // below this line: unused kmer counting code FILE * F_kmercpt_read; FILE * F_kmercpt_write; //in last partition : create solid kmers file, and load solid kmers in bloo1 bloom void end_kmer_count_partition(bool last_partition, Hash16 *hasht1) { int value; int cptk=0; int64_t nso=0; /////////////////////////begin write files rewind (F_kmercpt_read); rewind (F_kmercpt_write); #ifndef MINGW ftruncate(fileno(F_kmercpt_write), 0); //erase previous file #else // tempfix? fileno is not accepted by mingw fclose(F_kmercpt_write); F_kmercpt_write = fopen("kmer_count2","wb+"); #endif BinaryBank * SolidKmers = NULL; kmer_type graine; if (last_partition) SolidKmers = new BinaryBank(return_file_name(solid_kmers_file),sizeof(kmer_type),1); while(fread(&graine, sizeof(graine),1, F_kmercpt_read)){ fread(&cptk, sizeof(cptk), 1, F_kmercpt_read); hasht1->remove(graine,&value); // if graine is present, get value of graine and remove graine, else value=0 cptk += value; fwrite(&graine, sizeof(graine), 1, F_kmercpt_write); fwrite(&cptk, sizeof(cptk), 1, F_kmercpt_write); if (last_partition && cptk >= nks) // if last partition, also need to search for solid kmers in remaining of hasht1, so this is not enough: { SolidKmers->write_element(&graine); nso++; } } hasht1->dump(F_kmercpt_write); // dump remaining of hasht1 if (last_partition) { nso+=hasht1->getsolids(NULL,SolidKmers,nks); // get remaining solids of hasht1 fprintf(stderr,"nsolid kmers = %lli \n",(long long)nso); SolidKmers->close(); #ifndef MINGW ftruncate(fileno(F_kmercpt_read), 0); //erase previous file #else // tempfix? fileno is not accepted by mingw fclose(F_kmercpt_read); F_kmercpt_read = fopen("kmer_count2","wb+"); #endif } } template void exact_kmer_count(Bank *Sequences, T *bloom_counter, unsigned long max_memory) { FILE * count_file = fopen("kmer_count","wb+"); FILE * count_file_2 = fopen("kmer_count2","wb+"); FILE * F_tmp; F_kmercpt_read = count_file ; F_kmercpt_write = count_file_2; Sequences->rewind_all(); unsigned int max_kmer_per_part = max_memory*1024LL*1024LL /sizeof(cell); int numpart = 0; char * rseq; long i; int64_t NbRead = 0; int64_t NbInserted = 0; int64_t NbInserted_unique = 0; kmer_type kmer, graine, graine_revcomp; // that code makes hasht1 occupy full memory. should probably be reduced (but we're deprecating that procedure, right?) int NBITS_HT = max( (int)ceilf(log2f((max_memory*1024L*1024L)/sizeof(cell_ptr_t))), 1); Hash16 *hasht1 =new Hash16(NBITS_HT); // partitioned exact kmer counting based on Bloom filter for solidity: // the bloom filter enables membership test for a set S of supposedly solid kmers (contains false positives) // read the (redundant) kmers from the reads, and load only those in S, in chunks, into a hash table // at each pass, update a file containing the true count of non-redundant supposedly solid kmers (S) // at the end, analyze the file to keep only those with true count >= solid while (Sequences->get_next_seq(&rseq,&readlen)) { for (i=0; icontains_n_occ(kmer,nks)) continue; //insert into hasht1 NbInserted_unique += hasht1->add(kmer); NbInserted++; if(hasht1->nb_elem >max_kmer_per_part) //end partition { fprintf(stderr,"End of Kmer count partition %lli / %i \n",(long long)(hasht1->nb_elem),max_kmer_per_part); if(numpart==0) hasht1->dump(F_kmercpt_write); else end_kmer_count_partition(false,hasht1); //swap file pointers F_tmp = F_kmercpt_read; F_kmercpt_read = F_kmercpt_write; F_kmercpt_write = F_tmp; /////////end write files //reset hash table hasht1->empty_all(); numpart++; } ///end partition } NbRead++; if ((NbRead%10000)==0) fprintf (stderr,"%cLoop through reads for exact kmer count %lld",13,(long long)NbRead); } fprintf (stderr," \nTotal Inserted in hash (ie output of Bloom) unique %lli / %lli redundants \n",(long long)NbInserted_unique,(long long)NbInserted); ///////////////////////// last partition end_kmer_count_partition(true,hasht1); delete hasht1; } void bloom_count(Bank *Reads, unsigned long max_memory) { #define NBITS_BLOOMCPT 23 // 33 :4GB (4 bits/elem) // size of the bloom counter table to count kmers fprintf(stderr,"nbits bloom counter: %i \n",NBITS_BLOOMCPT); BloomCpt3 * bloocpt = new BloomCpt3(NBITS_BLOOMCPT); BloomCpt3 * bloocpt2 = new BloomCpt3(NBITS_BLOOMCPT); bloocpt->setSeed( 0x4909FEA3A68CC6A7LL); bloocpt2->setSeed( 0x0CD5DA28467C5492LL); // bloocpt->set_number_of_hash_func(4); // bloocpt2->set_number_of_hash_func(6); ///////////////////////////////////first pass ; count kmers with Bloom cpt bloom_pass_reads(Reads,bloocpt, (BloomCpt * ) NULL, (char*)"%cFirst pass %lld"); fprintf (stderr,"\n ____________ Second bloom counter _________\n"); bloom_pass_reads(Reads,bloocpt2, bloocpt, (char*)"%cSecond pass %lld"); STARTWALL(count); fprintf(stderr,"\n------------------ second pass bloom counter \n\n"); delete bloocpt; ////////////////////////////////////// exact kmer count with hash table partitionning, //also create solid kmers file and fills bloo1 exact_kmer_count(Reads,bloocpt2,max_memory); ////////////////////////////////////// STOPWALL(count,"Counted kmers"); fprintf(stderr,"\n------------------ Counted kmers and kept those with abundance >=%i \n\n",nks); ////////////////////////////////////////////////////fin bloom insert //delete bloocpt2; } void estimate_distinct_kmers(unsigned long genome_size, Bank *Reads) { int size_linearCounter = genome_size * 8; // alloc 8 bits * genome size for counting, i.e. ~ as much as the assembly Bloom size LinearCounter *linearCounter = new LinearCounter(size_linearCounter); bloom_pass_reads(Reads,linearCounter, (BloomCpt * ) NULL, (char*)"%cEstimating number of distinct kmers (%lld reads processed so far)"); long nb_distinct_kmers = linearCounter->count(); if (linearCounter->is_accurate()) printf("Estimated that %ld distinct kmers are in the reads\n",nb_distinct_kmers); else printf("Cannot estimate the number of distinct kmers. Allocate a larger counter\n"); delete linearCounter; } uint64_t extrapolate_distinct_kmers(Bank *Reads) { // start with 100MB RAM estimation and grow if necessary return extrapolate_distinct_kmers_wrapped(100000000L, Reads); } uint64_t extrapolate_distinct_kmers_wrapped(unsigned long nbytes_memory, Bank *Reads) { unsigned long size_linearCounter = nbytes_memory * 8L; // alloc 8 bits * nbytes for counting LinearCounter *linearCounter = new LinearCounter(size_linearCounter); int stops = 100000; // variant of bloom_pass_reads int64_t NbRead = 0; int64_t NbInsertedKmers = 0; Reads->rewind_all(); char * rseq; long i; kmer_type kmer, graine, graine_revcomp; long nb_distinct_kmers = 0; long previous_nb_distinct_kmers = 0; uint64_t estimated_nb_reads = Reads->estimate_nb_reads(); bool stop = false; while (Reads->get_next_seq(&rseq,&readlen)) { if (stop) break; for (i=0; iadd(kmer); NbInsertedKmers++; if (NbInsertedKmers % stops == 0 && NbRead != 0) { previous_nb_distinct_kmers = nb_distinct_kmers; nb_distinct_kmers = linearCounter->count()*estimated_nb_reads/NbRead; //printf("estimated now: %ld\n",nb_distinct_kmers); // the following condition will grossly over-estimate the number of distinct kmers // I expect the correct result to be in the same order of magnitude if (abs((int)(nb_distinct_kmers-previous_nb_distinct_kmers)) < previous_nb_distinct_kmers/20) // 5% error stop = true; if (!linearCounter->is_accurate()) stop = true; } } NbRead++; if ((NbRead%10000)==0) fprintf (stderr,(char*)"%cExtrapolating number of distinct kmers %lld",13,NbRead); } if (!linearCounter->is_accurate()) { printf("Inaccurate estimation, restarting with %lu MB RAM\n",(2*nbytes_memory)/1024/1024); delete linearCounter; return extrapolate_distinct_kmers_wrapped(2*nbytes_memory, Reads); } nb_distinct_kmers = linearCounter->count()*estimated_nb_reads/NbRead; // this is a very rough estimation printf("Linear estimation: ~%ld M distinct %d-mers are in the reads\n",nb_distinct_kmers/1000000L,sizeKmer); delete linearCounter; return nb_distinct_kmers; } #endif float needleman_wunch_mtg(string a, string b, int * nbmatch,int * nbmis,int * nbgaps, int deb ) { float gap_score = -5; float mismatch_score = -5; float match_score = 10; #define nw_score(x,y) ( (x == y) ? match_score : mismatch_score ) int n_a = a.length(), n_b = b.length(); float ** score = (float **) malloc (sizeof(float*) * (n_a+1)); for (int ii=0; ii<(n_a+1); ii++) { score [ii] = (float *) malloc (sizeof(float) * (n_b+1)); } // float score[n_a+1][n_b+1]; //stack is too small // float pointer[n_a+1][n_b+1]; for (int i = 0; i <= n_a; i++) score[i][0] = gap_score * i; for (int j = 0; j <= n_b; j++) score[0][j] = gap_score * j; // compute dp for (int i = 1; i <= n_a; i++) { for (int j = 1; j <= n_b; j++) { float match = score[i - 1][j - 1] + nw_score(a[i-1],b[j-1]); float del = score[i - 1][j] + gap_score; float insert = score[i][j - 1] + gap_score; score[i][j] = max( max(match, del), insert); } } // traceback int i=n_a, j=n_b; float identity = 0; int nb_mis = 0; int nb_gaps = 0; int nb_end_gaps = 0 ; bool end_gap = true; while (i > 0 && j > 0) { float score_current = score[i][j], score_diagonal = score[i-1][j-1], score_up = score[i][j-1], score_left = score[i-1][j]; if (score_current == score_diagonal + nw_score(a[i-1], b[j-1])) { //if(deb==1)printf("eat %i %i \n",i,j); if (a[i-1]== b[j-1]) { // if(deb==1)printf("match %c %c \n",a[i-1],b[j-1]); identity++; } else { // if(deb==1)printf("mis %c %c \n",a[i-1],b[j-1]); nb_mis++; } i -= 1; j -= 1; end_gap = false; } else { if (score_current == score_left + gap_score) { //if(deb==1)printf("add gap s1 at ij %i %i \n",i,j); i -= 1; } else if (score_current == score_up + gap_score) { // if(deb==1)printf("add gap s2 at ij %i %i \n",i,j); j -= 1; } if(!end_gap) //pour ne pas compter gap terminal { nb_gaps++; } } } //pour compter gaps au debut : nb_gaps += i+j; //if(deb==1)printf("add gaps i j %i %i \n",i,j); identity /= max( n_a, n_b); // modif GR 27/09/2013 max of two sizes, otherwise free gaps if(nbmatch!=NULL) *nbmatch = identity; if(nbmis!=NULL) *nbmis = nb_mis; if(nbgaps!=NULL) *nbgaps = nb_gaps; for (int ii=0; ii<(n_a+1); ii++) { free (score [ii]); } free(score); //printf("---nw----\n%s\n%s -> %.2f\n--------\n",a.c_str(),b.c_str(),identity); return identity; } float needleman_wunch(string a, string b ) { float gap_score = -5; float mismatch_score = -5; float match_score = 10; #define nw_score(x,y) ( (x == y) ? match_score : mismatch_score ) int n_a = a.length(), n_b = b.length(); float ** score = (float **) malloc (sizeof(float*) * (n_a+1)); for (int ii=0; ii<(n_a+1); ii++) { score [ii] = (float *) malloc (sizeof(float) * (n_b+1)); } // float score[n_a+1][n_b+1]; //stack is too small // float pointer[n_a+1][n_b+1]; for (int i = 0; i <= n_a; i++) score[i][0] = gap_score * i; for (int j = 0; j <= n_b; j++) score[0][j] = gap_score * j; // compute dp for (int i = 1; i <= n_a; i++) { for (int j = 1; j <= n_b; j++) { float match = score[i - 1][j - 1] + nw_score(a[i-1],b[j-1]); float del = score[i - 1][j] + gap_score; float insert = score[i][j - 1] + gap_score; score[i][j] = max( max(match, del), insert); } } // traceback int i=n_a, j=n_b; float identity = 0; int nb_mis = 0; int nb_gaps = 0; int nb_end_gaps = 0 ; bool end_gap = true; while (i > 0 && j > 0) { float score_current = score[i][j], score_diagonal = score[i-1][j-1], score_up = score[i][j-1], score_left = score[i-1][j]; if (score_current == score_diagonal + nw_score(a[i-1], b[j-1])) { if (a[i-1]== b[j-1]) identity++; else nb_mis++; i -= 1; j -= 1; end_gap = false; } else { if (score_current == score_left + gap_score) i -= 1; else if (score_current == score_up + gap_score) j -= 1; } } identity /= max( n_a, n_b); // modif GR 27/09/2013 max of two sizes, otherwise free gaps for (int ii=0; ii<(n_a+1); ii++) { free (score [ii]); } free(score); //printf("---nw----\n%s\n%s -> %.2f\n--------\n",a.c_str(),b.c_str(),identity); return identity; } void Progress::init(uint64_t ntasks, const char * msg) { gettimeofday(×tamp, NULL); heure_debut = timestamp.tv_sec +(timestamp.tv_usec/1000000.0); fprintf(stderr,"| %-*s |\n",98,msg); todo= ntasks; done = 0; partial =0; for (int ii=0; ii<16;ii++) partial_threaded[ii]=0; for (int ii=0; ii<16;ii++) done_threaded[ii]=0; subdiv= 100; steps = (double)todo / (double)subdiv; if(!timer_mode) { fprintf(stderr,"[");fflush(stderr); } } void Progress::finish() { set(todo); if(timer_mode) fprintf(stderr,"\n"); else fprintf(stderr,"]\n"); fflush(stderr); todo= 0; done = 0; partial =0; } void Progress::finish_threaded()// called by only one of the threads { done = 0; double rem = 0; for (int ii=0; ii<16;ii++) done += (done_threaded[ii] ); for (int ii=0; ii<16;ii++) partial += (partial_threaded[ii] ); finish(); } void Progress::inc(uint64_t ntasks_done, int tid) { partial_threaded[tid] += ntasks_done; done_threaded[tid] += ntasks_done; while(partial_threaded[tid] >= steps) { if(timer_mode) { struct timeval timet; double now; gettimeofday(&timet, NULL); now = timet.tv_sec +(timet.tv_usec/1000000.0); uint64_t total_done = 0; for (int ii=0; ii<16;ii++) total_done += (done_threaded[ii] ); double elapsed = now - heure_debut; double speed = total_done / elapsed; double rem = (todo-total_done) / speed; if(total_done > todo) rem =0; int min_e = (int)(elapsed / 60) ; elapsed -= min_e*60; int min_r = (int)(rem / 60) ; rem -= min_r*60; fprintf(stderr,"%c%-5.3g %% elapsed: %6i min %-4.0f sec estimated remaining: %6i min %-4.0f sec ",13,100*(double)total_done/todo,min_e,elapsed,min_r,rem); } else { fprintf(stderr,"-");fflush(stderr); } partial_threaded[tid] -= steps; } } void Progress::inc(uint64_t ntasks_done) { done += ntasks_done; partial += ntasks_done; while(partial >= steps) { if(timer_mode) { gettimeofday(×tamp, NULL); heure_actuelle = timestamp.tv_sec +(timestamp.tv_usec/1000000.0); double elapsed = heure_actuelle - heure_debut; double speed = done / elapsed; double rem = (todo-done) / speed; if(done>todo) rem=0; int min_e = (int)(elapsed / 60) ; elapsed -= min_e*60; int min_r = (int)(rem / 60) ; rem -= min_r*60; fprintf(stderr,"%c%-5.3g %% elapsed: %6i min %-4.0f sec estimated remaining: %6i min %-4.0f sec ",13,100*(double)done/todo,min_e,elapsed,min_r,rem); } else { fprintf(stderr,"-");fflush(stderr); } partial -= steps; } } void Progress::set(uint64_t ntasks_done) { if(ntasks_done > done) inc(ntasks_done-done); } discoSnp/compile_kissnp_kissreads.sh0000755000000000000000000000561312410743600016766 0ustar rootroot#Copyright inria / irisa (2013) # # #raluca.uricaru@gmail.com #pierre.peterlongo@inria.fr # #This software is a computer program whose purpose is to call SNPs from NGS reads. # #This software is governed by the CeCILL license under French law and #abiding by the rules of distribution of free software. You can use, #modify and/ or redistribute the software under the terms of the CeCILL #license as circulated by CEA, CNRS and INRIA at the following URL #"http:#www.cecill.info". # #As a counterpart to the access to the source code and rights to copy, #modify and redistribute granted by the license, users are provided only #with a limited warranty and the software's author, the holder of the #economic rights, and the successive licensors have only limited #liability. # #In this respect, the user's attention is drawn to the risks associated #with loading, using, modifying and/or developing or reproducing the #software by the user in light of its specific status of free software, #that may mean that it is complicated to manipulate, and that also #therefore means that it is reserved for developers and experienced #professionals having in-depth computer knowledge. Users are therefore #encouraged to load and test the software's suitability as regards their #requirements in conditions enabling the security of their systems and/or #data to be ensured and, more generally, to use and operate it in the #same conditions as regards security. # #The fact that you are presently reading this means that you have had #knowledge of the CeCILL license and that you accept its terms. k=29 if test $# -eq 0 then k=29 else k=$1 fi mkdir tools cd kissnp2 make k=$k cd ../ cp kissnp2/kissnp2 tools if [ $? -ne 0 ] then echo "there was a problem compiling kissnp2, sorry. Please fix the problem or contact pierre.peterlongo@inria.fr." exit fi cd kissreads make MYFLAGS=-DOMP k=$k # VERSION KISSREADS PARALLEL #make k=$k # VERSION KISSREADS SEQUENCIAL cd .. cp kissreads/kissreads tools if [ $? -ne 0 ] then echo "there was a problem compiling kissreads, sorry. Please fix the problem or contact pierre.peterlongo@inria.fr." exit fi echo "Compiling is done, if possible, :" echo -e "\t 1/ copy executables \"tools/kissnp2\" and \"tools/kissreads\" in a directory member of the PATH environment variable (e.g. /usb/local/bin)" echo -e "\t 2/ replace PATH_RS=\"./tools\" by PATH_RS=\"\" in the \"run_discoSnp.sh\" configuration file" MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized if [ -z "$MY_PATH" ] ; then # error; for some reason, the path is not accessible # to the script (e.g. permissions re-evaled after suid) exit 1 # fail fi echo -e " or" echo "Leave it as is. In this case, if working outside this current directory (\"$MY_PATH\"), you will have to indicate in the \"run_discoSnp.sh\" where executables \"kissnp2\" and \"kissreads\" are located by changing the value of the PATH_RS variable" discoSnp/README.txt0000644000000000000000000003227612365464650013061 0ustar rootrootdiscoSnp Reference-free detection of isolated SNPs v1.2.3 User's guide – July 2014 contact: pierre.peterlongo@inria.fr Table of contents CeCILL License 1 Publication 1 discoSnp features at a glance 2 Quick starting 2 Components 2 Download and install 2 Running discoSnp 3 Output 3 Extensions: differences between unitig and contigs (from version 2.1.1.3) 5 Output Analyze 5 CeCILL License Copyright INRIA This software is a computer program whose purpose is to find all the similar reads between two set of NGS reads. It also provide a similarity score between the two samples. This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, modify and/ or redistribute the software under the terms of the CeCILL license as circulated by CEA, CNRS and INRIA at the following URL "http://www.cecill.info". As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors have only limited liability. In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or developing or reproducing the software by the user in light of its specific status of free software, that may mean that it is complicated to manipulate, and that also therefore means that it is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the software's suitability as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions as regards security. The fact that you are presently reading this means that you have had knowledge of the CeCILL license and that you accept its terms. Publication Publication is in preparation discoSnp features at a glance Software discoSnp is designed for extracting isolated Single Nucleotide Polymorphism (SNP) from raw set(s) of reads obtained with Next Generation Sequencers (NGS). Isolated means far away from any source of polymorphism, and far away means at least k bp, with k a user defined parameter. Note that this tool is specially designed to use only a limited amount of memory (3 billions reads of size 100 can be treated with less that 6GB memory). The software is composed of two independent modules. The first module, kissnp2, detects isolated SNPs from read sets. The second module, kissreads, enhances the kissnp2 results by computing per read set and for each found SNP i/ its mean read coverage and ii/ the average (phred) quality of reads generating the polymorphism. Quick starting After compiling programs (./compile_kissnp_kissreads.sh) the main script can be called as follows: ./run_discoSnp.sh -r "data_sample/reads_sequence1.fasta data_sample/reads_sequence2.fasta.gz" This creates a fasta file called discoRes_k_31_c_4_coherent.fa containing the found SNPs. Components Licence and readme clear_kissnp_kissreads.sh : cleaning the compiled tools. Useful when changing the k value compile_kissnp_kissreads.sh : compile all binaries and put them in a ''tool'' directory data_sample : directory containing two toy example read sets kissnp2 : sources of the SNP detection module kissreads : sources of the read coverage and quality module minia : sources of the k-mer couting and datastructure output_analyses : directory containing third party tools for post processing discoSnp results. run_discoSnp.sh : main (hopefully user friendly) script running the both modules for searching SNPs from raw read sets and for counting their read coverage and quality Download and install Download from discoSnp web page – http://colibread.inria.fr/discosnp/ . Please read and accept the CeCILL license before downloading. Unzip the downloaded package : # unzip discoSnp_versionnumber.zip Get into the newly created discoSnp directory: # cd discoSnp Compile the two modules (kissnp and kissreads) with the single command: # ./compile_kissnp_kissreads.sh k_value Note about the k value: Replace k_value by the value of the kmer that you wish to use. No need to recompile for any values below or equal to 31 No need to recompile for any values in [32,63] No need to recompile for any values in [64,127] ... By default, k=31 (value used both for compiling and in runtime). If you wish to recompile (for instance for changing the k value from any value below or equal to 31 to any value bigger or equal to 32) first clear the previously compiled executables: # ./clear_kissnp_kissreads.sh This installation process should generate the “tool” directory containing the two executables : kissnp2 and kissreads. Running discoSnp The main script run_discoSnp.sh automatically run the two modules (SNP detection and read coverage and quality computations). You will provide the following information: -r (read_sets) “readref.fasta readsnp.fastq.gz”: localization of the read files. Note that these files may be in fastq, or fasta, gzipped or not. If there are more than one read file, then they must be surrounded by the " character and they are separated by space. This is the only mandatory parameter. -p prefix_name: all temp and final files will be written will start with this prefix default: “discoRes” -k kmer_size: size of kmers (default: 31) -b branching_strategy: branching filtering approach. This parameters influances the precision recall. 0: SNPs for wich any of the two paths is branching are discarted (high precision, lowers the recal in complex genomes). Default value 1: (smart branching) forbid SNPs for wich the two paths are branching (e.g. the two paths can be created either with a 'A' or a 'C' at the same position 2: No limitation on branching (lowers the precision, high recall)" -c minimal_coverage: minimal kmer coverage default 4 -d error_threshold: max number of errors per read (used by kissreads only). default 1 -g genome_size: estimated genome size. Used only to control kissnp2 memory usage. e.g. 3 billion (3000000000) uses 4Gb of RAM. Default 10000000 (uses a few MB of memory) -w: If this option is called the waste files are not removed. -h: show help. By default binaries are search in the current “tool” directory. You may change this default value by editing the run_discoSnp.sh script changing the PATH_RS line Additionally you may change some kissnp2 / kissreads options. In this case you may change the two corresponding lines in the run_discoSnp.sh file. To know the possible options, type ./tools/kissnp2 and/or ./tools/kissreads without options. Note that usually, changing these options is not necessary. Sample example: You can test discoSnp on a toy example containing 3 SNPs: ./run_discoSnp.sh -r "data_sample/reads_sequence1.fasta data_sample/reads_sequence2.fasta.gz" Output Final results are in prefix_coherent_k_kval_c_cval.fa file. This is a simple fasta file composed of a succession of pairs of sequences. Each pair corresponds to a SNP. Let's look at an example : >SNP_higher_path_2|high|left_unitig_length_472|right_unitig_length_261|left_contig_length_472|right_contig_length_378|C1_8|C2_120|rank_0.88900 ttgcggataccgttgagacatcttataagtagacgcaatgcggaatcttatagaatcgcccgatagcgttgtgttggtggacacggctgattaccctctcacccgcgctattagcttccataccacctgcggccatccattaagatccgctgctcctcacgaaaaaagaattaataagaagtcccgtaacatgcggatttggtagtcgttatagacaactttactggggcgaactaaaacgcttgtggacagaattttggcagtggcaattaatctctaatgatgtgatattagggtctaaaatgtaagaattcggtgagttagattggacaaggggatccgaagatgttttggcgcagttagtcacagggggagcccctgcctacaaaaagcgcttactgttgactgtctagggatacagcgaaagcggcagtcgttgaagcaaaagtgatatgtgcgacactgcatctagGCAGCGCAACAACGCAACAGCTCGAGGTGTACTTCGCAGAGAAACCGCACGTCCAGTTCTAacactctcatatgtgctcgtcgtttatgctttcggcgtgaaaactggtgcgccggtgtctggagaccatccttcttgcgtatgactccaaggacagccatcacggtttgtgggttcactgggactgtcacgcttaaccggacggaactcgagaaggcatacgactggtcgtaagaccgctctgatccgacaccaccataacgcggcactcatgattatcatcacttttttagtccctattacagagctgccgggtggatgactctctaccgcgctctgtggaagtgcacttgatcgttttgctgtagaaaaaacttaataaacagaatgccgatgaaggcactactgtactaatagggccgggctacatgttaactac >SNP_lower_path_2|high|left_unitig_length_472|right_unitig_length_261|left_contig_length_472|right_contig_length_378|C1_118|C2_6|rank_0.88900 ttgcggataccgttgagacatcttataagtagacgcaatgcggaatcttatagaatcgcccgatagcgttgtgttggtggacacggctgattaccctctcacccgcgctattagcttccataccacctgcggccatccattaagatccgctgctcctcacgaaaaaagaattaataagaagtcccgtaacatgcggatttggtagtcgttatagacaactttactggggcgaactaaaacgcttgtggacagaattttggcagtggcaattaatctctaatgatgtgatattagggtctaaaatgtaagaattcggtgagttagattggacaaggggatccgaagatgttttggcgcagttagtcacagggggagcccctgcctacaaaaagcgcttactgttgactgtctagggatacagcgaaagcggcagtcgttgaagcaaaagtgatatgtgcgacactgcatctagGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAacactctcatatgtgctcgtcgtttatgctttcggcgtgaaaactggtgcgccggtgtctggagaccatccttcttgcgtatgactccaaggacagccatcacggtttgtgggttcactgggactgtcacgcttaaccggacggaactcgagaaggcatacgactggtcgtaagaccgctctgatccgacaccaccataacgcggcactcatgattatcatcacttttttagtccctattacagagctgccgggtggatgactctctaccgcgctctgtggaagtgcacttgatcgttttgctgtagaaaaaacttaataaacagaatgccgatgaaggcactactgtactaatagggccgggctacatgttaactac In this example a SNP A/T is found (underlined here). The central sequence of length 2k-1 (here 2*31-1=61) is seen in upper case, while the two (left and right) extensions are seen in lower case. The comments are formatted as follow : >SNP_higher/lower_path_id|high/low|left_unitig_length_int|right_unitigtig_length_int|left_contig_length_int|right_contig_length_int|C1_int|C2_int|[Q1_int|Q2_int|]rank_float higher/lower: one of the two alleles id: id of the SNP: each SNP (couple of sequences) has a unique id, here 3. high/low: sequence complexity. If the sequece if of low complexity (e.g. ATATATATATATATAT) this variable would be low left_unitig_length: size of the full left extension. Here 472 right_unitig_length: size of the right extension. Here 261 left_contig_length: size of the full left extension. Here 472 right_contig_length: size of the right extension. Here 378 C1: number of reads mapping the central upper case sequence from the first read set C2: number of reads mapping the central upper case sequence from the second read set C3 [if input data were at least 3 read sets]: number of reads mapping the central upper case sequence from the third read set C4, C5, ... Q1 [if reads were given in fastq]: average phred quality of the central nucleotide (here A or T) from the mapped reads from the first read set. Q2 [if reads were given in fastq]: average phred quality of the central nucleotide (here A or T) from the mapped reads from the second read set. Q3 [if the data were at least 3 fastq read sets]: average phred quality of the central nucleotide (here A or T) from the mapped reads from the third read set. Q4, Q5, … rank: ranks the predictions according to their read coverage in each condition favoring SNPs that are discriminant between conditions (Phi coefficient) (see publication) Extensions: differences between unitig and contigs (from version 2.1.1.3) By default in the pipeline, the found SNPs (of length 2k-1) are extended using a contiger. The output contains such contigs and their lengths are shown in the header (left_contig_length and right_contig_length). Moreover, a contig may hide some small polymorphism such as substitutions and/or indels. The output also proposes the length of the longuest extension not containing any such polymorphism. These extensions are called unitigs (defined as « A uniquely assembleable subset of overlapping fragments »). Output Analyze From a fasta format to a csv format: If you wish to analyze the results in a tabulated format: # python output_analyses/discoSnp_to_csv.py discoSnp_output.fa will output a .csv tabulated file containing on each line the content of 4 lines of the .fa, replacing the '|' character by spaces and removing the CX_ example with previously used SNP example: >SNP_higher_path_3 high left_contig_length_86 right_contig_length_52 78 5 rank_0.89839 tctctaccgcgctctgtggaagtgcacttgatcgttttgctgtagaaaaaacttaataaacagaatgccgatgaaggcactactgtACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATacataacttggtatcgtgcatgtagcgttcaagggctatagcaattccgacg >SNP_lower_path_3 high left_contig_length_86 right_contig_length_52 4 91 rank_0.89839 tctctaccgcgctctgtggaagtgcacttgatcgttttgctgtagaaaaaacttaataaacagaatgccgatgaaggcactactgtACTAATAGGGCCGGGCTACATGTTAACTACTAGGCTATAACCTATTGATGACCCGGTCCATacataacttggtatcgtgcatgtagcgttcaagggctatagcaattccgacg Genotyping the results: If you wish to genotype your results: #python output_analyses/discoSnp_to_genotypes.py discoSnp_output.fa threshold_value will output a file containing on each line the “genotypes” of a SNP. For each input data set it indicates if the SNP is: heterozygous ALT1 path (coverage ALT1 >= threshold and ALT2 < threshold): 1 heterozygous ALT2 path (coverage ALT1 < threshold and ALT2 >= threshold): -1 homozygous (coverage ALT1 >= threshold and ALT2 >= threshold): 2 absent (coverage ALT1 < threshold and ALT2 < threshold): 0 then it outputs the central sequence of length 2k-1 replacing the central position by ALT1/ALT2 example with previously used SNP example and threshold 20: GENOTYPES_SNP_3_THRESHOLD_20 1 -1 TACTAATAGGGCCGGGCTACATGTTAACTACA/TAGGCTATAACCTATTGATGACCCGGTCCATA discoSnp/kissnp2/0000755000000000000000000000000012412740202012721 5ustar rootrootdiscoSnp/kissnp2/kissnp2.cpp0000644000000000000000000003767212424136666015055 0ustar rootroot//Copyright inria / irisa (2013) // // //raluca.uricaru@gmail.com //pierre.peterlongo@inria.fr // //This software is a computer program whose purpose is to call SNPs from NGS reads. // //This software is governed by the CeCILL license under French law and //abiding by the rules of distribution of free software. You can use, //modify and/ or redistribute the software under the terms of the CeCILL //license as circulated by CEA, CNRS and INRIA at the following URL //"http://www.cecill.info". // //As a counterpart to the access to the source code and rights to copy, //modify and redistribute granted by the license, users are provided only //with a limited warranty and the software's author, the holder of the //economic rights, and the successive licensors have only limited //liability. // //In this respect, the user's attention is drawn to the risks associated //with loading, using, modifying and/or developing or reproducing the //software by the user in light of its specific status of free software, //that may mean that it is complicated to manipulate, and that also //therefore means that it is reserved for developers and experienced //professionals having in-depth computer knowledge. Users are therefore //encouraged to load and test the software's suitability as regards their //requirements in conditions enabling the security of their systems and/or //data to be ensured and, more generally, to use and operate it in the //same conditions as regards security. // //The fact that you are presently reading this means that you have had //knowledge of the CeCILL license and that you accept its terms. #include #include #include #include #include #include #include // for mkdir #include #include #include // for max/min #include // for sorting_kmers #include #include // for ostringstream #define NNKS 4 // default minimal abundance for solidity int max_memory; // the most memory one should alloc at any time, in MB int order=0; // in kissnp, don't change it, it should be 0 #define MIN_CONTIG_SIZE 108 #include "../minia/Bank.h" #include "../minia/Hash16.h" #include "../minia/Set.h" #include "../minia/Pool.h" #include "../minia/Bloom.h" #include "../minia/Debloom.h" #include "../minia/Utils.h" #include "../minia/rvalues.h" #include "../minia/SortingCount.h" #include "../minia/Terminator.h" #include "../minia/Kmer.h" #include "SNP.h" #include "Kmer_for_kissnp2.h" #include "commons.h" int64_t genome_size = 3000000000; Bloom * bloo1; int threshold; BinaryBank * SolidKmers; BranchingTerminator * terminator; extern int size_seeds; char * getVersion(){ return (char *)"DiscoSnp - kissnp submodule 1.2.6 - Copyright INRIA - CeCILL License"; } void print_usage_and_exit(char * name){ fprintf (stderr, "NAME\nkissnp, version %s\n", getVersion()); fprintf (stderr, "\nSYNOPSIS\n%s [ [2){ fprintf(stderr,"Value %d forbiden for the authorised_branching value, exit\n", authorised_branching); exit(1); } break; case 'g': genome_size=atoll(optarg); printf(" Will use genome_size=%llu\n", genome_size); //TODO format break; case 'c': nks = atoi(optarg); if (nks<1) nks=1; // min abundance can't be 0 printf(" Will create SNPs with k-mers occurring at least %d time(s)\n", nks); break; case 'C': max_couv = atoi(optarg); if (nks<1) nks=1; // min abundance can't be 0 printf(" Will create SNPs with k-mers occurring at most %d time(s)\n", max_couv); break; case 'o': strcpy (SNP_file_name, optarg); outputfilename=true; //SNP_file_name=(char *)string(optarg).c_str(); printf(" Will output results in file: %s.fa\n", optarg); break; case 'k': sizeKmer=atoi(optarg); printf(" required size seeds = %d\n", sizeKmer); break; case 'h': print_usage_and_exit(argv[0]); break; case '-': if(strcmp("version", optarg)==0){ printf("kissReads version %s\n", getVersion()); exit(0); } printf(" what next ? %s\n",optarg); break; default: printf ("Unknown option %c\n", temoin); print_usage_and_exit(argv[0]); } } // printf("%d %d", argc, optind); if ( argc - optind <1 || !outputfilename) { print_usage_and_exit(argv[0]); } ///////////////////////////////////////////////////// END GET OPTS ////// if (sizeKmer%2==0) { sizeKmer-=1; printf("Need odd kmer size to avoid palindromes. I've set kmer size to %d.\n",sizeKmer); } if (sizeKmer<11){ printf("I can't use k so small(=%d), I fix it to 11\n",sizeKmer); sizeKmer=11; } if (sizeKmer>(sizeof(kmer_type)*4)) { printf("Max kmer size on this compiled version is %lu\n",sizeof(kmer_type)*2); exit(1); } size_seeds=sizeKmer; // TODO: conserve only one of this two redundant variables threshold = (sizeKmer/2-2)*(sizeKmer/2-3); init_static_variables();// kmer size kmerMask=(((kmer_type)1)<<(sizeKmer*2))-1; sprintf(prefix,"%s_k_%d_c_%d", SNP_file_name, sizeKmer, nks); sprintf(SNP_file_name,"%s_k_%d_c_%d", SNP_file_name, sizeKmer, nks); if(min_size_extension>-1) sprintf(SNP_file_name,"%s_e_%d", SNP_file_name, min_size_extension); //sprintf(SNP_file_name_too_many, "%s_too_many", SNP_file_name); // if(max_couv < INT_MAX) printf("will eliminate kmers with coverage > %i \n",max_couv); /////////////////////////// CREATE OR LOAD THE GRAPH printf("Indexing reads, using minia approach, generating file prefixed with \"%s\"\n", prefix); double lg2 = log(2); // NBITS_PER_KMER = log(16*sizeKmer*(lg2*lg2))/(lg2*lg2); // needed to process argv[5] NBITS_PER_KMER = rvalues[sizeKmer][1]; int estimated_BL1 = max( (int)ceilf(log2f(genome_size * NBITS_PER_KMER )), 1); uint64_t estimated_nb_FP = (uint64_t)(genome_size * 4 * powf(0.6,11)); // just indicative max_memory = max( (1LL << estimated_BL1)/8LL /1024LL/1024LL, 1LL ); // printf("estimated values: nbits Bloom %i, nb FP %lld, max memory %i MB\n",estimated_BL1,estimated_nb_FP,max_memory); kmerMask=(((kmer_type)1)<<(sizeKmer*2))-1; NBITS_PER_KMER = log(16*sizeKmer*(lg2*lg2))/(lg2*lg2); // needed to process argv[5] max_memory = max( (1LL << estimated_BL1)/8LL /1024LL/1024LL, 1LL ); // printf("estimated values: nbits Bloom %i, nb FP %lld, max memory %i MB\n",estimated_BL1,estimated_nb_FP,max_memory); // shortcuts to go directly to assembly using serialized bloom and serialized hash int START_FROM_SOLID_KMERS=0; // if = 0, construct the fasta file of solid kmers, if = 1, start directly from that file int LOAD_FALSE_POSITIVE_KMERS=0; // if = 0, construct the fasta file of false positive kmers (debloom), if = 1, load that file into the hashtable int NO_FALSE_POSITIVES_AT_ALL=0; // if = 0, normal behavior, if = 1, don't load false positives (will be a probabilistic de bruijn graph) // printf("SNPFILE = %s\n", SNP_file_name); if( access( (string(prefix)+string(".debloom")).c_str(), F_OK ) != -1 && access( (string(prefix)+string(".debloom2")).c_str(), F_OK ) != -1 && access( (string(prefix)+string(".false_positive_kmers")).c_str(), F_OK ) != -1 && access( (string(prefix)+string(".solid_kmers_binary")).c_str(), F_OK ) != -1){ printf("THE INDEX %s.... were already created we use them\n", prefix); START_FROM_SOLID_KMERS=1; LOAD_FALSE_POSITIVE_KMERS=1; } else printf("CREATING THE index %s.... \n", prefix); printf("SNPFILE = %s\n", SNP_file_name); // fprintf (stderr,"taille cell %lu \n", sizeof(cell)); STARTWALL(0); // counter kmers, write solid kmers to disk, insert them into bloo1 if (!START_FROM_SOLID_KMERS) { int max_disk_space = 0; // let dsk decide int verbose = 0; bool write_count = false; sorting_count(Reads,prefix, max_memory, max_disk_space, write_count, verbose); } // debloom, write false positives to disk, insert them into false_positives if (! LOAD_FALSE_POSITIVE_KMERS) { debloom(order, max_memory); } bloo1 = bloom_create_bloo1((BloomCpt *)NULL); // load false positives from disk into false_positives false_positives = load_false_positives_cascading4(); // load branching kmers BinaryBank *SolidKmers = new BinaryBank(return_file_name(solid_kmers_file),sizeof(kmer_type),0); int LOAD_BRANCHING_KMERS=0; if (LOAD_BRANCHING_KMERS) { BinaryBank *BranchingKmers = new BinaryBank(return_file_name(branching_kmers_file),sizeof(kmer_type),false); terminator = new BranchingTerminator(BranchingKmers,SolidKmers, bloo1,false_positives); BranchingKmers->close(); } else{ BinaryBank *SolidKmers = new BinaryBank(return_file_name(solid_kmers_file),sizeof(kmer_type),0); terminator = new BranchingTerminator(SolidKmers,genome_size, bloo1,false_positives); } /////////////////////////// FIND BUBBLES //fprintf (stderr,"\t Finding bubbles: call \"new Bubble\" function\n"); // fprintf (stderr,"\t Finding bubbles, printing results in %s", SNP_file_name); Bubble *bubble = new Bubble(SolidKmers,bloo1,false_positives, extend_snps, min_size_extension,print_extensions, strict_extension); //fprintf (stderr,"\t Finding bubbles: call \"find_bubble\" function, printing results in %s", SNP_file_name); bubble->find_bubbles((string(SNP_file_name)+string(".fa")).c_str(), low, authorised_branching); //fprintf (stderr,"\t Finding bubbles: done... call of STOPWALL before to exit, tcho\n"); STOPWALL(0,"Total"); delete Reads; // fprintf (stderr,"\t Bubbles found are in %s", SNP_file_name); return 0; } discoSnp/kissnp2/SNP.h0000644000000000000000000001006712304135336013544 0ustar rootroot//Copyright inria / irisa (2013) // // //raluca.uricaru@gmail.com //pierre.peterlongo@inria.fr // //This software is a computer program whose purpose is to call SNPs from NGS reads. // //This software is governed by the CeCILL license under French law and //abiding by the rules of distribution of free software. You can use, //modify and/ or redistribute the software under the terms of the CeCILL //license as circulated by CEA, CNRS and INRIA at the following URL //"http://www.cecill.info". // //As a counterpart to the access to the source code and rights to copy, //modify and redistribute granted by the license, users are provided only //with a limited warranty and the software's author, the holder of the //economic rights, and the successive licensors have only limited //liability. // //In this respect, the user's attention is drawn to the risks associated //with loading, using, modifying and/or developing or reproducing the //software by the user in light of its specific status of free software, //that may mean that it is complicated to manipulate, and that also //therefore means that it is reserved for developers and experienced //professionals having in-depth computer knowledge. Users are therefore //encouraged to load and test the software's suitability as regards their //requirements in conditions enabling the security of their systems and/or //data to be ensured and, more generally, to use and operate it in the //same conditions as regards security. // //The fact that you are presently reading this means that you have had //knowledge of the CeCILL license and that you accept its terms. // // SNP.h #ifndef SNP_H_INCLUDED #define SNP_H_INCLUDED #include #include #include #include // for log2f #include "../minia/Bloom.h" #include "../minia/Kmer.h" #include "Kmer_for_kissnp2.h" #include "../minia/Set.h" #include "../minia/Bank.h" class Bubble{ protected: BinaryBank *SolidKmers; Bloom *bloom_solid_kmers; Set *debloom; bool extend_snps; bool print_extensions; bool strict_extension; // true: strict extension, fales: contig extension int min_size_extension; /** * Extends if necessary left and/or right parts of the bubble. * Prints results * path1 and path2: character pathes (no binary format). Of length 2k-1, 2k, or 2k+1, depending ont the results of "close_snps" * score=complexity score * where_to_extend : 0=nothing, 1=left only, 2=right only, 3=both */ void print_sequence_and_eventually_contigs(char * path1, char * path2, const int score, int where_to_extend); //extension==0 no extension, =1 only left, =2 only right, =3 both unsigned char branching_structure(kmer_type graine); bool is_branching(kmer_type kmer); bool two_possible_extensions_on_one_path(kmer_type); int close_snp(const char * path1, const char * path2, char * path1_c, char * path2_c); //returns -1 not closed, 0 no unique extension, 1 only left, 2 only right, 3 both public: void find_bubbles(const char * SNP_file_name, int low, int authorised_branching); void start_SwitchingNode(kmer_type graine); void start_Bubble(kmer_type graine, int low, int authorised_branching); bool two_possible_extensions(kmer_type kmer1, kmer_type kmer2); // void expand_Bubble_till_SN(int direction, char* path1, char* path2, kmer_type kmer1, kmer_type kmer2, int pos); void expand_Bubble(int direction, char* path1, char* path2, kmer_type kmer1, kmer_type kmer2, int pos, char* p1, char* p2, char* p3, char* p4, int low, int no_branching); bool next(kmer_type *kmer); void read_bubble_file(char *bubble_filename); Bubble(BinaryBank *given_SolidKmers, Bloom *given_bloom, Set *given_debloom, bool extend_snps, int min_size_extension,bool print_extensions, bool strict_extension) : SolidKmers(given_SolidKmers), bloom_solid_kmers(given_bloom), debloom(given_debloom), extend_snps(extend_snps), min_size_extension(min_size_extension), print_extensions (print_extensions), strict_extension (strict_extension) { } Bubble() { } }; #endif // SNP_H_INCLUDED discoSnp/kissnp2/IterativeExtensions.h0000644000000000000000000000655212305104422017115 0ustar rootroot//Copyright inria / irisa (2013) // // //raluca.uricaru@gmail.com //pierre.peterlongo@inria.fr // //This software is a computer program whose purpose is to call SNPs from NGS reads. // //This software is governed by the CeCILL license under French law and //abiding by the rules of distribution of free software. You can use, //modify and/ or redistribute the software under the terms of the CeCILL //license as circulated by CEA, CNRS and INRIA at the following URL //"http://www.cecill.info". // //As a counterpart to the access to the source code and rights to copy, //modify and redistribute granted by the license, users are provided only //with a limited warranty and the software's author, the holder of the //economic rights, and the successive licensors have only limited //liability. // //In this respect, the user's attention is drawn to the risks associated //with loading, using, modifying and/or developing or reproducing the //software by the user in light of its specific status of free software, //that may mean that it is complicated to manipulate, and that also //therefore means that it is reserved for developers and experienced //professionals having in-depth computer knowledge. Users are therefore //encouraged to load and test the software's suitability as regards their //requirements in conditions enabling the security of their systems and/or //data to be ensured and, more generally, to use and operate it in the //same conditions as regards security. // //The fact that you are presently reading this means that you have had //knowledge of the CeCILL license and that you accept its terms. #ifndef ITERATIVE_EXTENSION_H #define ITERATIVE_EXTENSION_H #include #include // std::pair, std::get #ifdef MINIA_IS_IN_PARENT_FOLDER #include "../minia/Utils.h" #include "../minia/Terminator.h" #include "../minia/Traversal.h" #include "../minia/Kmer.h" #include "../minia/Bank.h" #include "../minia/Debloom.h" #else #include "minia/Utils.h" #include "minia/Terminator.h" #include "minia/Traversal.h" #include "minia/Kmer.h" #include "minia/Bank.h" #include "minia/Debloom.h" #endif extern int64_t genome_size; extern Bloom * bloo1; extern BinaryBank * SolidKmers; extern BranchingTerminator * terminator; //Raluca extern AssocPairedSet *pairedBranchingKmers ; typedef enum { LARGEUR, PROFONDEUR, NB_PARCOURS } parcours_t; class IterativeExtensions { public: IterativeExtensions(); static void construct_linear_seqs(string L,string R, int max_depth, string output_file, int verb, int max_nodes, parcours_t search_mode = PROFONDEUR, bool swf = false ); static void construct_linear_seqs(string L, int max_depth, string output_file); static void construct_linear_seqs_paired(string L,string R, int max_depth, string output_file , int verb, int max_nodes); static void construct_linear_seqs_paired(string L, int max_depth, string output_file); // controls behavior of construct_linear_seqs enum Traversal_type { SimplePaths, Monument }; enum When_to_stop_extending { After_first_contig, Until_max_depth }; static Traversal_type traversal_type; // initialized in .cpp static When_to_stop_extending when_to_stop_extending; static bool dont_output_first_nucleotide; // extra function added by pierre static pair extend_a_snp(string L, int max_depth); }; #endif discoSnp/kissnp2/filter.cpp0000644000000000000000000000605712147164104014730 0ustar rootroot//Copyright inria / irisa (2013) // // //raluca.uricaru@gmail.com //pierre.peterlongo@inria.fr // //This software is a computer program whose purpose is to call SNPs from NGS reads. // //This software is governed by the CeCILL license under French law and //abiding by the rules of distribution of free software. You can use, //modify and/ or redistribute the software under the terms of the CeCILL //license as circulated by CEA, CNRS and INRIA at the following URL //"http://www.cecill.info". // //As a counterpart to the access to the source code and rights to copy, //modify and redistribute granted by the license, users are provided only //with a limited warranty and the software's author, the holder of the //economic rights, and the successive licensors have only limited //liability. // //In this respect, the user's attention is drawn to the risks associated //with loading, using, modifying and/or developing or reproducing the //software by the user in light of its specific status of free software, //that may mean that it is complicated to manipulate, and that also //therefore means that it is reserved for developers and experienced //professionals having in-depth computer knowledge. Users are therefore //encouraged to load and test the software's suitability as regards their //requirements in conditions enabling the security of their systems and/or //data to be ensured and, more generally, to use and operate it in the //same conditions as regards security. // //The fact that you are presently reading this means that you have had //knowledge of the CeCILL license and that you accept its terms. #include "filter.h" #include "../minia/Kmer.h" #include "Kmer_for_kissnp2.h" /** * Methode permettant d'appliquer le filtre Low Complexity * Les zones ininteressantes des sequences sont mises en lettres minuscules * \param la sequence * \param lenseq la longueur de la sequence * \return 1 si l'operation s'est deroulee correctement */ int filterLowComplexity (char* data, int lenseq, int threshold) { int DUSTSCORE[64]; int i, j, k, s, m; for (i=0; i<64; i++) DUSTSCORE[i]=0; for (j=2; j=threshold) return s; else return -1;*/ return s; } /** * Methode permettant d'appliquer le filtre Low Complexity sur les deux chemins d'un SNP **/ int filterLowComplexity2Paths (char* seq1, char *seq2, int lenseq, int threshold) { int DUSTSCORE1[64], DUSTSCORE2[64]; int i, j, k, s1, m, s2; for (i=0; i<64; i++) { DUSTSCORE1[i]=0; DUSTSCORE2[i]=0; } for (j=2; j=threshold) return s1+s2; else return -1;*/ return s1+s2; } discoSnp/kissnp2/filter.h0000644000000000000000000000471212147164134014374 0ustar rootroot#ifndef FILTER_H #define FILTER_H //Copyright inria / irisa (2013) // // //raluca.uricaru@gmail.com //pierre.peterlongo@inria.fr // //This software is a computer program whose purpose is to call SNPs from NGS reads. // //This software is governed by the CeCILL license under French law and //abiding by the rules of distribution of free software. You can use, //modify and/ or redistribute the software under the terms of the CeCILL //license as circulated by CEA, CNRS and INRIA at the following URL //"http://www.cecill.info". // //As a counterpart to the access to the source code and rights to copy, //modify and redistribute granted by the license, users are provided only //with a limited warranty and the software's author, the holder of the //economic rights, and the successive licensors have only limited //liability. // //In this respect, the user's attention is drawn to the risks associated //with loading, using, modifying and/or developing or reproducing the //software by the user in light of its specific status of free software, //that may mean that it is complicated to manipulate, and that also //therefore means that it is reserved for developers and experienced //professionals having in-depth computer knowledge. Users are therefore //encouraged to load and test the software's suitability as regards their //requirements in conditions enabling the security of their systems and/or //data to be ensured and, more generally, to use and operate it in the //same conditions as regards security. // //The fact that you are presently reading this means that you have had //knowledge of the CeCILL license and that you accept its terms. /** * Logiciel Gassst (Global Alignment Short Sequence Search Tool) * \file filter.h * \brief Module Filter, definit le filtre Low Complexity qui detecte les zones non pertinentes des sequences afin de ne pas les indexer * \author Dominique Lavenier * \author Damien Fleury * \version 5.2 * \date 28/08/2008 */ /// Fentre du filtre Low complexity /// #define WS 12 using namespace std; /** * Methode permettant d'appliquer le filtre Low Complexity * \param data le tableau des donnees de la banque de sequences * \param id l'index du debut de la sequence * \param lenseq la longueur de la sequence * \return 1 si l'operation s'est deroulee correctement */ int filterLowComplexity (char* data, int lenseq, int threshold); int filterLowComplexity2Paths (char* seq1, char *seq2, int lenseq, int threshold); #endif discoSnp/kissnp2/versions.txt0000644000000000000000000000442312424137162015345 0ustar rootroot 29/10/2014: discoSnp_1.2.6: fixed a bug in kissreads affecting multiple hits of read on a pattern. Added the -O option to kissread. 01/10/2014: discoSnp_1.2.5: fixed bugs of version 1.2.4 (bugs were not affecting version <1.2.4). 25/09/2014: discoSnp_1.2.4: incresed kissread speed 28/07/2014: discoSnp_1.2.3: improved the documentation – cleaned the output messages and the output useless files 20/05/2014: discoSnp_1.2.2: -b 0 is the default option. 26/04/2014: discoSnp_1.2.1: Fixes a compilation problem due to a makefile typo. 05/03/2014: discoSnp_1.2.0: New option with regards to branching bubbles 14/11/2013: discoSnp_1.0.1: fixes a bug concerning the contigs extensions (note that unitig extension lengths were not affected) 14/10/2013: discoSnp_1.0.0: read2SNPs name changes. discoSnp_1.0.0 is a new name for read2SNPs_2.1.1.4 -------------------------------------------------------------- 2.1.1.3 Adding option -T 15/07/2013 read2SNPs_2.1.0.0: 1/ improves speed and memory (thank to Salikhov, Kucherov and Sacomoto work) 2/ adding post-treatment scripts 3/ by default: keep the low complexity SNPs. 29/07/2013 read2SNPs_2.1.1.0: script run_read2SNPs.sh can now be called anywhere bubbles are now of length 2k-1 instead of 2k+1 before extensions. This improves the precision/recall 01/08/2013 read2SNPs_2.1.1.1 Bug fix (consequence of bubbles of length 2k-1) 2.0.5.9 - integrating the gustavos changes 2.0.5.8 2.0.5.7 - verify the branching of the two extreme kmers of each bubble - kissreads ranks swrt qrt(Xi2,sum) 2.0.5.4 - symetrise the branching extremities test of the bubbles 2.0.5.3 - fixes a (last ?) small bug with the ranking function & enhance the pipeline avoiding odd k values 2.0.5.2 - removes useless output and proposes a full pipeline with a use case 2.0.5.1 -fixes a bug with the kissreads ranking function 2.0.5 (2013 04 11) - validated version about branchings 2.0.4 (2013_04_10) - simplified code for the detection of branching kmers during SNP detection 2.0.3 (2013_04_08) - option b means print branching snps - by default, only non branching snps are printed (tests of branching are done in both directions) 2.0.2: (2013_04_05) - adding option -C - clarifying the -h message 2.0.1: initial version discoSnp/kissnp2/Kmer_for_kissnp2.cpp0000644000000000000000000000626012147164152016657 0ustar rootroot//Copyright inria / irisa (2013) // // //raluca.uricaru@gmail.com //pierre.peterlongo@inria.fr // //This software is a computer program whose purpose is to call SNPs from NGS reads. // //This software is governed by the CeCILL license under French law and //abiding by the rules of distribution of free software. You can use, //modify and/ or redistribute the software under the terms of the CeCILL //license as circulated by CEA, CNRS and INRIA at the following URL //"http://www.cecill.info". // //As a counterpart to the access to the source code and rights to copy, //modify and redistribute granted by the license, users are provided only //with a limited warranty and the software's author, the holder of the //economic rights, and the successive licensors have only limited //liability. // //In this respect, the user's attention is drawn to the risks associated //with loading, using, modifying and/or developing or reproducing the //software by the user in light of its specific status of free software, //that may mean that it is complicated to manipulate, and that also //therefore means that it is reserved for developers and experienced //professionals having in-depth computer knowledge. Users are therefore //encouraged to load and test the software's suitability as regards their //requirements in conditions enabling the security of their systems and/or //data to be ensured and, more generally, to use and operate it in the //same conditions as regards security. // //The fact that you are presently reading this means that you have had //knowledge of the CeCILL license and that you accept its terms. #ifndef ASSERTS #define NDEBUG // disable asserts, they're computationnally intensive #endif #include #include #include // for min #include "../minia/Kmer.h" #include "Kmer_for_kissnp2.h" #include "../minia/lut.h" using namespace std; kmer_type next_kmer_new(kmer_type graine, int added_nt, int strand) { assert(added_nt<4); assert((strand == NULL) || (strand<2)); kmer_type new_graine; kmer_type temp_graine; if (strand == 1)// the kmer we're extending is actually a revcomp sequence in the bidirected debruijn graph node temp_graine = revcomp(graine); else temp_graine = graine; new_graine = (((temp_graine) * 4 ) + added_nt) & kmerMask; //new_graine = (((graine) >> 2 ) + ( ((kmer_type)added_nt) << ((sizeKmer-1)*2)) ) & kmerMask; // previous kmer kmer_type revcomp_new_graine = revcomp(new_graine); return min(new_graine,revcomp_new_graine); } kmer_type next_kmer_new_norevcomp(kmer_type graine, int added_nt, int strand) { assert(added_nt<4); assert((strand == NULL) || (strand<2)); kmer_type new_graine; kmer_type temp_graine; if (strand == 1)// the kmer we're extending is actually a revcomp sequence in the bidirected debruijn graph node temp_graine = revcomp(graine); else temp_graine = graine; new_graine = (((temp_graine) * 4 ) + added_nt) & kmerMask; //new_graine = (((graine) >> 2 ) + ( ((kmer_type)added_nt) << ((sizeKmer-1)*2)) ) & kmerMask; // previous kmer kmer_type revcomp_new_graine = revcomp(new_graine); return new_graine; } discoSnp/kissnp2/commons.h0000644000000000000000000000502712175425746014574 0ustar rootroot//Copyright inria / irisa (2013) // // //raluca.uricaru@gmail.com //pierre.peterlongo@inria.fr // //This software is a computer program whose purpose is to call SNPs from NGS reads. // //This software is governed by the CeCILL license under French law and //abiding by the rules of distribution of free software. You can use, //modify and/ or redistribute the software under the terms of the CeCILL //license as circulated by CEA, CNRS and INRIA at the following URL //"http://www.cecill.info". // //As a counterpart to the access to the source code and rights to copy, //modify and redistribute granted by the license, users are provided only //with a limited warranty and the software's author, the holder of the //economic rights, and the successive licensors have only limited //liability. // //In this respect, the user's attention is drawn to the risks associated //with loading, using, modifying and/or developing or reproducing the //software by the user in light of its specific status of free software, //that may mean that it is complicated to manipulate, and that also //therefore means that it is reserved for developers and experienced //professionals having in-depth computer knowledge. Users are therefore //encouraged to load and test the software's suitability as regards their //requirements in conditions enabling the security of their systems and/or //data to be ensured and, more generally, to use and operate it in the //same conditions as regards security. // //The fact that you are presently reading this means that you have had //knowledge of the CeCILL license and that you accept its terms. /* * commons.h * * Created on: 17 sept. 2010 * Author: ppeterlo */ #ifndef COMMONS_H_ #define COMMONS_H_ #include #include "../minia/Kmer.h" // FOR uint64_t and kmer_type void revcomp(char *s, int len); void rev(char s[], int len); void init_static_variables(); char * to_upper (char * word); char * to_lower (char * word); char ** sort_strings (char ** strings, int number); uint64_t codeSeed_uint64_t(const char *seq); int valid_character(const char c); void print_rev_comp(char s[], FILE * out=stdout); // macro to test if a variable is null (i.e., a malloc failed) #define test_alloc( variable) { if(variable == NULL){ fprintf(stderr,"cannot allocate memory for variable %s, exit\n",#variable); exit(1); }} #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) #define Sinc24(a) ((a == 0xFFFFFF ) ? 0xFFFFFF : a++) #define Sinc8(a) ((a == 0xFF ) ? 0xFF : a++) #endif /* COMMONS_H_ */ discoSnp/kissnp2/Kmer_for_kissnp2.h0000644000000000000000000000345312147164176016333 0ustar rootroot//Copyright inria / irisa (2013) // // //raluca.uricaru@gmail.com //pierre.peterlongo@inria.fr // //This software is a computer program whose purpose is to call SNPs from NGS reads. // //This software is governed by the CeCILL license under French law and //abiding by the rules of distribution of free software. You can use, //modify and/ or redistribute the software under the terms of the CeCILL //license as circulated by CEA, CNRS and INRIA at the following URL //"http://www.cecill.info". // //As a counterpart to the access to the source code and rights to copy, //modify and redistribute granted by the license, users are provided only //with a limited warranty and the software's author, the holder of the //economic rights, and the successive licensors have only limited //liability. // //In this respect, the user's attention is drawn to the risks associated //with loading, using, modifying and/or developing or reproducing the //software by the user in light of its specific status of free software, //that may mean that it is complicated to manipulate, and that also //therefore means that it is reserved for developers and experienced //professionals having in-depth computer knowledge. Users are therefore //encouraged to load and test the software's suitability as regards their //requirements in conditions enabling the security of their systems and/or //data to be ensured and, more generally, to use and operate it in the //same conditions as regards security. // //The fact that you are presently reading this means that you have had //knowledge of the CeCILL license and that you accept its terms. #include #include "../minia/Kmer.h" kmer_type next_kmer_new(kmer_type graine, int added_nt, int strand); kmer_type next_kmer_new_norevcomp(kmer_type graine, int added_nt, int strand); discoSnp/kissnp2/LICENSE0000644000000000000000000005115412227036510013740 0ustar rootroot CeCILL FREE SOFTWARE LICENSE AGREEMENT Notice This Agreement is a Free Software license agreement that is the result of discussions between its authors in order to ensure compliance with the two main principles guiding its drafting: * firstly, compliance with the principles governing the distribution of Free Software: access to source code, broad rights granted to users, * secondly, the election of a governing law, French law, with which it is conformant, both as regards the law of torts and intellectual property law, and the protection that it offers to both authors and holders of the economic rights over software. The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) license are: Commissariat à l'Energie Atomique - CEA, a public scientific, technical and industrial research establishment, having its principal place of business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. Centre National de la Recherche Scientifique - CNRS, a public scientific and technological establishment, having its principal place of business at 3 rue Michel-Ange, 75794 Paris cedex 16, France. Institut National de Recherche en Informatique et en Automatique - INRIA, a public scientific and technological establishment, having its principal place of business at Domaine de Voluceau, Rocquencourt, BP 105, 78153 Le Chesnay cedex, France. Preamble The purpose of this Free Software license agreement is to grant users the right to modify and redistribute the software governed by this license within the framework of an open source distribution model. The exercising of these rights is conditional upon certain obligations for users so as to preserve this status for all subsequent redistributions. In consideration of access to the source code and the rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors only have limited liability. In this respect, the risks associated with loading, using, modifying and/or developing or reproducing the software by the user are brought to the user's attention, given its Free Software status, which may make it complicated to use, with the result that its use is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the suitability of the software as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions of security. This Agreement may be freely reproduced and published, provided it is not altered, and that no provisions are either added or removed herefrom. This Agreement may apply to any or all software for which the holder of the economic rights decides to submit the use thereof to its provisions. Article 1 - DEFINITIONS For the purpose of this Agreement, when the following expressions commence with a capital letter, they shall have the following meaning: Agreement: means this license agreement, and its possible subsequent versions and annexes. Software: means the software in its Object Code and/or Source Code form and, where applicable, its documentation, "as is" when the Licensee accepts the Agreement. Initial Software: means the Software in its Source Code and possibly its Object Code form and, where applicable, its documentation, "as is" when it is first distributed under the terms and conditions of the Agreement. Modified Software: means the Software modified by at least one Contribution. Source Code: means all the Software's instructions and program lines to which access is required so as to modify the Software. Object Code: means the binary files originating from the compilation of the Source Code. Holder: means the holder(s) of the economic rights over the Initial Software. Licensee: means the Software user(s) having accepted the Agreement. Contributor: means a Licensee having made at least one Contribution. Licensor: means the Holder, or any other individual or legal entity, who distributes the Software under the Agreement. Contribution: means any or all modifications, corrections, translations, adaptations and/or new functions integrated into the Software by any or all Contributors, as well as any or all Internal Modules. Module: means a set of sources files including their documentation that enables supplementary functions or services in addition to those offered by the Software. External Module: means any or all Modules, not derived from the Software, so that this Module and the Software run in separate address spaces, with one calling the other when they are run. Internal Module: means any or all Module, connected to the Software so that they both execute in the same address space. GNU GPL: means the GNU General Public License version 2 or any subsequent version, as published by the Free Software Foundation Inc. Parties: mean both the Licensee and the Licensor. These expressions may be used both in singular and plural form. Article 2 - PURPOSE The purpose of the Agreement is the grant by the Licensor to the Licensee of a non-exclusive, transferable and worldwide license for the Software as set forth in Article 5 hereinafter for the whole term of the protection granted by the rights over said Software. Article 3 - ACCEPTANCE 3.1 The Licensee shall be deemed as having accepted the terms and conditions of this Agreement upon the occurrence of the first of the following events: * (i) loading the Software by any or all means, notably, by downloading from a remote server, or by loading from a physical medium; * (ii) the first time the Licensee exercises any of the rights granted hereunder. 3.2 One copy of the Agreement, containing a notice relating to the characteristics of the Software, to the limited warranty, and to the fact that its use is restricted to experienced users has been provided to the Licensee prior to its acceptance as set forth in Article 3.1 hereinabove, and the Licensee hereby acknowledges that it has read and understood it. Article 4 - EFFECTIVE DATE AND TERM 4.1 EFFECTIVE DATE The Agreement shall become effective on the date when it is accepted by the Licensee as set forth in Article 3.1. 4.2 TERM The Agreement shall remain in force for the entire legal term of protection of the economic rights over the Software. Article 5 - SCOPE OF RIGHTS GRANTED The Licensor hereby grants to the Licensee, who accepts, the following rights over the Software for any or all use, and for the term of the Agreement, on the basis of the terms and conditions set forth hereinafter. Besides, if the Licensor owns or comes to own one or more patents protecting all or part of the functions of the Software or of its components, the Licensor undertakes not to enforce the rights granted by these patents against successive Licensees using, exploiting or modifying the Software. If these patents are transferred, the Licensor undertakes to have the transferees subscribe to the obligations set forth in this paragraph. 5.1 RIGHT OF USE The Licensee is authorized to use the Software, without any limitation as to its fields of application, with it being hereinafter specified that this comprises: 1. permanent or temporary reproduction of all or part of the Software by any or all means and in any or all form. 2. loading, displaying, running, or storing the Software on any or all medium. 3. entitlement to observe, study or test its operation so as to determine the ideas and principles behind any or all constituent elements of said Software. This shall apply when the Licensee carries out any or all loading, displaying, running, transmission or storage operation as regards the Software, that it is entitled to carry out hereunder. 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS The right to make Contributions includes the right to translate, adapt, arrange, or make any or all modifications to the Software, and the right to reproduce the resulting software. The Licensee is authorized to make any or all Contributions to the Software provided that it includes an explicit notice that it is the author of said Contribution and indicates the date of the creation thereof. 5.3 RIGHT OF DISTRIBUTION In particular, the right of distribution includes the right to publish, transmit and communicate the Software to the general public on any or all medium, and by any or all means, and the right to market, either in consideration of a fee, or free of charge, one or more copies of the Software by any means. The Licensee is further authorized to distribute copies of the modified or unmodified Software to third parties according to the terms and conditions set forth hereinafter. 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION The Licensee is authorized to distribute true copies of the Software in Source Code or Object Code form, provided that said distribution complies with all the provisions of the Agreement and is accompanied by: 1. a copy of the Agreement, 2. a notice relating to the limitation of both the Licensor's warranty and liability as set forth in Articles 8 and 9, and that, in the event that only the Object Code of the Software is redistributed, the Licensee allows future Licensees unhindered access to the full Source Code of the Software by indicating how to access it, it being understood that the additional cost of acquiring the Source Code shall not exceed the cost of transferring the data. 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE When the Licensee makes a Contribution to the Software, the terms and conditions for the distribution of the resulting Modified Software become subject to all the provisions of this Agreement. The Licensee is authorized to distribute the Modified Software, in source code or object code form, provided that said distribution complies with all the provisions of the Agreement and is accompanied by: 1. a copy of the Agreement, 2. a notice relating to the limitation of both the Licensor's warranty and liability as set forth in Articles 8 and 9, and that, in the event that only the object code of the Modified Software is redistributed, the Licensee allows future Licensees unhindered access to the full source code of the Modified Software by indicating how to access it, it being understood that the additional cost of acquiring the source code shall not exceed the cost of transferring the data. 5.3.3 DISTRIBUTION OF EXTERNAL MODULES When the Licensee has developed an External Module, the terms and conditions of this Agreement do not apply to said External Module, that may be distributed under a separate license agreement. 5.3.4 COMPATIBILITY WITH THE GNU GPL The Licensee can include a code that is subject to the provisions of one of the versions of the GNU GPL in the Modified or unmodified Software, and distribute that entire code under the terms of the same version of the GNU GPL. The Licensee can include the Modified or unmodified Software in a code that is subject to the provisions of one of the versions of the GNU GPL, and distribute that entire code under the terms of the same version of the GNU GPL. Article 6 - INTELLECTUAL PROPERTY 6.1 OVER THE INITIAL SOFTWARE The Holder owns the economic rights over the Initial Software. Any or all use of the Initial Software is subject to compliance with the terms and conditions under which the Holder has elected to distribute its work and no one shall be entitled to modify the terms and conditions for the distribution of said Initial Software. The Holder undertakes that the Initial Software will remain ruled at least by this Agreement, for the duration set forth in Article 4.2. 6.2 OVER THE CONTRIBUTIONS The Licensee who develops a Contribution is the owner of the intellectual property rights over this Contribution as defined by applicable law. 6.3 OVER THE EXTERNAL MODULES The Licensee who develops an External Module is the owner of the intellectual property rights over this External Module as defined by applicable law and is free to choose the type of agreement that shall govern its distribution. 6.4 JOINT PROVISIONS The Licensee expressly undertakes: 1. not to remove, or modify, in any manner, the intellectual property notices attached to the Software; 2. to reproduce said notices, in an identical manner, in the copies of the Software modified or not. The Licensee undertakes not to directly or indirectly infringe the intellectual property rights of the Holder and/or Contributors on the Software and to take, where applicable, vis-à-vis its staff, any and all measures required to ensure respect of said intellectual property rights of the Holder and/or Contributors. Article 7 - RELATED SERVICES 7.1 Under no circumstances shall the Agreement oblige the Licensor to provide technical assistance or maintenance services for the Software. However, the Licensor is entitled to offer this type of services. The terms and conditions of such technical assistance, and/or such maintenance, shall be set forth in a separate instrument. Only the Licensor offering said maintenance and/or technical assistance services shall incur liability therefor. 7.2 Similarly, any Licensor is entitled to offer to its licensees, under its sole responsibility, a warranty, that shall only be binding upon itself, for the redistribution of the Software and/or the Modified Software, under terms and conditions that it is free to decide. Said warranty, and the financial terms and conditions of its application, shall be subject of a separate instrument executed between the Licensor and the Licensee. Article 8 - LIABILITY 8.1 Subject to the provisions of Article 8.2, the Licensee shall be entitled to claim compensation for any direct loss it may have suffered from the Software as a result of a fault on the part of the relevant Licensor, subject to providing evidence thereof. 8.2 The Licensor's liability is limited to the commitments made under this Agreement and shall not be incurred as a result of in particular: (i) loss due the Licensee's total or partial failure to fulfill its obligations, (ii) direct or consequential loss that is suffered by the Licensee due to the use or performance of the Software, and (iii) more generally, any consequential loss. In particular the Parties expressly agree that any or all pecuniary or business loss (i.e. loss of data, loss of profits, operating loss, loss of customers or orders, opportunity cost, any disturbance to business activities) or any or all legal proceedings instituted against the Licensee by a third party, shall constitute consequential loss and shall not provide entitlement to any or all compensation from the Licensor. Article 9 - WARRANTY 9.1 The Licensee acknowledges that the scientific and technical state-of-the-art when the Software was distributed did not enable all possible uses to be tested and verified, nor for the presence of possible defects to be detected. In this respect, the Licensee's attention has been drawn to the risks associated with loading, using, modifying and/or developing and reproducing the Software which are reserved for experienced users. The Licensee shall be responsible for verifying, by any or all means, the suitability of the product for its requirements, its good working order, and for ensuring that it shall not cause damage to either persons or properties. 9.2 The Licensor hereby represents, in good faith, that it is entitled to grant all the rights over the Software (including in particular the rights set forth in Article 5). 9.3 The Licensee acknowledges that the Software is supplied "as is" by the Licensor without any other express or tacit warranty, other than that provided for in Article 9.2 and, in particular, without any warranty as to its commercial value, its secured, safe, innovative or relevant nature. Specifically, the Licensor does not warrant that the Software is free from any error, that it will operate without interruption, that it will be compatible with the Licensee's own equipment and software configuration, nor that it will meet the Licensee's requirements. 9.4 The Licensor does not either expressly or tacitly warrant that the Software does not infringe any third party intellectual property right relating to a patent, software or any other property right. Therefore, the Licensor disclaims any and all liability towards the Licensee arising out of any or all proceedings for infringement that may be instituted in respect of the use, modification and redistribution of the Software. Nevertheless, should such proceedings be instituted against the Licensee, the Licensor shall provide it with technical and legal assistance for its defense. Such technical and legal assistance shall be decided on a case-by-case basis between the relevant Licensor and the Licensee pursuant to a memorandum of understanding. The Licensor disclaims any and all liability as regards the Licensee's use of the name of the Software. No warranty is given as regards the existence of prior rights over the name of the Software or as regards the existence of a trademark. Article 10 - TERMINATION 10.1 In the event of a breach by the Licensee of its obligations hereunder, the Licensor may automatically terminate this Agreement thirty (30) days after notice has been sent to the Licensee and has remained ineffective. 10.2 A Licensee whose Agreement is terminated shall no longer be authorized to use, modify or distribute the Software. However, any licenses that it may have granted prior to termination of the Agreement shall remain valid subject to their having been granted in compliance with the terms and conditions hereof. Article 11 - MISCELLANEOUS 11.1 EXCUSABLE EVENTS Neither Party shall be liable for any or all delay, or failure to perform the Agreement, that may be attributable to an event of force majeure, an act of God or an outside cause, such as defective functioning or interruptions of the electricity or telecommunications networks, network paralysis following a virus attack, intervention by government authorities, natural disasters, water damage, earthquakes, fire, explosions, strikes and labor unrest, war, etc. 11.2 Any failure by either Party, on one or more occasions, to invoke one or more of the provisions hereof, shall under no circumstances be interpreted as being a waiver by the interested Party of its right to invoke said provision(s) subsequently. 11.3 The Agreement cancels and replaces any or all previous agreements, whether written or oral, between the Parties and having the same purpose, and constitutes the entirety of the agreement between said Parties concerning said purpose. No supplement or modification to the terms and conditions hereof shall be effective as between the Parties unless it is made in writing and signed by their duly authorized representatives. 11.4 In the event that one or more of the provisions hereof were to conflict with a current or future applicable act or legislative text, said act or legislative text shall prevail, and the Parties shall make the necessary amendments so as to comply with said act or legislative text. All other provisions shall remain effective. Similarly, invalidity of a provision of the Agreement, for any reason whatsoever, shall not cause the Agreement as a whole to be invalid. 11.5 LANGUAGE The Agreement is drafted in both French and English and both versions are deemed authentic. Article 12 - NEW VERSIONS OF THE AGREEMENT 12.1 Any person is authorized to duplicate and distribute copies of this Agreement. 12.2 So as to ensure coherence, the wording of this Agreement is protected and may only be modified by the authors of the License, who reserve the right to periodically publish updates or new versions of the Agreement, each with a separate number. These subsequent versions may address new issues encountered by Free Software. 12.3 Any Software distributed under a given version of the Agreement may only be subsequently distributed under the same version of the Agreement or a subsequent version, subject to the provisions of Article 5.3.4. Article 13 - GOVERNING LAW AND JURISDICTION 13.1 The Agreement is governed by French law. The Parties agree to endeavor to seek an amicable solution to any disagreements or disputes that may arise during the performance of the Agreement. 13.2 Failing an amicable solution within two (2) months as from their occurrence, and unless emergency proceedings are necessary, the disagreements or disputes shall be referred to the Paris Courts having jurisdiction, by the more diligent Party. Version 2.0 dated 2006-09-05. discoSnp/kissnp2/IterativeExtensions.cpp0000644000000000000000000006511712332235176017465 0ustar rootroot//Copyright inria / irisa (2013) // // this file is shared between MindTheGap and Kissnp2, // and possibly other Minia-related software // //raluca.uricaru@gmail.com //pierre.peterlongo@inria.fr //guillaume.rizk@irisa.fr //rayan.chikhi@ens-cachan.org // //This software is governed by the CeCILL license under French law and //abiding by the rules of distribution of free software. You can use, //modify and/ or redistribute the software under the terms of the CeCILL //license as circulated by CEA, CNRS and INRIA at the following URL //"http://www.cecill.info". // //As a counterpart to the access to the source code and rights to copy, //modify and redistribute granted by the license, users are provided only //with a limited warranty and the software's author, the holder of the //economic rights, and the successive licensors have only limited //liability. // //In this respect, the user's attention is drawn to the risks associated //with loading, using, modifying and/or developing or reproducing the //software by the user in light of its specific status of free software, //that may mean that it is complicated to manipulate, and that also //therefore means that it is reserved for developers and experienced //professionals having in-depth computer knowledge. Users are therefore //encouraged to load and test the software's suitability as regards their //requirements in conditions enabling the security of their systems and/or //data to be ensured and, more generally, to use and operate it in the //same conditions as regards security. // //The fact that you are presently reading this means that you have had //knowledge of the CeCILL license and that you accept its terms. #include "IterativeExtensions.h" //#define DONTMARK AssocPairedSet *pairedBranchingKmers; // this type bears similarity with Traversal.h:kmer_strand_nt but I wanted to rename "nt" to "depth" for clarity struct kmer_strand_depth { kmer_type kmer; int strand; int depth; kmer_strand_depth(kmer_type kmer, int strand, int depth) : kmer(kmer), strand(strand), depth(depth) {} bool operator<(const kmer_strand_depth &other) const { // needed for comparisons inside a list if (kmer != other.kmer) return (kmer < other.kmer); if (depth != other.depth) return depth < other.depth; return (strand < other.strand); } }; /* * our assembly graph is connected by (k-1)-overlaps, * so this function is used to make sure we see each (k-1)-overlap in at most one right extremity */ bool compare_and_mark_last_k_minus_one_mer(string node, set &kmers_set) { kmer_type kmer_fw, kmer_rc; sizeKmer--; kmer_type kmer = extractKmerFromRead( (char *)node.c_str(), node.size() - sizeKmer, &kmer_fw, &kmer_rc, false); int strand = (kmer == kmer_rc); // char kmer_seq[100]; // code2seq(kmer_fw,kmer_seq); // convert starting kmer to nucleotide seq // //printf("checking marking kmer: %s\n",kmer_seq); sizeKmer++; if (kmers_set.find(kmer) != kmers_set.end()) return true; kmers_set.insert(kmer); return false; } // default extension modes (do not change) IterativeExtensions::Traversal_type IterativeExtensions::traversal_type = Monument; IterativeExtensions::When_to_stop_extending IterativeExtensions::when_to_stop_extending = Until_max_depth; bool IterativeExtensions::dont_output_first_nucleotide = false; void IterativeExtensions::construct_linear_seqs(string L, int max_depth, string output_file) { construct_linear_seqs(L, string(),max_depth,output_file,2,1000000000); } /* * return the contig which starts with L, as well as all ths contigs that follow him, up to max_depth. * results go to a fasta file (output_file) * * requires that: * global variables terminator, bloo1 and false_positives are already constructed by minia * * outputs: * a set of contigs in the output file */ void IterativeExtensions::construct_linear_seqs(string L,string R, int max_depth, string output_file , int verb, int max_nodes, parcours_t search_mode, bool swf ) { bool debug = verb>=2 ? 1 : 0; kmer_type kmer; char kmer_seq[sizeKmer+1]; FILE *linear_seqs_file; Traversal *traversal; if (traversal_type == IterativeExtensions::SimplePaths) traversal = new SimplePathsTraversal(bloo1,false_positives,terminator); else if (traversal_type == IterativeExtensions::Monument) traversal = new MonumentTraversal(bloo1,false_positives,terminator); traversal->set_maxlen(max_depth); traversal->set_max_depth(500); traversal->set_max_breadth(20); long long nbNodes = 0; long long totalnt=0; long long contig_len =0; long long maxlen=1000000; char *right_traversal = (char *) malloc(maxlen*sizeof(char)); char *node = (char *) malloc(maxlen*sizeof(char)); node [0] = '\0'; if(!output_file.empty()) { linear_seqs_file = fopen((char * )output_file.c_str(),"w"); } else { linear_seqs_file = NULL; IterativeExtensions::when_to_stop_extending = IterativeExtensions::After_first_contig; // sequence } STARTWALL(nodes); // heuristics: start from the last kmer of L vector < kmer_strand_depth > kmers_to_traverse; kmer_type kmer_fw, kmer_rc; kmer = extractKmerFromRead( (char *)L.c_str(), L.size() - sizeKmer, &kmer_fw, &kmer_rc, false); int strand = (kmer == kmer_rc); kmer_strand_depth first_kmer (kmer,strand,0); kmers_to_traverse.push_back(first_kmer); #ifndef DONTMARK set already_extended_from; // compare_and_mark_last_k_minus_one_mer(L, already_extended_from); // mark first kmer to never extend from it again, // L will be marked at first iteration below #endif while (kmers_to_traverse.size() > 0) // min_depth is max_gap_length here { kmer_strand_depth ksd (0,0,0); if (search_mode == PROFONDEUR) { ksd = kmers_to_traverse.back(); kmers_to_traverse.pop_back(); } else if (search_mode == LARGEUR) { ksd = kmers_to_traverse.front(); kmers_to_traverse.erase (kmers_to_traverse.begin()); } kmer = ksd.kmer; int strand = ksd.strand; int depth = ksd.depth; code2seq(kmer,kmer_seq); // convert starting kmer to nucleotide seq if (strand == 1) revcomp_sequence(kmer_seq,sizeKmer); if (debug) printf(" --- iteration: kmer %s%s (of lenght %d) depth %d nbNodes explored %lli ---\n",kmer_seq,strand?" (internally rc)":"", (int)strlen(kmer_seq), depth,nbNodes); // right extension int len_right = traversal->traverse(kmer,right_traversal,strand); if (debug) printf("right traversal %i = %s\n", len_right,right_traversal); // save the node strcpy(node,kmer_seq);// + starting_kmer if we ask for the de bruijn graph or for a text output strcat(node,right_traversal);// + right_traversal int node_len=len_right+sizeKmer; //TODO: watch the reason of wrong length with depth = 0 fprintf(linear_seqs_file,">%lli__len__%i__depth__%i\n",nbNodes,node_len,depth); if (depth == 0 && dont_output_first_nucleotide ) /* we need this in mapsembler: // the first used kmer should be a k-1 mer. Indeed, if a first kmer is extracted from a sequence : /// -------------****** (k=6), then this node is the one linked to a new one starting with ******, thus with an overlap of k and not k-1. */ fprintf(linear_seqs_file,"%s\n",node+1); else fprintf(linear_seqs_file,"%s\n",node); nbNodes++; totalnt+=node_len; if (debug) { // printf ("[L=%s] assembled a %d bp node at depth %d\n",L.c_str(),node_len, depth); printf("(node seq: %s)\n",node); } // if we only want 1 extension, stop now if (when_to_stop_extending == IterativeExtensions::After_first_contig) { if (debug) printf("Stopping because we want only 1 extension\n"); break; } if(swf) { char * found = NULL; found =strstr(node, R.c_str()); if(found!=NULL && depth > sizeKmer) { if (debug) printf("swf STOP \n"); break; } } if(nbNodes > max_nodes) //GR stop when too complex huum when to stop ? { if (debug) printf("... XXX Stopped extending node %s because %d nodes reached. Was at depth %d.\n", node, nbNodes, depth); break; } // if max depth reached, don't extend that one if (depth + node_len > max_depth) { if (debug) printf("... XXX max depth reached for node %s (depth + node length %i %i = %i) \n",node, depth,node_len,depth + node_len ); continue; } #ifndef DONTMARK // make sure this is the only time we see this (k-1)-overlap bool already_seen = compare_and_mark_last_k_minus_one_mer(node, already_extended_from); if (already_seen) { if (debug) printf("... XXX not extending node %s becaues last k-1-mer was already seen\n",node); continue; } #endif kmer = extractKmerFromRead( node, node_len - sizeKmer, &kmer_fw, &kmer_rc, false); strand = (kmer == kmer_rc); if (debug) { code2seq(kmer,kmer_seq); if (strand == 1) revcomp_sequence(kmer_seq,sizeKmer); printf("... restarting from kmer %s %s\n",kmer_seq,strand?"(internally rc)":""); } // continue extending from immediately overlapping kmers // there may be just one 1 possibility (there was in-branching) int nb_extensions = 0; for(int test_nt=0; test_nt<4; test_nt++) { int current_strand = strand; kmer_type current_kmer = next_kmer(kmer,test_nt, ¤t_strand); if(bloo1->contains(current_kmer) && !false_positives->contains(current_kmer)){ kmers_to_traverse.push_back(kmer_strand_depth (current_kmer,current_strand,depth + len_right +1 )); // ou plutot depth + len_right +1 (+1 = la nt ajoutee ici) (et pas node_len) ? nb_extensions++; if (debug) { code2seq(current_kmer,kmer_seq); // convert starting kmer to nucleotide seq if (current_strand == 1) revcomp_sequence(kmer_seq,sizeKmer); printf("... --> found kmer immediately after kmer %s: %s \n",kmer_seq,current_strand?"(internally rc)":""); } } } if (debug) printf("... number of extensions: %d\n", nb_extensions); } //delete terminator; //delete traversal; free(right_traversal); //SolidKmers->close(); free(node); fclose(linear_seqs_file); } void IterativeExtensions::construct_linear_seqs_paired(string L, int max_depth, string output_file) { construct_linear_seqs_paired(L, string(),max_depth,output_file,2,1000000000); } /* * return the contig which starts with L, as well as all ths contigs that follow him, up to max_depth. * results go to a fasta file (output_file) * * requires that: * global variables terminator, bloo1 and false_positives are already constructed by minia * * outputs: * a set of contigs in the output file */ void IterativeExtensions::construct_linear_seqs_paired(string L,string R, int max_depth, string output_file , int verb, int max_nodes) { ///code for paired kmer int number_of_kmers_memorized = 1000; //should be greater than insert length, but maybe too much can be detrimental ? kmer_type * kmer_history = (kmer_type *) malloc (sizeof(kmer_type)*number_of_kmers_memorized); memset(kmer_history,0,sizeof(kmer_type)*number_of_kmers_memorized); int store_index =0; /// bool debug = verb>=2 ? 1 : 0; char bin2NT[4] = {'A','C','T','G'}; char bin2NTrev[4] = {'T','G','A','C'}; char binrev[4] = {2,3,0,1}; kmer_type kmer; char kmer_seq[sizeKmer+1]; FILE *linear_seqs_file; Traversal *traversal; if (traversal_type == IterativeExtensions::SimplePaths) traversal = new SimplePathsTraversal(bloo1,false_positives,terminator); else if (traversal_type == IterativeExtensions::Monument) traversal = new MonumentTraversal(bloo1,false_positives,terminator); traversal->set_maxlen(max_depth); traversal->set_max_depth(500); traversal->set_max_breadth(20); long long nbNodes = 0; long long totalnt=0; long long contig_len =0; long long maxlen=1000000; char *right_traversal = (char *) malloc(maxlen*sizeof(char)); char *node = (char *) malloc(maxlen*sizeof(char)); node [0] = '\0'; if(!output_file.empty()) { linear_seqs_file = fopen((char * )output_file.c_str(),"w"); } else { linear_seqs_file = NULL; IterativeExtensions::when_to_stop_extending = IterativeExtensions::After_first_contig; // sequence } STARTWALL(nodes); // heuristics: start from the last kmer of L vector < kmer_strand_depth > kmers_to_traverse; kmer_type kmer_fw, kmer_rc; kmer = extractKmerFromRead( (char *)L.c_str(), L.size() - sizeKmer, &kmer_fw, &kmer_rc, false); int strand = (kmer == kmer_rc); kmer_strand_depth first_kmer (kmer,strand,0); kmers_to_traverse.push_back(first_kmer); #ifndef DONTMARK set already_extended_from; compare_and_mark_last_k_minus_one_mer(L, already_extended_from); // mark first kmer to never extend from it again #endif while (kmers_to_traverse.size() > 0) // min_depth is max_gap_length here { kmer_strand_depth ksd = kmers_to_traverse.back(); kmers_to_traverse.pop_back(); kmer = ksd.kmer; int strand = ksd.strand; int depth = ksd.depth; code2seq(kmer,kmer_seq); // convert starting kmer to nucleotide seq if (strand == 1) revcomp_sequence(kmer_seq,sizeKmer); if (debug) printf("iteration: kmer %s%s (of lenght %zu) depth %d nbNodes explored %lli\n",kmer_seq,strand?" (internally rc)":"", strlen(kmer_seq), depth,nbNodes); // right extension int len_right = traversal->traverse(kmer,right_traversal,strand); if (debug) printf("right traversal = %s\n", right_traversal); // save the node strcpy(node,kmer_seq);// + starting_kmer if we ask for the de bruijn graph or for a text output strcat(node,right_traversal);// + right_traversal int node_len=len_right+sizeKmer; fprintf(linear_seqs_file,">%lli__len__%i__depth__%i\n",nbNodes,node_len,depth); if (depth == 0 && dont_output_first_nucleotide ) /* we need this in mapsembler: // the first used kmer should be a k-1 mer. Indeed, if a first kmer is extracted from a sequence : /// -------------****** (k=6), then this node is the one linked to a new one starting with ******, thus with an overlap of k and not k-1. */ fprintf(linear_seqs_file,"%s\n",node+1); else fprintf(linear_seqs_file,"%s\n",node); ////memorize previous kmers in the kmer_history, it is a circular buffer kmer_type kmer, graine, graine_revcomp ; for (int ii=0; ii max_nodes) //GR stop when too complex huum when to stop ? break; // if max depth reached, don't extend that one and clear kmer history, a new branch is explored if (depth + node_len > max_depth) { memset(kmer_history,0,sizeof(kmer_type)*number_of_kmers_memorized); store_index = 0; continue; } #ifndef DONTMARK // make sure this is the only time we see this (k-1)-overlap bool already_seen = compare_and_mark_last_k_minus_one_mer(node, already_extended_from); if (already_seen) continue; #endif //this is the last kmer of the contig kmer = extractKmerFromRead( node, node_len - sizeKmer, &kmer_fw, &kmer_rc, false); strand = (kmer == kmer_rc); if (debug) { code2seq(kmer,kmer_seq); if (strand == 1) revcomp_sequence(kmer_seq,sizeKmer); printf("restarting from kmer %s %s\n",kmer_seq,strand?"(internally rc)":""); } // continue extending from immediately overlapping kmers // there may be just one 1 possibility (there was in-branching) //we are at the end of a contig, we push the starting point of all possible branches in a stack of kmers //todo : push only kmers that are consistent with pairing information //use kmer_history and the pairedBranchingKmers object for that //Raluca //first, compute the degree of the kmer named "kmer" int degree = 0; int current_strand; kmer_type current_kmer, aux_kmer; int nt1=-1, nt2=-1; bool ok_nt1=false, ok_nt2=false; for(int test_nt=0; test_nt<4; test_nt++) { current_strand = strand; current_kmer = next_kmer(kmer,test_nt, ¤t_strand); if(bloo1->contains(current_kmer) && !false_positives->contains(current_kmer)) { degree++; nt1==-1 ? nt1 = test_nt : nt2 = test_nt; } } if(debug) { printf("degre %i \n",degree); } //second, depending on the degree and on whether we find the current_kmer in the history, we decide to push it or not if ( degree == 0 ) // this path ends, a new one will be explored, clear kmer history { memset(kmer_history,0,sizeof(kmer_type)*number_of_kmers_memorized); store_index = 0; } else if ( degree == 1 ) // not branching, is this possible knowing that we're at the end of a contig? { //if it is possible, then simply push the kmer obtained with nt1 ok_nt1 = true; ok_nt2 = false; } else if (degree == 2 ) { //we have the 2 extension, nt1 and nt2 //first, get the entries in pairedBranchingKmers for kmer named "kmer" pair_nt_kmer_t val; int is_present = pairedBranchingKmers->get(kmer, &val); if (!is_present) // strange { //simply push the two possible branches ok_nt1 = ok_nt2 = true; } else { if(debug) { printf("is_present, %c %c \n",bin2NT[nt1],bin2NT[nt2]); } int aux_nt; //search each of the two nucleotides in val of kmer for (int i=1; i<=2; i++) { aux_kmer = -1; i==1 ? aux_nt = bin2NT[nt1] : aux_nt = bin2NT[nt2]; if(debug) { // char seq[100]; // code2seq(aux_kmer, seq); printf("loop %i aux_nt %c \n",i,aux_nt); } if ( val.nk1.nt == aux_nt ) aux_kmer = val.nk1.prev_kmer; else if ( val.nk2.nt == aux_nt ) aux_kmer = val.nk2.prev_kmer; else { i==1 ? ok_nt1 = false : ok_nt2 = false; if ( i==2 && !ok_nt1 && !ok_nt2 ) break; } if(debug) { printf("loop %i ok_nt1 %i ok_nt2 %i \n",i,ok_nt1,ok_nt2); } //if one of the nt1 and nt2 corresponds, then search the corresponding prev_kmer (aux_kmer) in the history, if the prev_kmer is not present then ok_nt = false if ( aux_kmer != -1 ) { for ( int j=0; jclose(); free(node); fclose(linear_seqs_file); } /* requires: * bloo1 and false_positives are already constructed by minia * * outputs: * a pair containing: * 1/ the extension * 2/ the length of the first unitig composing this sequence. * - if the traversal is a simple traversal, then this length is equal to the length of the extension * - else (if the traversal is a monument traversal), then this length is equal to the starting position of the first bubble (if exist)) */ pair IterativeExtensions::extend_a_snp(string L, int max_depth) { // printf("\nExtended sequ = %s\n", L.c_str()); // DEB // bool debug = true; bool debug = false; kmer_type kmer; char kmer_seq[sizeKmer+1]; Traversal *traversal; if (traversal_type == IterativeExtensions::SimplePaths) traversal = new SimplePathsTraversal(bloo1,false_positives,terminator); else if (traversal_type == IterativeExtensions::Monument) traversal = new MonumentTraversal(bloo1,false_positives,terminator); traversal->set_maxlen(max_depth); traversal->set_max_depth(500); traversal->set_max_breadth(20); long long nbNodes = 0; long long totalnt=0; long long contig_len =0; long long maxlen=1000000; char *right_traversal = (char *) malloc(maxlen*sizeof(char)); char *node = (char *) malloc(maxlen*sizeof(char)); node [0] = '\0'; IterativeExtensions::when_to_stop_extending = IterativeExtensions::After_first_contig; // sequence STARTWALL(nodes); // heuristics: start from the last kmer of L kmer_type kmer_fw, kmer_rc; kmer = extractKmerFromRead( (char *)L.c_str(), L.size() - sizeKmer, &kmer_fw, &kmer_rc, false); int strand = (kmer == kmer_rc); code2seq(kmer,kmer_seq); // convert starting kmer to nucleotide seq // printf("Extended kmer = %s strand = %d\n", kmer_seq, strand); // DEB if (strand == 1) revcomp_sequence(kmer_seq,sizeKmer); // if (debug) // printf("iteration: kmer %s%s depth %d\n",kmer_seq,strand?" (internally rc)":"", 0); // right extension int len_right = traversal->traverse(kmer,right_traversal,strand); // if(debug) printf("right traversal = %s\n", right_traversal); // save the node strcpy(node,kmer_seq);// + starting_kmer if we ask for the de bruijn graph or for a text output strcat(node,right_traversal);// + right_traversal free(right_traversal); int first_divergence=strlen(node); if (traversal_type == IterativeExtensions::Monument && traversal->bubbles_positions.size()>0) { first_divergence=traversal->bubbles_positions[0].first+sizeKmer; } return std::make_pair(node,first_divergence); } discoSnp/kissnp2/SNP.cpp0000644000000000000000000010631212365451150014100 0ustar rootroot//Copyright inria / irisa (2013) // // //raluca.uricaru@gmail.com //pierre.peterlongo@inria.fr // //This software is a computer program whose purpose is to call SNPs from NGS reads. // //This software is governed by the CeCILL license under French law and //abiding by the rules of distribution of free software. You can use, //modify and/ or redistribute the software under the terms of the CeCILL //license as circulated by CEA, CNRS and INRIA at the following URL //"http://www.cecill.info". // //As a counterpart to the access to the source code and rights to copy, //modify and redistribute granted by the license, users are provided only //with a limited warranty and the software's author, the holder of the //economic rights, and the successive licensors have only limited //liability. // //In this respect, the user's attention is drawn to the risks associated //with loading, using, modifying and/or developing or reproducing the //software by the user in light of its specific status of free software, //that may mean that it is complicated to manipulate, and that also //therefore means that it is reserved for developers and experienced //professionals having in-depth computer knowledge. Users are therefore //encouraged to load and test the software's suitability as regards their //requirements in conditions enabling the security of their systems and/or //data to be ensured and, more generally, to use and operate it in the //same conditions as regards security. // //The fact that you are presently reading this means that you have had //knowledge of the CeCILL license and that you accept its terms. // // SNP.cpp // #ifndef ASSERTS #define NDEBUG // disable asserts, they're computationnally intensive #endif #include #include #include #include #include #include #include // for max #include "SNP.h" #include "../minia/Terminator.h" #include "../minia/Traversal.h" // for extensions() #include "filter.h" #include "commons.h" #include "IterativeExtensions.h" extern int sizeKmer; extern int threshold; char bin2NT[8] = {'A','C','T','G','A','C','T','G'}; //#define DEBUG FILE * SNP_file; //bool already_an_extension; using namespace::std; unsigned long int nb_bubbles=0, nb_bubbles_high=0, nb_bubbles_low=0; unsigned char Bubble::branching_structure(kmer_type graine) { kmer_type next_kmer; unsigned char result = 0; int nt; int strand; for(nt=0; nt<4; nt++) { // forward right extensions strand=0; next_kmer = next_kmer_new(graine,nt,strand); if(bloom_solid_kmers->contains(next_kmer) && !debloom->contains(next_kmer)){ result|=1<contains(next_kmer) && !debloom->contains(next_kmer)){ result|=1<<(nt+4); } } return result; } //extend two 2k-1 paths with a new nucleotide left and a new nucleotide right. //returns 0: no unique extension neither left nor right, 1 unique only left, 2 unique only right, 3: both int Bubble::close_snp(const char * path1, const char * path2, char *path1_c, char *path2_c){ kmer_type kmer_fw, kmer_rc; int strand; int i; kmer_type kmer; char right_extension=-1, left_extension=-1; char * seq1 = (char *) malloc((2*sizeKmer)*sizeof(char)); for(i=0;i<2*sizeKmer-1;i++) seq1[i]=bin2NT[path1[i]]; seq1[2*sizeKmer-1]='\0'; //RIGHT EXTENSION kmer = extractKmerFromRead(seq1, strlen(seq1) - sizeKmer, &kmer_fw, &kmer_rc, false); strand = (kmer == kmer_rc); bool left_extensible; bool right_extensible; int nb_right_extensions = 0; for(int test_nt=0; test_nt<4; test_nt++) { int current_strand = strand; kmer_type current_kmer = next_kmer(kmer,test_nt, ¤t_strand); if(bloo1->contains(current_kmer) && !false_positives->contains(current_kmer)){ right_extension=test_nt; nb_right_extensions++; //break; } } if (nb_right_extensions == 1) // one right extension found, extend to the right right_extensible=true; else right_extensible=false; // LEFT EXTENSION int nb_left_extensions = 0; revcomp(seq1, strlen(seq1)); kmer = extractKmerFromRead(seq1, strlen(seq1) - sizeKmer, &kmer_fw, &kmer_rc, false); strand = (kmer == kmer_rc); for(int test_nt=0; test_nt<4; test_nt++) { int current_strand = strand; kmer_type current_kmer = next_kmer(kmer,test_nt, ¤t_strand); if(bloo1->contains(current_kmer) && !false_positives->contains(current_kmer)){ left_extension=test_nt; nb_left_extensions++; //break; } } revcomp(seq1, strlen(seq1)); if (nb_left_extensions == 1 ) // one left extension found, extend to the left left_extensible = true; else left_extensible=false; free(seq1); //returns 0 no extension neither left nor right, 1 unique only left, 2 unique only right, unique 3 both // Add the new results. (revcomp of left extension and rigth extension). // put the found bubble in the middle of the 2k+1 length array // DO NOT MODIFY path1 AND path2 as we still need them outside this method if (!left_extensible && !right_extensible){//no extension, 2k-1 paths for(i=0;i<2*sizeKmer-1;i++) { path1_c[i]=bin2NT[path1[i]]; path2_c[i]=bin2NT[path2[i]]; } path1_c[i]='\0'; path2_c[i]='\0'; return 0; } if (left_extensible && !right_extensible){//2k path, only left path1_c[0]=bin2NT[revcomp_int(left_extension)]; path2_c[0]=bin2NT[revcomp_int(left_extension)]; for(i=1;i<=2*sizeKmer-1;i++) { path1_c[i]=bin2NT[path1[i-1]]; path2_c[i]=bin2NT[path2[i-1]]; } path1_c[i]='\0'; path2_c[i]='\0'; return 1; } if (!left_extensible && right_extensible){//2k path, only right for(i=0;i<2*sizeKmer-1;i++) { path1_c[i]=bin2NT[path1[i]]; path2_c[i]=bin2NT[path2[i]]; } path1_c[i]=bin2NT[right_extension]; path2_c[i]=bin2NT[right_extension]; i++; path1_c[i]='\0'; path2_c[i]='\0'; return 2; } if (left_extensible && right_extensible) { path1_c[0]=bin2NT[revcomp_int(left_extension)]; path2_c[0]=path1_c[0]; for(i=1;i<2*sizeKmer;i++) { path1_c[i]=bin2NT[path1[i-1]]; path2_c[i]=bin2NT[path2[i-1]]; } path1_c[i]=bin2NT[right_extension]; path2_c[i]=bin2NT[right_extension]; i++; path1_c[i]='\0'; path2_c[i]='\0'; return 3; } assert(1==0); // should not come here } // prints the headers depending of the extension choice. inline void prints_contig_informations(FILE * file, std::pair left_extension, std::pair right_extension, bool strict_extension, int where_to_extend){ // printf("strict_extension = %s\n", strict_extension?"true":"false"); if (strict_extension){ if(where_to_extend == 0) fprintf(file,"|left_unitig_length_0|right_unitig_length_0"); if(where_to_extend == 1) fprintf(file,"|left_unitig_length_%d|right_unitig_length_0", (int)strlen(left_extension.first)-sizeKmer+1); //+1 because of close_snp if(where_to_extend == 2) fprintf(file,"|left_unitig_length_0|right_unitig_length_%d", (int)strlen(right_extension.first)-sizeKmer+1);//+1 because of close_snp if(where_to_extend == 3) fprintf(file,"|left_unitig_length_%d|right_unitig_length_%d", (int)strlen(left_extension.first)-sizeKmer+1,(int)strlen(right_extension.first)-sizeKmer+1);//+1 because of close_snp } if(!strict_extension){ if(where_to_extend == 0){ fprintf(file,"|left_unitig_length_0|right_unitig_length_0"); fprintf(file,"|left_contig_length_0|right_contig_length_0"); } if(where_to_extend == 1){ fprintf(file,"|left_unitig_length_%d|right_unitig_length_0", left_extension.second-sizeKmer+1); //+1 because of close_snp fprintf(file,"|left_contig_length_%d|right_contig_length_0", (int)strlen(left_extension.first)-sizeKmer+1); //+1 because of close_snp } if(where_to_extend == 2){ fprintf(file,"|left_unitig_length_0|right_unitig_length_%d", right_extension.second-sizeKmer+1);//+1 because of close_snp fprintf(file,"|left_contig_length_0|right_contig_length_%d", (int)strlen(right_extension.first)-sizeKmer+1);//+1 because of close_snp } if(where_to_extend == 3){ fprintf(file,"|left_unitig_length_%d|right_unitig_length_%d", left_extension.second-sizeKmer+1,right_extension.second-sizeKmer+1);//+1 because of close_snp fprintf(file,"|left_contig_length_%d|right_contig_length_%d", (int)strlen(left_extension.first)-sizeKmer+1,(int)strlen(right_extension.first)-sizeKmer+1);//+1 because of close_snp } } } /** * Extends if necessary left and/or right parts of the bubble. * Prints results * path1 and path2: character pathes (no binary format). Of length 2k-1, 2k, or 2k+1, depending ont the results of "close_snps" * score=complexity score * where_to_extend : 0=nothing, 1=left only, 2=right only, 3=both */ void Bubble::print_sequence_and_eventually_contigs(char * path1, char * path2, const int score, int where_to_extend){ int i; terminator->reset(); // need to reset branching kmers between extensions in case of overlapping extensions. FILE * file; //Here, path1 and path2 may have 2k, 2k-1 or 2k+1 size int size_path = strlen(path1); pair right_contig; pair left_contig; if(extend_snps){// && where_to_extend > 0){ if(strict_extension) IterativeExtensions::traversal_type = IterativeExtensions::SimplePaths; // strict else IterativeExtensions::traversal_type = IterativeExtensions::Monument; // contigs if (where_to_extend == 2 || where_to_extend == 3) right_contig=IterativeExtensions::extend_a_snp(path1,10000); // path1 or path2 provides the same result (the extended kmer is not involved) if (where_to_extend == 1 || where_to_extend == 3) { revcomp(path1, size_path); // get the reverse complement of the sequence left_contig=IterativeExtensions::extend_a_snp(path1,10000); // get the left extension of this sequence revcomp(left_contig.first, strlen(left_contig.first)); // put back the left contig in the right order revcomp(path1, size_path); // put back the sequence in the right order. } if(min_size_extension >-1){ if(where_to_extend<3 || (int)strlen(left_contig.first)-sizeKmerSNP_higher_path_%lu|score_%d|", nb_bubbles, score); fprintf(file, ">SNP_higher_path_%lu|", nb_bubbles); if ( score >= threshold ) fprintf(file,"low"); else { fprintf(file,"high"); } prints_contig_informations(file, left_contig, right_contig, strict_extension, where_to_extend); fprintf(file,"\n"); if (print_extensions && extend_snps){ // prints the left extension if(where_to_extend%2==1) for(i=0;i1) // right: last nucleotide is an extension path1[size_path-1]=tolower(path1[size_path-1]); fprintf(file,"%s",path1); if(extend_snps && print_extensions && where_to_extend>1) for(i=sizeKmer;i1) // right: last nucleotide is an extension stop--; } for(i=start;iSNP_lower_path_%lu|", nb_bubbles); if ( score >= threshold ) fprintf(file,"low"); else fprintf(file,"high"); prints_contig_informations(file, left_contig, right_contig, strict_extension, where_to_extend); fprintf(file,"\n"); if (print_extensions && extend_snps){ if(print_extensions && where_to_extend%2==1) for(i=0;i1) // right: last nucleotide is an extension path2[size_path-1]=tolower(path2[size_path-1]); fprintf(file,"%s",path2); if(extend_snps && print_extensions && where_to_extend>1) for(i=sizeKmer;i1) // right: last nucleotide is an extension stop--; } for(i=start;i1){ free(right_contig.first); } } // determines if a kmer is branching or not, function copied (I know, it's horrible) from Terminator.cpp in minia //bool Bubble::is_branching(kmer_type kmer) //{ // bool reversed = false; // if (kmer > revcomp(kmer)) { // kmer = revcomp(kmer); // reversed = true; // } // // // cannot really be optimized, because most kmers will be non-branching, hence computing branching_structure() takes optimal time // int nb_forward_links = 0, nb_reverse_links = 0; // int i; // unsigned char branching = branching_structure(kmer); // // for (i=0;i<4;i++) // nb_forward_links += (branching>>i)&1; // // for (i=4;i<8;i++) // nb_reverse_links += (branching>>i)&1; // // if(reversed) kmer = revcomp(kmer); // go back to the good value. // return !(nb_forward_links == 1 && nb_reverse_links == 1); // //} //void Bubble::expand_BubblePierre(int direction, char* path1, char* path2, kmer_type kmer1, kmer_type kmer2, int pos, char *p1, char *p2, char *p3, char *p4, int low, int authorised_branching){ // kmer_type next_kmer1, next_kmer2; // int nt,nt2,i,score; // char p_aux1[sizeKmer+1], p_aux2[sizeKmer+1]; // // // // if (pos <= sizeKmer-1) // { // for(nt=0; nt<4; nt++) // { // next_kmer1 = next_kmer_new(kmer1,nt,direction); // next_kmer2 = next_kmer_new(kmer2,nt,direction); // // if(authorised_branching && // (is_branching(next_kmer1) || is_branching(next_kmer2)) // ) continue; // one of the two new kmers is branching, we continue. // // code2seq(next_kmer1, p_aux1); // code2seq(next_kmer2, p_aux2); //#ifdef DEBUG // if ( !(strcmp(p_aux1,p1) && strcmp(p_aux1,p2) && strcmp(p_aux2,p3) && strcmp(p_aux2,p4)) ) // { // if ( !strcmp(p_aux1,p1) ) // printf("\n1st branch: 1st and 3rd equal kmers %s\n", p_aux1); // if ( !strcmp(p_aux1,p2) ) // printf("\n1st branch: 2nd and 3rd equal kmers %s\n", p_aux1); // if ( !strcmp(p_aux2,p3) ) // printf("\n2nd branch: 1st and 3rd equal kmers %s\n", p_aux2); // if ( !strcmp(p_aux2,p4) ) // printf("\n2nd branch: 2nd and 3rd equal kmers %s\n", p_aux2); // } //#endif // if(bloom_solid_kmers->contains(next_kmer1) && !debloom->contains(next_kmer1) && bloom_solid_kmers->contains(next_kmer2) && !debloom->contains(next_kmer2) // && strcmp(p_aux1,p1) && strcmp(p_aux1,p2) && strcmp(p_aux2,p3) && strcmp(p_aux2,p4)) // { // // strcpy(p1, p2); // strcpy(p3, p4); // strcpy(p2, p_aux1); // strcpy(p4, p_aux2); // // if ( direction == 0 ){ // //if everything is ok then we only use direction = 0 // path1[sizeKmer-1+pos]=nt; // path2[sizeKmer-1+pos]=nt; // } // else // { // //shouldn't go in here // path1[sizeKmer-1+pos]=nt+4; // path2[sizeKmer-1+pos]=nt+4; // } // // //if we finished the bubble and need to close it // if ( pos == sizeKmer-1 ) // { // //TEST whether the first kmer of the first path is smaller than the first kmer of the revcomp(first path), this should avoid repeated SNPs // char first_kmer[sizeKmer+1], first_kmer_rev[sizeKmer+1]; // for ( i=0; i=threshold && low)) // { // char path1_c[2*sizeKmer+1], path2_c[2*sizeKmer+1]; // if(close_snp(path1, path2, path1_c, path2_c)) // PRINT A SNP Only if we can close it right and left // { // if (score < threshold) // nb_bubbles_high++; // else // nb_bubbles_low++; // // print_sequence_and_eventually_contigs(path1_c, path2_c, score); // } // } // } // } // else //bubble not yet finished // { // // next_kmer1 = next_kmer_new_norevcomp(kmer1,nt,direction); // next_kmer2 = next_kmer_new_norevcomp(kmer2,nt,direction); // expand_Bubble(direction, path1, path2, next_kmer1, next_kmer2, pos+1, p1, p2, p3, p4, low, authorised_branching); // } // } // } // } //} bool Bubble::two_possible_extensions_on_one_path(kmer_type kmer){ kmer_type next_kmer; bool already_an_extension; for (int d=0; d<=1; d++) { already_an_extension = false; for(int nt=0; nt<4; nt++) { next_kmer = next_kmer_new(kmer,nt,d); if(bloom_solid_kmers->contains(next_kmer) && !debloom->contains(next_kmer)){ if (already_an_extension) return true; already_an_extension = true; } } } return false; } bool Bubble::two_possible_extensions(kmer_type kmer1, kmer_type kmer2){ kmer_type next_kmer1, next_kmer2; char p_aux1[sizeKmer+1], p_aux2[sizeKmer+1]; bool already_an_extension = false; for (int d=0; d<=1; d++) { for(int nt=0; nt<4; nt++) { next_kmer1 = next_kmer_new(kmer1,nt,d); next_kmer2 = next_kmer_new(kmer2,nt,d); code2seq(next_kmer1, p_aux1); code2seq(next_kmer2, p_aux2); if(bloom_solid_kmers->contains(next_kmer1) && !debloom->contains(next_kmer1) && bloom_solid_kmers->contains(next_kmer2) && !debloom->contains(next_kmer2) )//&& strcmp(p_aux1,p1) && strcmp(p_aux1,p2) && strcmp(p_aux2,p3) && strcmp(p_aux2,p4)) { if (!already_an_extension) { #ifdef DEBUG printf("\nFirst branching in direction %d with %c at pos %d\n", d, bin2NT[nt], pos); #endif already_an_extension = true; } else { #ifdef DEBUG code2seq(kmer1, p_aux1); code2seq(kmer2, p_aux2); printf("\nDon't expand, branching in direction %d with %c for %s and %s at pos %d\n", d, bin2NT[nt], p_aux1, p_aux2, pos); #endif return true; } } } already_an_extension = false; } return false; } /**************************************************************************************************************** //the 2 functions that follow build bubbles starting from the first node in the bubble (after the switching node) *****************************************************************************************************************/ /** * ... * authorised_branching = * - 0: branching forbiden in any path * - 1: same branching on both path forbiden (i.e. 2 disctinct nucelotides may be used in both paths for extension) * - 2: no restriction on branching */ void Bubble::expand_Bubble(int direction, char* path1, char* path2, kmer_type kmer1, kmer_type kmer2, int pos, char *p1, char *p2, char *p3, char *p4, int low, int authorised_branching){ kmer_type next_kmer1, next_kmer2; int nt,nt2,i,score; char p_aux1[sizeKmer+1], p_aux2[sizeKmer+1]; // ---x--- (2k-1) // 0123456 // * (size kmer -1) if (pos <= sizeKmer-1) { // stop the extension if authorised_branching==0 (not branching in any path) and any of the two paths is branching if (authorised_branching==0 && (two_possible_extensions_on_one_path(kmer1) || two_possible_extensions_on_one_path(kmer2))) return; // stop the extension if authorised_branching==1 (not branching in both path) and both the two paths are branching if (authorised_branching==1 && two_possible_extensions (kmer1, kmer2)) return; for(nt=0; nt<4; nt++) { next_kmer1 = next_kmer_new(kmer1,nt,direction); next_kmer2 = next_kmer_new(kmer2,nt,direction); code2seq(next_kmer1, p_aux1); code2seq(next_kmer2, p_aux2); #ifdef DEBUG printf("\nTry %d at pos %d\n for kmers %s %s\n", nt, pos, p_aux1, p_aux2); if ( !(strcmp(p_aux1,p1) && strcmp(p_aux1,p2) && strcmp(p_aux2,p3) && strcmp(p_aux2,p4)) ) { if ( !strcmp(p_aux1,p1) ) printf("\n1st branch: 1st and 3rd equal kmers %s\n", p_aux1); if ( !strcmp(p_aux1,p2) ) printf("\n1st branch: 2nd and 3rd equal kmers %s\n", p_aux1); if ( !strcmp(p_aux2,p3) ) printf("\n2nd branch: 1st and 3rd equal kmers %s\n", p_aux2); if ( !strcmp(p_aux2,p4) ) printf("\n2nd branch: 2nd and 3rd equal kmers %s\n", p_aux2); } #endif if(bloom_solid_kmers->contains(next_kmer1) && !debloom->contains(next_kmer1) && bloom_solid_kmers->contains(next_kmer2) && !debloom->contains(next_kmer2) && strcmp(p_aux1,p1) && strcmp(p_aux1,p2) && strcmp(p_aux2,p3) && strcmp(p_aux2,p4)) { strcpy(p1, p2); strcpy(p3, p4); strcpy(p2, p_aux1); strcpy(p4, p_aux2); if ( direction == 0 ){ //if everything is ok then we only use direction = 0 path1[sizeKmer-1+pos]=nt; path2[sizeKmer-1+pos]=nt; } else { //shouldn't go in here path1[sizeKmer-1+pos]=nt+4; path2[sizeKmer-1+pos]=nt+4; } //if we finished the bubble and need to close it if ( pos == sizeKmer-1 ) { //TEST whether the first kmer of the first path is smaller than the first kmer of the revcomp(first path), this should avoid repeated SNPs char first_kmer[sizeKmer+1], first_kmer_rev[sizeKmer+1]; for ( i=0; i=threshold && low)) { char path1_c[2*sizeKmer+2], path2_c[2*sizeKmer+2]; // +2 stands for the \0 character if (score < threshold) nb_bubbles_high++; else nb_bubbles_low++; //do not close snps and output only 2k-1 paths if extend_snps is not true int where_to_extend=0; if (!extend_snps) { for(i=0;i<2*sizeKmer-1;i++) { path1_c[i]=bin2NT[path1[i]]; path2_c[i]=bin2NT[path2[i]]; } path1_c[i]='\0'; path2_c[i]='\0'; } else where_to_extend = close_snp(path1, path2, path1_c, path2_c); print_sequence_and_eventually_contigs(path1_c, path2_c, score, where_to_extend); //2k-1, 2k or 2k+1 paths } } } else //bubble not yet finished { next_kmer1 = next_kmer_new_norevcomp(kmer1,nt,direction); next_kmer2 = next_kmer_new_norevcomp(kmer2,nt,direction); code2seq(next_kmer1, p_aux1); code2seq(next_kmer2, p_aux2); #ifdef DEBUG printf("\nExpanded with %d at pos %d\n for kmers %s %s\n", nt, pos, p_aux1, p_aux2); #endif expand_Bubble(direction, path1, path2, next_kmer1, next_kmer2, pos+1, p1, p2, p3, p4, low, authorised_branching); #ifdef DEBUG code2seq(next_kmer1, p_aux1); code2seq(next_kmer2, p_aux2); printf("\nReturn to expansion with %d at pos %d\n for kmers %s %s\n", nt, pos, p_aux1, p_aux2); #endif //there's only one branch to expand if we keep non branching SNPs only, therefore we can safely stop the for loop if ( authorised_branching==0 || authorised_branching==1 ) break; } } } } } //tries to start a bubble from the current node, first node containing a SNP void Bubble::start_Bubble(kmer_type kmer1, int low, int authorised_branching) { char seq1[256], seq2[256];//, seq_aux[26]; int i,j, direction; char path1[2*sizeKmer-1], path2[2*sizeKmer-1]; kmer_type kmer2, kmer_aux; char p1[sizeKmer+1], p2[sizeKmer+1], p3[sizeKmer+1], p4[sizeKmer+1]; #ifdef DEBUG { printf("\nInitial kmer "); code2seq(kmer1, seq1); for (j=0;j<=sizeKmer-1;j++) printf("%c",seq1[j]); } #endif for (direction=0; direction<=1; direction++) { if ( direction == 1 ) { // start bubble for kmer in reverse form kmer1 = revcomp(kmer1); } // PATCH 20 May 2014: check if the initial kmer can be reverse extended : this allows to test all its possible alternative ends bool exists_previous=false; for(int nt=0; nt<4; nt++) { kmer_type previous_kmer = next_kmer_new(kmer1,nt,1); if(bloom_solid_kmers->contains(previous_kmer) && !debloom->contains(previous_kmer)){ exists_previous=true; break; } } if (!exists_previous) continue; // in this case, we can't test the alternative ends of kmer1. // end PATCH code2seq(kmer1, seq1); code2seq(kmer1, seq2); for (i=0; icontains(min(kmer2,revcomp(kmer2))) && !debloom->contains(min(kmer2,revcomp(kmer2)))) // the tried kmer is indexed. { path2[sizeKmer-1] = NT2int(seq2[sizeKmer-1]); strcpy(p1,"\0"); strcpy(p3,"\0"); code2seq(kmer1, p2); code2seq(kmer2, p4); #ifdef DEBUG printf("\nCouple with %c \n", bin2NT[i]); #endif // already_an_extension = false; expand_Bubble(0, path1, path2, kmer1, kmer2, 1, p1, p2, p3, p4, low, authorised_branching); // we open a new putative bubble #ifdef DEBUG printf("\n Starting Bubble\n"); if ( direction == 1) printf("reverse\n"); for (j=1;j<=sizeKmer;j++) printf("%c",bin2NT[path1[j]]); printf("\n"); for (j=1;j<=sizeKmer;j++) printf("%c",bin2NT[path2[j]]); #endif } else { #ifdef DEBUG printf("\ndoes not contain it"); #endif } } } } void Bubble::find_bubbles(const char * SNP_file_name, int low, int authorised_branching) { kmer_type kmer; // printf("\nSearch for bubbles with threshold %d\n", threshold); SNP_file=fopen(SNP_file_name,"w"); if(SNP_file == NULL){ fprintf(stderr,"cannot open file %s, exit\n",SNP_file_name); exit(1); } printf("Find Bubbles:\n"); unsigned long int nb=0; off_t nbel = SolidKmers->nb_elements(); while (SolidKmers->read_element(&kmer)) { if(nb%1000==0) {printf("%c \t %llu %%",13,(nb*100)/nbel); } nb++; //start_SwitchingNode(kmer); start_Bubble(kmer, low, authorised_branching); } printf("%c \t 100 %%\n", 13); fclose(SNP_file); printf("\nFound %lu bubbles (not branching if demanded and with no restriction on closing). Among these, we select the closing bubbles with non-branching kmers (if demanded), from which %lu are high complexity bubbles and %lu are low complexity bubbles (by default, this is 0 if low bubbles do not have to be printed)\n", nb_bubbles, nb_bubbles_high, nb_bubbles_low); } /*void Bubble::read_bubble_file(char *bubble_filename) { FILE *bubble_file; char line[512], line2[512]; char SNP[2*sizeKmer-1]; int i, score, hc_bubbles=0, lc_bubbles=0; printf("kissnp is opeing file %s\n", bubble_filename); bubble_file = fopen(bubble_filename,"r"); if (bubble_file == NULL) { printf("kissnp error opening file: %s\n",bubble_filename); exit(1); } while(fgets(line, 512, bubble_file) != NULL){ if ( strstr(line, "Bubble") != NULL) { strcpy(line2, line); if ( fgets(line, 512, bubble_file) != NULL ) { for (i=0; i<2*sizeKmer-1; i++) SNP[i]=NT2int(line[i+1]); score = filterLowComplexity(SNP, 2*sizeKmer-1,threshold); if ( score >= 2*threshold ) { printf("Low complexity bubble with score %d\n", score); lc_bubbles++; } else { printf("%s", line2); printf("High complexity bubble with score %d\n", score); hc_bubbles++; printf("%s\n", line); } } } } printf("%d high complexity bubbles and %d low complexity bubbles, with threshold %d", hc_bubbles, lc_bubbles, threshold); fclose(bubble_file); }*/ discoSnp/kissnp2/makefile0000644000000000000000000000624512236717642014450 0ustar rootroot#Copyright inria / irisa (2013) # # #raluca.uricaru@gmail.com #pierre.peterlongo@inria.fr # #This software is a computer program whose purpose is to call SNPs from NGS reads. # #This software is governed by the CeCILL license under French law and #abiding by the rules of distribution of free software. You can use, #modify and/ or redistribute the software under the terms of the CeCILL #license as circulated by CEA, CNRS and INRIA at the following URL #"http:#www.cecill.info". # #As a counterpart to the access to the source code and rights to copy, #modify and redistribute granted by the license, users are provided only #with a limited warranty and the software's author, the holder of the #economic rights, and the successive licensors have only limited #liability. # #In this respect, the user's attention is drawn to the risks associated #with loading, using, modifying and/or developing or reproducing the #software by the user in light of its specific status of free software, #that may mean that it is complicated to manipulate, and that also #therefore means that it is reserved for developers and experienced #professionals having in-depth computer knowledge. Users are therefore #encouraged to load and test the software's suitability as regards their #requirements in conditions enabling the security of their systems and/or #data to be ensured and, more generally, to use and operate it in the #same conditions as regards security. # #The fact that you are presently reading this means that you have had #knowledge of the CeCILL license and that you accept its terms. CC=g++ CFLAGS= -O4 -lz -DMINIA_IS_IN_PARENT_FOLDER #CFLAGS= -O4 -lz -DMINIA_IS_IN_PARENT_FOLDER -DDONTMARK SRC=../minia/Pool.cpp ../minia/Bank.cpp ../minia/Bloom.cpp ../minia/Hash16.cpp ../minia/Terminator.cpp ../minia/Kmer.cpp ../minia/Traversal.cpp ../minia/LinearCounter.cpp ../minia/Set.cpp ../minia/Utils.cpp ../minia/SortingCount.cpp ../minia/Debloom.cpp ../minia/OAHash.cpp Kmer_for_kissnp2.cpp SNP.cpp filter.cpp IterativeExtensions.cpp commons.cpp EXEC=kissnp2 OBJ= $(SRC:.cpp=.o) all: $(EXEC) ifeq ($(prof),1) CFLAGS=-O3 -pg -lz endif ifeq ($(deb),1) CFLAGS+=-O0 -DASSERTS -g -lz endif k := 0$(k) # dummy k if not specified K_BELOW_32 := $(shell echo $(k)\<=32 | bc) K_BELOW_64 := $(shell echo $(k)\<=64 | bc) ARCH := $(shell getconf LONG_BIT) # detects sizeof(int) USING_UINT128 := 0 ifeq ($(K_BELOW_32),0) # use uint128 when k<=64 and 64-bit architecture ifeq ($(K_BELOW_64),1) ifeq ($ARCH),64) CFLAGS += -Dkmer_type=__uint128_t USING_UINT128 := 1 endif endif # use a bigint library otherwise ifeq ($(USING_UINT128),0) ttmath := 1 endif endif # ttmath is used when you type "make k=[kmer size]" with a kmer size longer than supported integer type, # or when typing "make k=[anything] ttmath=1" ifeq ($(ttmath),1) KMER_PRECISION := $(shell echo \($(k)+15\)/16 | bc) CFLAGS += -D_ttmath -DKMER_PRECISION=$(KMER_PRECISION) endif all: $(EXEC) kissnp2: $(OBJ) kissnp2.cpp $(CC) -o $@ $^ $(CFLAGS) %.o: %.cpp %.h $(CC) -o $@ -c $< $(CFLAGS) %.o: %.c %.h $(CC) -o $@ -c $< $(CFLAGS) clean: rm -rf *.o ../minia/*.o discoSnp/kissnp2/commons.cpp0000644000000000000000000001164512365450656015131 0ustar rootroot/** * Copyright INRIA and ENS, contributors Peterlongo and Chikhi * pierre.peterlongo@inria.fr * rayan.chikhi@irisa.fr * * This software is a computer program whose purpose is to detect the * presence of a starter in a set of NGS reads, and to provide the neighbor * in case of success.. * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * commons.c * * Created on: 17 sept. 2010 * Author: ppeterlo */ #include "commons.h" #include #include #include #include extern size_t strlen (const char*); char comp['t'+1]; char nuc [4]; char keyi2nucleotide_array ['T'+1]; int size_seeds=25; // USED ONLY FOR MAPPING, might be different from the kmer_size used in minia. Size_seeds is no more than 32. char * prefix_trashable=(char *)"trashmeplease"; unsigned int nbits_nbseeds; uint64_t mask_nbseed ; uint64_t mask_offset_seed; /** * redefined this fonction for mac users, absent from string.h */ char * strndup (const char *s, size_t n) { char *result; size_t len = strlen (s); if (n < len) len = n; result = (char *) malloc (len + 1); if (!result) return 0; result[len] = '\0'; return (char *) memcpy (result, s, len); } static int cmpstringp(const void *p1, const void *p2) { /* Les arguments de cette fonction sont des "pointeurs de pointeurs sur des caractères", mais les arguments de strcmp(3) sont des "pointeurs sur des caractères", d’où le forçage de type et l’utilisation de l’astérisque */ return strcmp(* (char * const *) p1, * (char * const *) p2); } char ** sort_strings (char ** strings, int number) { qsort(strings,number, sizeof(char *), cmpstringp); return strings; } void init_static_variables(){ int i; for (i=0;i<'T'+1;i++) { comp[i]=i; // for other iupac alphabet letters } comp['A']='T'; comp['T']='A'; comp['C']='G'; comp['G']='C'; comp['a']='t'; comp['t']='a'; comp['c']='g'; comp['g']='c'; nuc[0]='A'; nuc[1]='C'; nuc[2]='G'; nuc[3]='T'; keyi2nucleotide_array['A']=0; keyi2nucleotide_array['C']=1; keyi2nucleotide_array['G']=2; keyi2nucleotide_array['T']=3; } void print_rev_comp(char s[], FILE * out){ int i; const int len=strlen(s); for(i=len-1;i>-1;i--)fprintf(out, "%c",comp[(int)s[i]]); } void revcomp(char *s, int len) { int i; char t; for (i=0;i %c |", word[i]); i++; } // printf("after upper=%s\n", word); return word; } char * to_lower (char * word){ int i=0; while(word[i]!='\0') {word[i]=tolower(word[i]); i++;} return word; } char line[1048576]; // TODO: REMOVE THIS AND CHECK ALL POTENTIAL PROJECTS USING THIS FUNCTION int last_index_of(char * string, char character){ int i, pos=-1; for(i=0;i> stream x[I+ϯـ.$ 7;` ?*."ͳ}CXNp0ѴL'u#᧿~~MFv0p`=Vkpfa׿ݎ LaV %JtFGJ ;3Q]m`Ytz8\7Bx77Z{.{*L=EW`jQfON4N%0;7))3HidJޑ<8J,.?owj,AߣVCfnj^Xp .4gqrk/=p]GTphsʓWu7#te]xF8)"Fx5`N4e5 8̧;k\mF+ \;򤩥ٹT4@e4;ډ'nr3UAٜ=7+mQ†q \ Ŋ'nCY^J1pP~NF*_)O~rE3{'/->,Э&Z踜ЋϷ)^ ,B񚓗"m/,*||ZL'-o+^KCMEւORs]UlnU8*v=uʉxbOqR;](t8ufP8ZlzRO5k7{D-l)|Zl^t貉E!ܠFiNvY;Z >Uܾz9u SOVl]T[}V`flC:Ox g8yig' jjP˨ݐ'׍߭P!YN0(jf)=+FL.R`t[} 8ҴjtS ȸ su*qyoXa} xcnq g?~(Ƿޟm8 ?b߇?/XiZe45KSL,OLs٬ST;R FRCW#ShkM\-rh6=7AΜT{3T%WɣnOtsUYԪP bJNaI/ *,Tj,e#*뿸~;+frHbtWw.}ɂrAwe/iYi!Ju1d{0,I㹾&[!V_eTZw67n)Pe`z$/ޕuUmDA9,`Lj6>r80y͢H{SDS+QGƁyͪYo_kY}{):/ ?#}Rv-#m.#.dvCٵ|мXBq}&%b ")9u ي QJm_<&̥vǒic7i(qյXlYtV L)D\Y6bǢVˆ¥\4i$ɼl:]%hF:lB}̍^1' X]7F6 cʌ0˾lqhX:믮~xMV*e}(꠺5Ȅ[ E4" 43C(ҫ|tjӛ;G3)6 HΘSX,l|c8ppţS9Hc^GUI endstream endobj 3 0 obj 2436 endobj 5 0 obj <> stream x[I, )JVoc7`| c\;%Z 7Qe "̌]5@@߽/'/,Rcfe54}ʄDz 'Xa ^U65`k RdMd">V`H\FF 9Ό;.{0.]$s35j-^ȚggBc#d\T =H3A¹ J(0=G ?KBl{IDLv!D IUZFҹMd{AJdC<)a}-Qq¨J0*k4+fTjŘ3 Kw\G' BhWw71MzʈU;%S} n MQn%B*h:bbHv9ߜK/e9p٬'eC qO*nH{v$~bu/朲kL9;Nm[mk eV}XAwj-H*7]k+."`q;Գ|BȪчTyzSF,Y?SWY5)ޕ{#+xjsG";QwM".)6U&$6˂Vcb$C^VŊ Llۙ@DLm50ML04 e84c 1Sv*XϜgx3ο*18ߢx%o1>|/+C1@Ngmtj_뎯Y,(6~`8[b劮8Bu|o yb6ˬ{Xecc%\[\ `9!V|+s}I+sǯ6:˂bt{m&XWKjbgXŗˣ~0;P 2{)fUJU.C,vޗ[8DɯmcG֏n`i71Ŋ#1̲΋1si19(꜓7M$'Ǹp~M/=FR5(bA.X┻fD8%VPn>5=\x)o ݋BLu^wS|l_`w640YTtmeڗׂ=a>7̎Yc$h6YנRB]D~ {_?%lPn)gFwM>sB&4L| endstream endobj 6 0 obj 3098 endobj 8 0 obj <> stream xZK;ϧ90-mr[a-@~TRR۳2qzRg}ד:)-lN_כ6ٞB_I׿~n>QN\~hz=ѷS~GN{x්S9|kxvxӷ>Zbu(uoo `Yc^Q??vZu!%3\3X)>DJE}ZvhѮGǼ}:@ #"+1X3DȽjp ?,]+oz<kG`/숝;XL '-2C֊!k@4E$I܉v! wfeRnIִ's< \T `RS:c)tL-z1]OkR_;Wӌ!61ٸH]zHv~렒- i;?GaG!Pi 0#Ao3z޳.yO_j~{:Eat+?IV`ɓ.2\$@2{&=b@Ka'M訰bdkp{,#^JnIL yϱ5Ȁq$y .$.b[]cg'= (k!]߀ӛZv_ P:n[%%Wؕ~1糴J"rksb$=z~ rk@&PwLjZ9qV;0_90Sq| !3ecjuS%wA|% Iw43GMDD+%6C(î%|IW5{XvGI8j#B/bH\?0uhLKW>uW:%iVH7HKb|FcabwAk]/g'N01@ֆ5cpm3~7MWcT*.$w8nPqnFSʠ>)Y9OJJKauR<֕Jיڭ09[pJnBd5?a͊ݦ7=*R%`̎T\Td,ˆk,JpfDEܫp(Ҕ,T엙NrTPC=n̐6B&˒:^U7_ ~/}پ !6L;zdw Ѽ D?)2vS(9´iɅϜ7. TF(/]!B&ra&^6R衪ʃSBBj&kt|Me@V\\pEb1n+D 05$ZW͒@q#UVB* 6EmI %߽@k%ZH5>~CD&,hj$滼X:Ztfh;foEWY/7/=t0ԩ dH9-Ҫw/v Ud`Ol! vJDTOkmDu1_c$H՞ܴƭ(KeG,6ׁ/w/9߁sXZ1jMKaOl荕K o'TfZoHܨyP=Rn5.. n"}5mHEx0[.l12E0[N 꺣j:.J;uc%>[HlA8YB~feYV13qSxbKSxbӐf?7]țJ<xC7q.>|w۹@>CMY:qH)t174mCt a޷YMkۈ`;ygTOOUl/jjWVVʛ|Isn ś#̕8H\әkH@ rhhxN:B}OMIhF~ѥ+F(N =}96AɅipRamf@ 00G~ NLCR6g}r&gkbܳy.};]V6Y^I؀wGwS (0PJ}kIC/>ۇ $i% ˋ ehg]d~#<)0A#9;1Lh'Sϱ`3y0Oo2H.Mqu'MO 1B17&sx8N endstream endobj 9 0 obj 2927 endobj 11 0 obj <> stream x[Ik,GW\iV|3'o`"ȵZ5aTKeddd(=0Rz*q]ữw/1Q//?.__ry'8'q`'~|mHPq Ǘ_{/ y TT oujlu[)8$"H{@Ԇٲ2mٱ#e`,8ۜ2 bWQa'{f(ccȽ, !^ñdבd(w˚A gZ͘T67꒟ M{9nݬZՎy/<32vwtaJq*CAj^œbDsv,tg6OLqoҚΤ-M/{tNyHI,s8qwרbDqߕ0 j{T4Sp9bAh#J6ps8ՆcgA.G1dY}r`pOHEG[KW7ؑ؈QJ'Ye.gI;8" ;lczG,zk?'~uFY)>pw6L\ ߯*_M0v/Mj<-v)%W }oȨǍ׉.Ho{*smdtߐoωI;`F5iE%.!Ѫ3u=!-ifT[0xVM:CXs7sDɜ8-4e}ҔxK7Q tz-5'ck#H$OАWU*Z`rT{7SqɴjlvڅX'6,/UnYc Od5쥾 d,f$Ep`Zӌڅ7s\ ^&[16<0Vz|F;?,=, "l0}8o˿:"Hc ADVa eutgyLU' OMᦛr:gRbS$ U4]^&Y)R45,axՖ.*)'{>JE dI//Th3RQsM%Y,R+ɕ E](zmN(\(B>-PdH]Kho*ݜ^(*v2)UP{s׉29NBթr8aT{hX'[l7՛:偷\cdLBՄ-Ncݸ /ن)"yrU.Lq\R55K|2&zH[ӌӱot Β.5M" ̤2O4ؙ 'rTWEl6P"в{yۥio;?ֶqNWbzo\1i X72V̈́9&ϳSt*J|*#M*#D\ V-ڵb>ŶM?U e72qc"~GBb'}%\+]W10n c2eҷr ŸWf)" > 㢫o\4G ?K\:}Įrf^wO$p ܇g}\%潑㰉~S0(apSoAH8y[ĭ_Z8 Fp89^Q8]+ԋt(&-ឝ*f#+Lu}Eٮȷ-ww-pT0*i^at.1*lslP[?h d:OmqNP\6$7!ǔW_mto +uENZ\韩UG4:9ZcwtdnG%зp9+eɒ2n[xs*;MoaK]$kn(T7ZwrYiY+C wGrJkO{<.f> stream x[K+ϯ:0Jn5{l/0%< @&?*=h۹C,zjUTT/#:(|s;ꃷp?ox[??'>~Ԗ2ů'I>J*jаqQh~<אW(*y_<--IF^ƞ % {ZmՃa!c Rֵ. țlA7Y wqz BLQû]qymBQx&4ӭ]$94V!d+ Q#va}خ:i)Ҧm'f0hk};JҺ{;Q3O$GRe/n”?(v,ixOgN1ड़Ώr7!mŭX*fyg75+H{[gݠqwZ+L} mSϦ02x(X&d,KOͽ ܶln)$Ye~ +MF[sքq}!|^uYU(B9GW5%00c0>x; ~'cYňkHPG7YW鉓VJi;6,t3KTnmx`ڂ>E:4}=Osz RDFmĿ׎n9+g:EԊPG@HqD1D X芏̓.׷306 ɤg;ۈ= (ؘS(it,ǂ5 w:qԈX|hxk UjYJ:weM# ' FP1uavokpi^$2"/$Yt/LF$":OHҩl,ڄV-ܠQ,r Ɂ DBIhhHn"*tӅb L m0@>zrZڌ9*LOa hjvɍҊx#>D ؐA ٴ"2Xcن1KY Ul|^HՄz:Aϰ#>;@h!T) %4!Kub l/nU W7lYZ :&UN OɡE33&D]P,yx4gC =ˊ+;l&&ߤ lqDȅ02 yLzA+Rե @YqL|2z{L8eNb(yinrzTӜn=DҨFkn?{a%efgWm*(IT J'gm7N)E@:Dv+m'xHW#qvQiϸp)(ʢɀQZ99}]bܐqM"h㠬) 3SISe-~5 y^S3J^~ XtrxiOYEhLBԂj=hcu)Y9FaDn>QLͱ"yzYt쌘ƑG IzHSYp!.6w^?oe#Wc1=bԘr Yw&Tshĝŷc6=@Ԙ {u6\۽ш;T-vw{kwU{_i1Aۻ~ \i/#^ձOyԤ5A j>kDA tJ>UpȖcl0"MS \xSkr逇Qg&bEP )-E|CUF8e4e7NW rwvE˽| %ݦN0#@Qh1~eG^R{^ SQ[jʌnz 7{5Lo)%[EjѸ^^Zw2‹,9Ņ=!# M"I lͦe"c{Աq,R؏{|{xWR׭s*}r}^Y'WI(:MU4#t#V[{+Cm>~f4YYr𾾭ow5O@$>j?ݵى=8Ē]4tUP'%!/B"VhVm:WEB8_B..a jȞ6 lܶ4O"[3B暺v=ꔫ 3U`5q3o%b[O_f * endstream endobj 15 0 obj 2620 endobj 18 0 obj <> stream x|y|SǵMWdѕeƲ&c c0k$nl'`/&8Ii8iY&fiYf+I4K 4XΌd6*1s̜3s93giAzԋ8\Ѷ_!+VУSEHlUu[i7BrBoVݴl"ɆkZRB{kbmF 2׬ޘeXP +f΢PX״# %5kO;Cml;ڻМ 1C ,oB/ip JY&Śb;.'5 4@i|S5~QH>e'REOAWDgG_"CcndCK=؊2-Cs14At+~0~M3t z4,1D/3 @ ϸQ8ҠH؁л p' ?~F TϢ\t+K8&?@_oEP#Pя Ss]nAa72`w֓n4-GmhCO_`+ 'ߋDr@V.c>>=> Wa;_?!\?ѳXb @E0 tzL679h sKzr=mi{n9#ߢQ1T<w?=i&opry? ,Q7z ~p;?GI|A5M7ƾ/]EA?Bh?3t?#xAdAry[=ϗ3-I}+S,{ IBl;O5Eb`kA?D5h?@Qt V}8.5W|#ފGOa0"ARE&Bn&[md?|Ȼ9;9?䊸e\̡4{ )wVO{k'Ku}TxN~-ΊDibxG$J:i?sAr݂'ߌO@E: fuX^?i;f'n>r*n|⟣"`'GQ@F%܈\ C{a7ECxO*rx}# _^|O2M|3?Jx,$ |3?q9}!oVi~ /`w`7j]V[6?aY+E*עkp,j줟Z򿏗5h6x`%GLKWka/)Cftzw#77/8G Gz;{xS ֌F؅p1 a_Xھ=;f-`%5}56nB %a=|6ətA/7>q+1Lf@?+qX 4î6)S{`>@mǙ\y/TW;FT;k5+w&68C( ħV1q+]׃&ㅨ4dx s|ɤķrbk/ѓ&*TZT~IŴSJC%EsY ❐q-j1N+k$Q9Q,M 4FΜ|Z7AEj.(LRUC&(sجTnekMʬH5kf5VCw:Lm~q;s:fqΚ:@BEo!::ZhMUJD黪A7:EYJz/R7U PMnUq_ܒ7`$;`4%B\9j,AD HR9MYԷr '+ +g6z~/,⋋k5b/NΙ`0KMD k 2NgkdYCuۦPGxǐV@!һ>QVЊ(R i-#-ew{,y?(#&#e֚'-%E+]zQ)>\[̬RI#k1-#|Q7G80JVqN"k}3$i.`\ gKJ]1V|bX|Bgɂ CqVFΪ){:U\ ur+% $ N ido0U(A(9Ahu]0_fiWh]T?@)@fTh nJ}v[p7ӡ۹O!Zb^]#y4iB3/uNܬߚ?ȓ5VW~g8ϫzQ4ۑ-N.gY jpR(Sȁ̝j== jM -iJj H37h}f"(TզPLs a~x8z= C8q{!ƸdJ'ȉ:t;9*OZat0Q:ND0Ŏ8|"QFgSCK33IC0k9g4'd}jX'O.)v8٢&O. F!bQDQR UKqK<jԬ:qÏ,?v)3/Ub֑MzgcCriZ[SSvmiYJڢYboZ]Ӗ2[@[5adQteSu\ܱNJKii)ZCmʬԻeA "DF"E3!ӧtL 0 ቪw^ϝ^'*rOԄ7nJʱ՚&4QC\ TeSlNʶbbTkhn^ݲE88v'c'c_~>c'ZP'^!7—B?T0U"`FQk}!++|ɭ2ԝL;[8w9Ά\+_~py|0hlx-hNc8 }UfJ`avh ߰sv mdbh8N +{0] 111 JcP5;S b_iª:nNB>\`-4b`•'O04ҸӓQ8, 8TKͱU &]E1h72V* YNatܔ c@`-BGDetVU?N= oTAKF:oTAYuZP V`K :׃aRQI1|jk)5ItbxK+u[1ieWTT`GChcĎ\c^{3 B[0^uΧW)_WȧL)a׽>>ͽ![''__/j^ =BPsu\4vT=u˒p8po[ͫ.Sg )!+82Y󮶸o?P/~+}w[=$V,^Oo=Cr!x2syŬX|KϹa!6bL1!1#3_눎NH+bɁ Gеb%: 1XU1%@lW~Lj88LZQFa 8@Ǒ a}JʋMI)%t.)vJTv{w=T~Ʈ闔f쓇@ݖdd._Tgt`+aE5Xcj:smrKտl~4|f?#LIbgqziQ6L[-='|75D3V[Xb5 !M aVR@JvyxCMS´P"J>EC]:xDUj8'ة` n`NBiLu d>b4\zVٱ-xbĎ/|L(^􎧎3 "5td4z\qT%38tqэ͑wI҅]Z]@o)j0,z|b3|L? Y+ܢS|hZ&;}|nw0 vB/t˔1/xh57!< V:QA k'&mG.aGNk ;Ć],i%kcՄΈk01 L7ndmjmBJ8丸Ӻ^imgm]66Vha7GG%ipF >&bO)='X\ aϵ$Y椑<iIi\;N˞ZK-7܀=|`4`Z%fݍ}DZB"3XB.yA-_8Yݛ}w,jlz0l|t8Ѱb[waTW33[[m[2nʔue9 xf G'd73Qv{XYMjQqᮌ2}z{<8ЈdЙ_G6+gd(T=B:7^|sLq%|+Е`?)Y#H.E:DaЖObm庲,}n˯Ή}ePI |o /I+P6K}G^=mռ-?x3=p= 1r\wtW韒0ZQ#jvXc4fb3L6ddlSq-n}M6y{K(;l2K=ƛwdAo}դ 7mfC/ ю4Vl Sň8"yqk+B? VP!E+;݄O78pb|7`36򭓂 /aK9rrnМ^lp8S|$[,p`';CN 7^w`v.߾sU9?.ō&mʖʽaC܂. t' v%|άTw,-, Ra%Od9n☀ݎM`'W"''9wdiI \|d]x^?QaWʮ4LPn#W?u)v{WV|{H52maq<4=Іa$8%ɤW#QKYʍf*Ns&Utg\DAx-Wnݫ*Yh f:[V H7-8`~3--ٳ@]!}k: E[ E<R©x&]n Y'.Kզ33)iǴZC6:~̩"ޠ=ߠueKmȠN{2JP%S#+{MHtvs'` `,EZT鳺 +)'"SkIb±{r+.ZM֬W[ DzEp RUY d$~ n p&=gy[YVw[s?C;cٛW߾mMM5S|"w|`bv#ɇcӵ/kJ>إ[bX&W'/ T.jqyjlc,t$##:' LUl2!NsM>HXsӏتm&W~| :+7U=&BFT_۴[]R?)L `'ch?4gg;;3@AGzjkQ+-UMrb-ײduBd urp2ON5ИV;03 -j'nMh q/k*E;xaų{;.44ߍ[7$;;ru7-ț#oG>?LcۦEIӖoiNj 塬UZ[ {uҔ9) )jnanJuש2}*8gS5_СәM'F)`633d>wO1ܹ1+8ܬ蓉c@Z=kK~z0&;‰}Պ\ ZuͱNޫY67<' oP*zT]vp>}F^%$] Vie} ]]xum}skG/Y56czl#dw9iag1k-"Jaޘޑޛޟ.*'I9aC Lk,Y nORBeqqBSYϩ <'j|Kؑpz\􇁁쳣:cx'^u,= \ISu^xI%Z. DdV!$rdΣ 3򅡚hP=T,4Vc.(A^. {+E}t7_y32:p%3C_AFt>uG*OAH%ehfIAi2*y}3IR6Oh_5jam3N_G:}@{VkxI^s%|[;U@{ Y5i^'7N GU¼Va@d Aˁ8)!.@d! t擠rf] 6EAe b]T,:MBn( GIV[O&ҵQ%廙ɹh;0T!*L ^I$638;3ZE F"vWמ;1J0 8=x^>=ıppfL5{KaVFTn )V""iӼJG 3WNzxpZ"8 SkߊWv=jνxJkq Ø^=٩I~u$[9H6˅r˞VruuQVzFR9*npO<~FKj#.OǞ,{)Zp?}4wf_2mqҿLz*'h+C ϵ_>?aQ!24XCدS 03QC9CNӚQ=@~ ,ʠc~E] < clyYl%~>06 d2,[si-FR*$v/) *dP: (r)U[%Ѭ~ʙ托hd́&yIp HCI AhUOt-BIiljLEZ`уiRu^^o"q+ D R!I 9| ' ,%#A'^ASAQތ̘i1@8mTSܐY]=:@aʉ C\; FY3nuɟϒdX>0t3`o[_1Djb$ђ-)zҊ[f#K~Tk GCiu .?f &iemٔ|KE&ThRMMX%M  }Hz'-`|XBn?KC| NhͩN78'(ǟ `eWbQm!@kI@MlU>ʼnxOZ]άd`{Qe$X\gWŶsmv: 8L>{%{nC+>~䟮4UEְ7[}X@Ey_=ezlyey96]*(Bsn%N)2 x ʷ1ߣ4 <;rnk\: u2 3nۈH*=O ^MqWmz~ EFL fJ{3fT<+ H`KQOe8ƥAICII\@.i #ؕ5eGH7ȭt]*LN I ^H8B^x*Hj^HI\F xOL>y2JN:YmGg{sn: k@ FڶrmO3,2.D{MJNDe ::#ol颳9?@Bɾ(-.;[a mkۛ/VBSb֥[inhִXC`nwJ [Q69vU̕/lK0Zu6_Tǿ8wD˥iME:i"8Žs?wyCxu9.IakYsq-uu 6]Dmj객iL~2?WKZBom_ښOp\vyAho(c {\ݥl[ _j?X[eF d\C*d(VZm F SKX}]ŽJT{hAi XP`Thl*@"ȔB i7 ^8$=BAG* c HqHH1e~4(?b\܏R/}ހ$vwCC{E{{$jfH{0}ots)X2sw:HEhn;h~SaXl d 9fe15Y2hvׁ6"̵pmȏ'\ 0 \ Uy%gmUq8\5A'jL-\P^2ouTmQw '!Pk:iael&KeC*=1hu,,. 9j.p|{<=<Hd\?5}`,n k00UT7}`}j}R}R} TXCv)E nY٣adsn1Ub F*+jMadAv}\U~eStR(ΙX`t%9¥"bҹ Q7R25d/(UyC/; 2 _OH9p &Uic*CE}2D aT ,x0{;DF :Yb4XDYIęD,yA y22>ptW>CJ!I9LMz1F^ zLUBR;ݐAzİ7 })NJ $-vK$a4*P-}HTb`(l-h'7C%$8D dX% !gK"!rB2r\\%٘g;U}`@tؙn? L 0Q ! R1|HY.Ռd!eCARjѨĀz9w(]`(*@4*/=?ICD! I.f2eS֥IMw9-z'z[J eAD\Jre&FGdDZc3Hr ЗøǪ{{ `#(=eF^jUh0 > xNޞ?@lFeUSBowqowɻېQTLdot8fb"x7yUo\9L$-?L5~s/+5W:).fH$!M%ƪ1kFhD !T H0===]4 v!T]RL_p$: u8 4AMX?QpH/zU|3$Ǒ v}&3{4Ja+ӕ+Y Zٕ+WYV~}P}т9Wa"hZ:"`8^aD`5IP9v%{bw/H+ Dbq$kaLNs? endstream endobj 19 0 obj 14275 endobj 20 0 obj <> endobj 21 0 obj <> stream x]Ko0 Cƭ4}fBCժ8X)2'Gy$&?B7P SGnz|?#n'= #N7Ʀq(϶ endstream endobj 22 0 obj <> endobj 23 0 obj <> stream xVoU\v K[ g:\vv7AH Z۴[h:Mtm!K@$X#A $}s$@}FcF#o Q[=~统o;; 8 "D);'9*(G+r;ө[MNQiug xP /*(GQnIj'Qfwg)Xeq=A44ms^AV6sD*k\2w!%?=\D_V&%8oe腏m!0DB/FX dAmm2YQy.ȝ-Fj !Ft3 9RCL6P2UBLҹ'ہ@=s9p h*&9j7, z&r3ccFE**k|tG$V$LاQ&32cS pQxեu} F3)zCԤ%\GԡN9ъ4EQ&6UHT5@la6#nnjQZ\f|82bԧ9u%~ 1/? ~CVMku,yRsF̮5W J_B+W1jfx#Z ;5E|M %xc4&Fgb_p T'Iy_nyEE۞ȿt-Bȋ9xZ$𩾍OJ3yweFn|¸x`=>؊^UG x$miSӝ:ٟ2N f Mg@n)VaFX-:^aco^"AV_H0/jRU\ A뫫G mM-ZY@Z,GX 1a?\v=A>3 R1?oN+X/Y^*z13iIKL,KbF8!\XN{G059eaCYq~|mlãD@;et#*$ A{M/1|jK8{JhUXq<.oub{PHPZqA EϺXBe=6'ֶV:l2=|<55GfC!M̤i{3mRڡt+Aȁ,$gqM0L@Łi8F'i<E& xalT: {zsgeCf7|̋?~i)c?N endstream endobj 24 0 obj 1334 endobj 25 0 obj <> endobj 26 0 obj <> stream x]Pn {L6Q{|Cu.R  I[Ќvf4ԝ;g^`D\5€u`NwV~=8ymI8wnM;͖7صg5M<5+TLJ08Rγ /jF^\ئ@?D4F&dMUIh.Й1KER֤1cm[2꜖i zju{Cv rG endstream endobj 27 0 obj <> endobj 28 0 obj <> stream xݽ xTE?\U{ҝtB:iB $$1J@,ԘHX@Q1ApťF ƨ:̈2#$d=u筷NZz: -Zk,% NS_!>m~wZe~?!Ĵpzӌ9i319cU|ÄOh )tc:4ӷp]usZαނ\?:qZMs6>kB\{z'\o&JSc3Iuy 4" ?67Pk&ɊF8j; .wb'9W7-;OfV~/eID /{XKWgGx /IH{?_[*2$u.l'U$m?#,г,7;39AvGP`B&wB[@6'fЙnHгp:r M;;Fv YF5H*^KaMdZjɝ <k(InT{*+5 +%ӻGcZ@o#װ.z%GHluSDFtn@nʛIF ׃$i;:W1vwN? wI I.Grxo; r߇Dʥ%lw N|ax@I BC f{*iCO "MI3'Bmh^/Dl2FrϢ}+yTHy׍xTpjr=5I#Hd1Ym;5$WG[SSЪ;>SENʤSdeG2pc44X½`5]D~ OzкoAbФ.P.b{M{4Mx}\iJ+JSGa9{Kaa =FlPvȞ~.a/A:H& uB J"b5d/,n8TdDI4f1.pm7m)ϐr2/  Χox=C6`|b<9{!Әo;8R:,a~ZyqU[X}aBhDV=#-XXњՕ/I n'Qh!Tj]~F(揽'hdτ_e*_u;@xzԮ/=ZI][u0i;ȟ !K|NXcod@jfo@UA:@m?8z[B|VJe AynAL`gW@sB)DMW7J Z1䷡Qq0QzCصP;3ԽmXw: {i(=M&'Λ_hcZPUTM/<ŬGݞZz;ruΥS}^ocW7VyS[ eJZUGB\F魫yaBOmJw[51(;Tj7 W~r aӄ1{HS2J'"j+&IK泦#H"صLI0U;Owv^僘c'7SW|vo [^ٚС㯅!]*iGIajy$^3ṊB.y Y!hjgz5e'qZC(Dx;?N]rf@o*U ;p& #s58~&l}gOLxMq.c'vƗ_v 2*CO-Z TD2Y?:?w4蠜4[-Eߖ*$d)Op%b{neX-/dCӆa}hǓU_>e()PpfCN23$'%w2H|)ܴ@C eꢔC %f"c{nW%ldY v#ήsRvnvpfS9+Iᦶ`Rz2&N;l=^yM Æ B( k_z/Fsk❽(^iqӍ o_}D?ݦ;㩣={xmrBb!sf얳Byh\G'Aޜ5LOZ36f(r0ѓo-ZP#!6M갷[_'E=A97Dp.* ._jY~0O%gl/@c?ˠ33$9ƯlF  [)Ԍ֔k֞HQ%,3m+93YNbs/i)KILr3lB%׾ټa~,fJf%a=ڷ]qP OIz[jBE \Zwx^6v|z/*?fdWVTV yCܴkK ? =mE4/MiFw&iOisqͅAjYJ9g"}m/kjwX}DK%_m7|MtMqv+ڱ 8"7'OjJ[28!R8NI:.: Nf`qŨۭ& 16gh3I&Rq`*sd7b5 4kZ#6ol+[[>9Pnvv;&O.Z塞+[%, N^`L{LGL&#+eY[cQfhﵵI%GVRa:]L3’ڈ-ι\LgsQ _̤ -L}l`v 6̅W }Ngy׭;-ܴTÞƓo> AvIdStH$eƲEa8DzײC0`ʤ]Z%&oBQ(۬{P/:/Y!&*R.EgЭHMq\-Q63T&= ML1^0c Xא"[uFڃV.͝V&k\qҬzS~qizc~. ǥ̤q6CӖ sJ)9X<  ˩ aI~}/f4|2"˞sRξ.ۉԮqQٌKTpvхJT'YKD=sy Rx\bॣ&X=il{mU("_:FqcrW(t%!hd!pH!ǹx0觠+Z/lHw-Z"Ғ(8I"|+&i`s)-8~uS7x=«o匍VT ˾?'/SŜaf658*S'Ӻ|G 1)N*ԁsD> lo=uJ{7ħ y6g,ձI_ܫ\Va=.{]Oxr[֏XjؐKyaC{7c(BKjX}/12iDIN8 e3JL#P '[[,XdGGCCn"ThFv'Tqs6Ȯcn'-' X*cJ<ڬ̇ȵlN;̑~WQ/_X|ۇߨ<{meŴ}p>>YK%TpD J jBYf|AxeYܛ{ ^N'M&&%#^LII^3R2$IQ.2L60HR4Z)Ő,[btC YxPxa g;HlKm>GWhrݬM~]stˢk}IsOӏKWq፜>x@%Tjn t8"Ea+a14&d2M`c,G4 &e㈃;:r:F; #G1rSiIbnϼFdjY}D&QS 3 ܊;a܆rCaA12ՠ$ebb2[LY'ht$Ph'O 'BE"8/R}@>hf _>q?1'%t¥>)Cj\Cy:ٿy[OGk4?Twu9TZ_JycG>W.LYߏ(DREJiNvL:\drQrb.Z`8*ϨEs&B6 '$WRfCI{${IuTD^=x!Wv?p<-WvE$2*z.}C>|ϯ&[nY;nmt8[̿= }鞛\ ^ϪMdJ0OR-( l uc, 2i2Ng\#g"z|@n}}.3x+ZW, /30:h y418vsR0=C*OLONrK,sPPc;:z[B~m-Iլ/=Ӈ6FEЋ~:LչtmQnDm29d њ:: L:fkW̅f5PQHi}Itڥ(o5{45ڛvx*Isp}}z.Y>$푎H_Ir"‡iChrgZ\k>œٯךm#K2:T"jBaC$҂܋ؐ%_v[ۡ']ysthզ3W.w|Hhix[ya_AÌO֖scOna>Ea{JOP&SfbY9Q˻VQkT# 9%41ʒŨ#J ZGkWj XyIKWhV+$zDzOb+׾򄧟;BEH Zc82Q i>)Mn'ӧAY({sJrvz0:\wno^%S^'^?cYq4.κ^/k+13qrM ILLX/9V&HH|?Qv9&;8CRC p~_@$o q7k^3܏϶cy}\sE5O/ֿi[/D1sdh}9x6G tV$3!#fO%+3XMl&gD[\N6qkuBd])_$Nz_b)T&$$ri3?I(%( iSJ,H%Q6'³# ǭ21ё?;g=_ !ܟyD{Jt=ǁ蚊tp~E4 Lhdé!_ m{mT:?_y`ugZ:5oǿ|я_r50[&,H&Z*c AIg4Oq|nGi0$CO6?;\u6=So-8ht/W_|J;:TZ~"o<幮v/u¿DJF`ݭ=V[zyg.7U[/GR2NU#eauiwj5Ѹ~J $+hj47k]=ut43D 2q[6ϚOZD=Eѓ*CEyד4UnuA3[꯭TT{56-W?śU;(-1;eQSq^SƆٳbHw^ms5hW_={[mW]S;z,otĺ]PW?;zwj-&QR;d7xk:~ W̶x)!VmtŸU/FM-k뙤Uڌ>|3Ih|Q ~73ggqsw6wzAȳǝ=?TsxZ#5/0*B0L6OܩkO@*,3& ߥ?[nաR<6Bм@P1חaŊ7H"1QH˶w?GobR>wL1N=|μs+zwi+^m}U.:Wzbj|.vʵ2_6ӑ9lXel1nv}qʺZ*jv翋H.&#%._V.(/hvsh(fpF]r uשܟ'b@̺[_Bj|VӹEп{MΣ=,u'fsD%ܖfZޠ^-V)ju?_6ۥ5[ 4[ j1;zy'ԋvmfMܛs^~51KoqTOU%Ӡ| yŮT;׊߯|6ڊr*pbU-Vl!3lι[Y}g̣'2 x'vˣU4v{Hzml--8us]zx| g i~]~LFm*8O3c?uitXE{k71 `97뚹YNԐXԟ~O5_&Wqƺc:9og"ټ? 4,lb4{I"SB2 [,@+u,O'(㝅־U|m$ Avϡk֑>KOVV {j^Z=_h];l{g+'^94U9\~PN-G#A{>$;(_\ܸxbi%'_bNٍ(f5$x.klhlA&Z:+4K~}հd^e6?GixN\IH R2D!ag|^K1zuNϒu}\'ZZ[67)9ڒĴEMz$ФEl@~@M2HJ3 `Ĉ8M 5d? x} $,&n4BMbOd x4c=,Ӎ 5n+,'5U(wWd`N\o ۝?:!:;811_Q*EKJLƢ-&7B#`W6lO 5L蕿Aow*M'/C" \_Ԣt] r,Xx@N8AQ>;shyXN9YdO"^MF.SJ*Lr*V>$TEUS|;;m#m( (S!U&ؠl!Ône' eK$>jl*%s*SśUܮ1`C8)"6'aS 8l)G;Fr`?ڊvlXlPT¿}3/ǕuEu@@`o:_c}kEsm7')Or-祲UKwrrgT!e0vrr?<br#$J`JrqWإԓ ,bB(32Pz;@"L,تŴdJ$7>% >V˔11V6W*`r2f2pI3̊8  UjK11k5>húŁBAi$fIK,WN y^vPj lB6HS j?oET0GPIdHa2J )hI(#1$5<Pȫ(E?%6XUW/)`+TeyrRs(WA"h sbʅ0 F.{"/Ezy?M ~Fɂ*(2Xܰ7zZcF$pDF )i$)9xdh< ArS)>R`e RR/p@\)!"/G/dX7'*h|X}W~E zCQOc5 X{Y~4^wȻ\6\S9"&fbAf  aVY ^ I('X!ވ2RVL|#@Dut2lN]R$M<x:@>wS?o79pnFfг(o!| MEnibj6גe`)`` c3N#urz_8UkN.lhjѲ -0Uj̱F6SR/"qkĕnC6\XЀ+#{[dZ 20p ;½SY'u#il(ї _/O M)סu&Em X&x{S؝a7f1l97R)ǰXs>$>|P[wZ!Bx1p/kUH ^#| @Ar#J#J`M}\`Vq<,02VqI nDG3d~<0hu0"ς.BFu(UtvJV*yL4 <0f+ʝ[F,I JH DWSUj,UTbR 嫱a WrdXW+WJGS"zS`3,47<:$g{Ap*p*88 8/p`p&0XV 0r:Ԡ d-| #0_b CV6`/K9XXo aҿ_"b~JRQ3`CC8x~~$үOOZGa(/T[;pER'HH Q*jwJG1cKIS##==_W>9T_ 7vxDp,<$*陨|(XIN/@I/Hs*0|8h1,TJ7D BJOH!'e%}ҊRV .xtWZGGtdEH(i vҪO'JN:-S9N;%fv'`;`7@f#%v6'?fp=M -]q=0tA[tߏ.g\eG) naM#: ʃ`4(BV~V.pox D9X@ `) P6v p' 4lנlH$(ըQeY,;"Lc) ܀DH H$eeUUMM#=uJ?짟18rԵf(!k^ P}߷3?XKU6 ln޴].gQi`+; c'It0 R@ŅT!*,cK8IJRDO"fpH6&ݪbnlp '-ODž<׏? Q*vF6)cm rA@@VD6~Rd7aFHБ^&vƿ¹WN#52.G\'vVwp/U%*+;X-c2eo`x9:nhx7|/6[2hB @&^S"tV<K̰'D:q3ujN-oS=jٽ\q1@+7H/hdxsUԟfo Tl.8,wq2ˀQe2#>]D/Ⱇ?6Fp@4~1b+}G'z@AhTw(ҧ:%8]% )͖x0gp`bU/ߏ~DDB^|jCaHnA`ԑ B=ٙzO{mn ՞8BRjwqm@ G e*@9<x PVKk fqGfsQùECL䎀6DVbK%_0bn T;S&O~*, \~ ~H}p%/ޔɉ>LK?ߒ3YzKqH(*&:GC`)` P*b$=2ALb6gS+dezeޟ{L-^:Hǀh~9㉵o_lj3&i:$+&AScoM#~"]c#&20 HICSڤx+.;h>8<c;$PlHWvU.Jo[/Wv0 {ɕWwD~̓ ت[bdx &s<]a%w1:o2eJ`lY99şҔ)\^Y2jnE /ϼ߅kWVPPҪ=;ӳǞy 57ڱZZZ[q*Zqof[0JœK"7EHԀO^4ʼn$)g 563JȐ>L7["}zb} wD[:qIWJF3 8CmTUq[Ak0v,0qXn}dyZ츤iQVvGO`Q<*V+U aCx`v VTm݄].^x{sw=V9vnS0mqEO,FZZ/U^s9ӽ4Fk1.+M3.Dpy?z#bOhpb$SGB"=gbwgأjWI3NfH.]O qI?cة08O'B(2Bƙ*ĺ6+|ۣ؜1-gDXpife͂]hvZKxI5pᇺIO9=E٤施niWi]Xi}:pr:o$ilFgq:kb,y EQGAToJ%ob 'οWC/8tf5_4йEe] n=j|햽I_K:0B7.tĄI'TmnQWVqfA*{ ?)EYat16 -]-BBP([8/hײcNj8J%\/jƇh/ߥwi]`#IIvuJI4d f 'Æ":?Э14hO!б endstream endobj 29 0 obj 18360 endobj 30 0 obj <> endobj 31 0 obj <> stream x]n0E /JT@#'2aw&m.@<w͞Gs\_}EL5㴒\Qr;eofjEowdf}XgvI2-CzxK x)ﷁ ڪJӷ|}N-2ص2Ҕñ}!4IhS&'L\c,P~)x</r ~η֗܍r~}ԱpQ'5XK[/˪?٪^v;X/ת*u?UL.1?h'7!'x;gȥqGROOEɾgh&#=\c'.I~@|h9Y endstream endobj 32 0 obj <> endobj 33 0 obj <> stream x| xT9ٷ;;̒:d\¾$H ! [K[2, VmfkjZk+3 j;7ϙ }H!=kͯ)oFl^{4I|݊߿z/BYfV玕i!~te_wo6{ 0Ft%T$I**rʵ#W?v(/^3=SG\u tஙCu Ehm}Pߺ @1)S4#K2BRkX.Ko0>/;_E6Ro M ZK//~! թoLVa; z2 |-FAG;1O2hS!4b f.]@qw  JX)<܆LQ5,fJmt7} axf36m'%ɮ=@TAjjj1jѵ˯0_׀B[a1B WZ/YU0>o)%(UERS.j#u/<_ޣh?sO s/Ew?&K%ˤIz ɻH夦SJ]nS2A䰰';ha48ߊ% \/t7P %OџЇCXu ~x9.vNWuxo7~w~y'I|85>Rb)=rBx&BLI=DM=:&.ҕt#& *Sw?3>x3gEYVFCDW'oK$G2KUIJGc#}3u3NP">+R[l UՔ} 9T7~z=j-hQ_Zi Q1@wREt.䥖QWZs9o3ަCS3*G dcj.u $G?mLjeO&wR3hsƇ@g"=W;h#k?G#Tz2RP8;Xۣ8W"Dx) 0l@sRj㷨J]QΠ#e(ݎ Kz8[ZD $76Dp_EGaq> 6O>9Ku 1}-3 S/B7S.饎tQ0#h%-9Ղ?%7'\0UGB7{rztD%AK:Q+Xڞ.ضHRF5`X{ X߂:Wqj]EfEO-%zI@f+F Ǩe#Ojk*+JK"EyP07ysuq̡ qӖsKE\W߾Vϑ];헷Ic@_Ե \ !'[IoHjVqqγrת.uWZcqc6OGw횳,W455@l @s&ɉɊ<- q{`#$+Gz >z{ qY}.Y?.nGʚL~HcR}B`ȅ kʥy : ȇfCM;ePoݞ.shm8EZNO擖m-ݻ< GS!.MiXcV86t{\OE\㮮 m[]QJOexV};m2eVœȤЮ3^ ܛHA5ٮt!w`DK.u,3^\uE)wѰ`G[k&0;v5y]]m<u>IܵkݶxmBuJI&1mB+#TFBtc: neKQ 1PCH$As }ȍ+F]@9W^hYI//7.\Mo2$UFdi 2f1 KY)iel5\8dv$fIR)ҔV5%(7sB\X1[ͦs(Ğ?w{\fu w^bR>DM 6 ;Ukuxg,CCT@;PȡC =:>s)+2Y?Ua500+ueH18Zؓy%jZɊ@̋{|IYM X\aGtYΧ]oiyMyw]pJ|mifS.519߮#4PR8G1g*%ST""n|wt. GC?SAqNc+, 92;䬙1g&+p*.tLEET֐e^IXp(iB>HwU317Ѧ֢⭑I8ěTHK^z$t,{L]O݌gYƤUTXS HE jr73T;778+J+8E0.xeʩʦŋ#+wI ?*}"|T}6bz3 "CjUsq. #[yvh~HO!oD,Fc%%H ʁ|p!V}y E䏆,S([P VJˊcU?zf(XV=:+rUu^~)ƾ,q9?L N%c0B.Iyn&伜P)t5/MQ SYuXF4l5XS3j䞕iQI A6~.NĂ ”$uZM0s,2b6 AS]tȘ2f>-$TLp2[sS7յ_O89nI\qީe,\zKtˆ;qss_ٴr7|n:NZ Vy#JBH}̗ZڔebMw+P77 >Smi9=2,i즱=FlL<_}F z7am70ƌqq1&o(J=7fgٱdϝ K ܈>#idL>uTRKT/NŲ>1M[sk *x jJ8 hq`W/v_j̸m‚5{ 7H_4ux@wJ"3jdTFu9U_V@cWJ;3A+Y1,cX=aTC)i%zV) |(M8+$" "'rIx_f)4vv/nu8C Jk^7mU-Dv) UNSn}:QgQ(|&d+2 NTD1j)e4ɢ{S_ܵ'3/ms}-7z䉯o֗bɢOp֒ c7'BWeG)| GΘ 44GV _(Pu~ٮ@)A~aK9v{:śmE&l/q1]cB-sUJ!)ͣݥzZ *p3Conլ@tmE컠𐘪~DVd)PgnA;sN9e-c\V؃g0{#߶ I(;osKk 4:hud͔%7NG&"'%yjMte½,^DiA"=1akTҸ)kA,&]Y:e))jHKrXX^jvA<Ę*XXLI=G*el3Ҁe>84 eKNOvPvJ&R 䠛*U*O͇.i^_ŷE8ǑxLa :=/4[7"Iǡ`97ĩ"3ZZ׿n_óe[\'5=zEC]w'jeΫz7-KZYXW[:t9C|M+]O,o­z\Tu H/m ZĠa]pRčfȬppWX$VҊZE՞-w*vEܧ}OޞȞ,;G%g,sKTex$?/.B$ir<~X]DF {8 R,(GJBK¡2%Wkm g4qp1$Ӂ+9uCYO9`-AD=檛#-jRƿF8\*rb7ܬ[&Z}7Mm㣳 ʳdLm7~i__?gV5,,:P*-`WWr- ,(T.xYDMcŔ:#*ٔ㧨8) Q>K"oP*c2e(qvniȠθ*H5Dr^C`gۯ4>9GIX]D Ĉ!GoƏO-Ĭ9OE`_2KL1D IƼlaKn>nytނ`e|mP{wg\X=7M .jo۽qø{jZ ;AU^:;W^2lb4o帒{Km#s帊2ۦƲvۼy=HIwARiJu@jn3'xy<2 p <#tMo#$Zm{P94-M)0G""`>mVi!Gp[b֙VjuuZ*&k|Km-JP|nD_<׹^p@m. ib !'/mUg0MQ e',3a#ʼa?1V]4)KR.nwko]] +C8cU.Ccnέp.DUP]ڵ~VURS챔 7~Z#Pem~HgEV򓾓T* Q6pfCkNb^V߭wWS}~i2H FU, hPcpvueħ1X@pWcWJC%)lF|eB̠`0[˻>{+cέBT)x:%C5D ?&179?^p +sp1Dl©JCش#tkLtxWSd*%蝸sYq¢07 JϏ8],GuN<_⒚-09]3 #5&gu~aKy7|[Յ:֬poS2!cm-ƷcB1?#HҠ<̄l!GYPXPT XaH7 u; ;);}GGO{BMUss XOB˳HQiql J"F 3%Pe~ޏ_[,,|'܅PnX& )L+ NJ"P)1^! `vte+¹sJq\ԔQEP+r-E^&Ϗ˞?YA B1t^ĹtoM\D(IZ 2%ZJg:\ '27y$Y+}hroMw6+oD5B)(KbHCv@o O7=%2<W.FMߢЛnk)jw˒3C$v/K7B{n{{\y zZY5LNZ,b=fXScUKˉy'vV&um­nIDN8`bU+2F[Y򽍉1bu4~|r(ߡUhj7~LTj%gE)9G/ r$GDӎWSTԫ2 MNAN9Ǩg9fKeQPR mjnK,ӑ|?oU/ K|er W(%F{1LHt^o>4ݒbr=X4`Q3x=b(uWގea]`vOΤ+vt!qjbvUr^ܜZ'N͠g=]xδ4CnH90-K_J E9=pD`gE5gY]۴x7n+o`sZt.>!/t }5Sݸ*Ͽj]z;^;xʂks,-J J>I4ř:G@ =1-0RȌUzJmVcfuBK@Y7AC*y%j&oQ-Um?aUb*㡕ZC=azblG&GiN%9F+< u:f*!7ܺY.MJϬYz7N/!$G Hp^}:G\tyuH-! n!LzNeYM.eW#Uhv^]/>Xdad2^'jE^TH&ڇM@*WJ*&VZ-MzT&s z8%AuHjxQF zJ}Ku 3x>E}}Lc-T _fuY6 :}(ȎSaJ&UCex sh|`L6&#ssJL¥܌ڧ p ISzqIG=60+41i0_fi!xp3S"rG'ڥK+q?YMO~a\9,@Q^ovhWb`7j?ZoBr|x<[ GSY$d#Z83R3\{i0è ^+Rr K;R)ve?lNABy=J(W@~Nтm*,0bN|H/mȮv%^Q5` DŽu{¯S |(DZЪ̯;+h4ڂ b8.#_@+y,'{׼aRPN j`XIŽf` IV^ 0 EAuk8Ql}i_`=u ̠jO d=e֣.F~20_[ȼY f5 3kWuf=,Ӭd`iևzޗTN ԧ  pٯA % a9,˰'oX7CQR9þeBxV> wmF넚z( Ln0e Z@ ?R}^kZ̀|5u0R@kC-0B7Q9p1N%Z e8nŠ !Pf!8C2 rf4ZzK#BsQhW}箢_hwDK/!^uQCJ}n +ɬ|^)P J/`+GyPIX (τ.FZ&W:^YQP@ɬ~@7BAj v t%l:M4 # u T2MAs}.kY'a/#&aH?}t~7p!AKziόГ+{?|PfAgAG8AږMi8.;!AR3))Kr|庪.Iz/#|2HOj6 ;4wtThmzn8s `S=sVqm#qCG)kpsW m͟׿oѷ3{npM/2ҽgbʿC.é\74 cs\ghpxpH?sy YsZfy?D0͍ uZ .̝rtHC q=F?kɺy$i?|yOGXӷ=#0޾"R1[۽0/an]e6Ο>Zº =#dV/=k6BבAx`||p`f.П]Fz]k`S$= zQ.^qf*a~eo-P?;i``¢K&LrcpȺ #\oFB\YٷfHw+}%[7B~~>!71(}x"D1'b.bX{:+!=Ɔ`f"cL=|]8};gl,0P3gm8'^z?{B q?W@BLF,#R43{Dv&"0Kr͌g|Zތez&ʔ3y(_GHèW }z *5ڄgF2@< 1EN?އҳ?H>Hcm E>Ap)f`.xK# PҳTi ޙ c4gʫ6Hvqv:rF\7ƥwJ\ .9y.3:C>sߙgNaΜ96jw}ml{ik+^D]O]OSLAOh> RzfQSnxf _]@4s'a4(KtƄ@H]BҔORzL3%ztoK-^Z>Eho ޥ2 @5=&?a IbJ)Zj;~Ő  RIћTI&Ur,4I47Qݙ1G5*GՔ!Z$҇jT}TɩSS#jSΩs8U'(=*LI*L(S%(MNP8ͨ6+AU +m NRŨRȨ0ra/C/<(ԫq(^+;Q!s0m422;ϕmsBvj+=;vuHτViV(( BQ|/ up4$,;߀|GGah~d] ã*Ⱦ>^S5g\_/M{yA=@Jρ1I00 rӮk"] Ӯm~,Cm\=[]]9EU' P;0Zˑ\a3ӳM>j-G]-U ,ꌫtx^k#*k\BWznvdQR?Yɨk~Ij!ϗFIDR(ɕ$^ 'KuRV*rT*2RJD,& ЋY2R$?Bоg`S,j[/ &$9Pk\2COe\㹞^yp\׊Zՙ9Nמ)Ovɫoȸ1fjM teХ9trj/&@vRQ;H~ P;zh^ {gm^K@ hXaF-A.Kp9C{QTJ x NOˣƆC,IyYaR%A:TU(*rHWtBsѥfwyVy\q4ܙnO_Fm[[gȮ$Ih-F)Bq.ԡXbqAk\5[*^N8 q1J%T[mFQB*Ӕ7%o i!Mj?ke[0c&0H6 PcȆdáFs?S#BtـBa$+O endstream endobj 34 0 obj 13185 endobj 35 0 obj <> endobj 36 0 obj <> stream x]Mn0tFBH  "cV=4CXsF,hxw n b)t浢Z, Cm1σ͟M[+<zsus 0:SkBrmkyz˟} $1GQɶ \knQTw&%[l^E{Yx)8 'ir?AΘ{O|`&rI,[g?"_)OŜy#& yO5'iBZ'#ÝBs~ x?N7oѢoԞ endstream endobj 37 0 obj <> endobj 38 0 obj <> stream x|{\T3s. {`aAEEAAM7D"K IMMcnmqAbKmn6iڤM4MӴDOj 삚7{3ܞy晙hwgOL k:re(*7VL隆AZٱjiJ}VnZ=0Bs鱭ӭbSQ?ro`:ym"ݫEZ6= ;i"15 <^ӎ.lK,3qw+0}7# j:A2 }4y\?#}⑖ȇ,#QxSp~Nc}pep/l2 h B.!~M9#1HEn o?Yt9!}_k]X ߅'Sb'S"mL6{r"RZEsBNxNbK&-GG^ȧMaGvN[%:|ɣ12"/(ࣥnJNKOs~&$ iB@, 5B;jg$A=iCkXFl& @ѣb@%-&:(D2D<'TCp/<-#[Z }x>yB#" hE;pH n| ?U1NӦ&WhG P1]I'&n$u9IQw''<񼦒4 76ؤMV@Bxf!OLz*>~T'ZUhKCn"ZP ы*U A rE~DVA[v`Gd3( vdu)r%Wifӓّ񴏾E;/_vqG<'CIoк+[pG10W8#idЁ= "DDH+,#ct5:HiA=B-?7T%3(>hjIs' dgRoJǝr&:6j1AjD)ͮWB͝;} hQR5rRŔ%U\I5*IY)9JO ()alQ5j8ͱqj*PʝeJ+˰~47+(ρ~ɈЈ('34|Z?;J򕕇\2փQZ̝Z3>'Df5V73d pś igtnQsaE}kj 5 [- %^{y1gU4-;[ۡ_T}in* kj,K3fƦoE%V,V5:Dc  Ut|A_9ԯVBL_szTnJHJRF@RWUK }5 exܴߥ*s˶b-0/<8Cc%G+ BJ=ᘦ 8~j 5ጴ iʇ4O'v9!fP f&s}ӓSCV0BBmCʹ\Tj*[*DwQu4 g9Fsќ>A~DNc_+o"W,U,ZVt[QuY*?u,/Bq7!x.e0KTBb~ܨ:=Z%evH kP8rbn.OO,}YL}vʊe}}eyhjEhPU \ GMeTYL/ʊ%/tp ~uϙoOW) 9y_Gy#nqfZj&pQP#;de&쬪ΪYӟys)2&K(,9@\}P"gtcGy4ʓGyybr03RKf"n'Px,Von .jK\B@,c8fapdbF?e>Z9Y CNroN\ ..~bbxH⒡"[Ѥ6MkiZ v7شV7۶:̷&OFNK}iڄm`޸﬿=5Iaϭ̾#iv[\:ݎ:}I6xEGdq^IVݢ`s`AOo!kӔ8Gl\?d@b3:e_ѯҶ44dg\ap;k5J^tլ54kkM $՘-TioZ&(Dyt,˭2ОT:qur{~?0qcQ0QG@'tM܌e`"bK:,̤ܘM|b<|b,ܜ-|L||^T %II|iY.Pw"# ~d<:ITbb HjɅ8O .ޑ7ero~q_o9=2tp`MHmG>H 1W/۔gG^>'\3p ‘ߩ x^o4W|[1/ţM3%dTٝqHLLdȌdSb GIlHliK>bc &uəWͫǪUYunU*pXnXnVh/&jzuV&=O''[x%>Q pgsEx.K8Cqnx~yuzy2:8["_k& nH0+]ŎD$|?m!@ぼ^w﫝ꦫMw_оÙG˧]t`ƅ{7˒pPD>l{T5zZ@ckդ9!s–ϼi")yW5ۊ @kv?$K )ČĐQ 05kB(XM `4HKRZ6$+iŰ6 t~a7 7v ? ߓY] ( O~PZdШvG-_n񰡃Lʦ]}zBp.hLFw-)qN0H, "7Z$֡SJ: 䚈)M@ a~FjjPJҌy$pp]sls)VC3!c ;&8YTA ~]6u5$?ͩ0.GZz6 HqU{z~PA zH&D/xNSgXb k4토QYd 3oi>$NOsM%zk]ڤFƄ S:,nCq c| %|eK8hLT٢F1A53yCfvALI^vX-exrNM.Jt pPdA;t8^Ja袯 ?paKcN~dͣxx]1N;MuDm2RT&[5r>>s$![ߦLS޼14A%1wG>}7j ȇB?D!QNLOf,}iZ0m6Í?{"ِLXfMP*Y5JZSy~aڸڴ<̴f3MI_&MYݾKnϺ+玉K|8kE#ktIQ> So(Q̼=h>3$I?A4NHN 4W4ĵܵuҥviurQsШ-L\&*29E(Pf[Q PܚL= :u٩ j&D7$8gA+hl`RXIJd6*'W~{@E&٬V"X5>: e'RѺђ8*Z 0paGbt;T3ǧ49~ldAfV`ҹf<)Lܐ3$74Hڀ6р۶mKlR׹.=je3'S3b_2`'g|{N--L]-W;޵-'"Wxtˮ936Φ,o`u>Or_vޫd^v'nŚCyB0MnA1C y NA+l%hEIЀW_ 3x^ *)L]DdC"7n~GopFDC|=;]zk qLj9u -߶sppPɓ_$~s&٢im}Tw^ΫŸ1o)g)*xK<.4x2u%dIwl0N~Q0f1lg2YϘ%l|,z4Jl5`jg4x ~l%L)9;i~gy): 6}>zы)7v1v]gQ~"eMؿzqWunT4^V:{n$vthmI/$A+mZX%{pusO/;Zx`]w2Eoj[[zG,:1H!/l7OP)|)~?`)),7caRjRbm*^vz O@.C^U4|D5XqbQ8$%XX5sl.}X}|]k@=oL2]3]{XsT{XJSʲd~m#?%}>tlu9YN?] 16I'H^=Ix$P}G0ax 3laœԕ:j[MtZL&3%t9mS%oOpy˟WM pY[al_ SCXubkj2R2GdP_Qe!MxhϹG{ s)O=UZxl Zŝ|룧?ΆIh)p; IAˡ} ޏ^NN&8t feI~V&>UQF'Eb@PCL:PSweh+2<|EZbGAqlL2iT@결4DѨxwbw-17^ny곡&>W~nx݌ާ_ƶ4HM̠.'?L |jHҸ2Σg"`W]V+'KK"@#fY\n,ۮw Vyu|Ǽ)&s_%"El0se/_G f2& }\Y^jf{r] e̎' e?, !2nD99ar{̶CܺQx[f'!9YW3ˣA /[63n ;\-Wۍ]V?YtY|yώ nxÍ7*ϼjiR??-qP5e,$'K{ UF-lof&jި8j$vZI{M23M󁍝c̙tx:+2vdټ#ޑw-o<=ܘzrk?n=?ff_-xd֏#0.`? iʹ0.vAq~0]q yv"ށTy0>ehppاi]{VǰpBn2^[$4\Xm<)&sQ[_CX)@w p "ʜa7Ű,0PzHǰ1lt4Y3! h41LAiar51,}1֢A@ ak1l&KX3lˤ{c!Y+:X0C9Q 1:oaԡ~W C1:èC5QF~èCIèC{KYs86q[8nXf}3snq<3C.^Y\&d.G 3K0= , TX,1`">SUA31gR7lΙN,l@~ 9Њ[廡Qz=M(Y˶UЃy_mk%WdcuvW`2< šZs1Vb.J^㿴>n>&a-c`SLG ,FSіېkPx| u¥'{P p+vYx>/"6<9l y yK42s4TbiK]X^ǙF:, 2&yÂsܯNo@bOi!R=Rћބ^H#0zU7a"IOO `3azr?[꠯ї!5~ǯҗxK"_8/1q.k۽R=bTi9.$-=Jv0J_xxPjꟅ? DULXVD,_  ߴ ˖#bA" g3 J7666H7>Y~8ۣe{{#>Hzw+FzI57@z=70%e"IzާHo қNzRi<*R0bz+MEͳ7cG1<)+iK K8 i$'y4籒+%Hˑ!C iQ: ;V sJ#]tI˻sB{xrc^Ry|?:Lj\aXSȂH -=ݦ}jCFwA2NXkdo=?-M wAVGO20 ]<=qހg)s:sO"s[%,o9)\g\tfneF3”jVyb}e^ <-\-JMfex'bQRxK äYݩ-Mrt:.YzYoћ^E=Ճ>^`2" EeBт=oA(NgбFX.,hYHIB "@EHV&PU&f b]7% [첯 c%;/ɡ;+WO 1I}c|yAwTfW20"Lr9PQ-\N3E("3 e \N$L+?=$*eKegLFqq.sdB3ǃ").BE<$,(yLfޒ@.x2323(O??Cz_y>tfgw7~Ec3_,+S~Mv-˞+Z5X60]^k(?gaAemDeȶfB-eo~ ]PoPPɢe:rِBFyFcy8r,ʜi)cWxCLO,VA/=)jPJEEWPg[,Ŷ` :bbsḷC1]thI,5SV`LcX!J&) endstream endobj 39 0 obj 10240 endobj 40 0 obj <> endobj 41 0 obj <> stream x]n0 yCE+m%"qhbXxqI;~`;ScO$[F90hҌ+-=o9v%.1T,yٻjK^WUf`<,>yK7B]F:XbүIl; 3Bu]20_-rg4 R!}8țȻ 5W H{l )@~">#W7['gʧ51Iiq$8*g\ޜ {Íi7EW|%y endstream endobj 42 0 obj <> endobj 43 0 obj <> stream x|y|[Օ}j}-~Kdˎ8-'Nq,KĶ$'54 i 餴iZ&ڦuPakaLC;LI߹=r](7={{uTb6Th?ˆOf8GB/"{SMufƧ4zSI#Z7>9t/#LDC!El*^|YPs3+&R7|a#P{2)O߄T膙իXZ:`6`ֿěS?[YwҪ_;A;IPFFww2wswERK{wC-0zHqBX8NgMC^'>aw3 O_hfCX%vF@0]C7O8+&-h;[lȊ6y7  nv n`"i)s691ҵrt~~[9?::\UQ?_˞^yw0`:;ʡqvDH.gݩA͢ρ'ȦdVPs"=k#. mS/N+cE2E!1pX LNOw7eٟD z%-g--e%7|z n=ozkRi荤mK7`;+R 3muӁ:+s}#gANP@7 /ϐ8L4әf,A\[۠1gH\hi7ĕ}t.X]7 _Mڕ+_ٝB5? ps7Q&h=Ad.8hZ5`.|ki (E"s&KYڞC1LoC-^ %h[[.2 W̅*=8pYl3[7mE]Mym#rxxIaF{+m!ֲTG hnOUB+h9|A [ǠVeXu<~@0GƑA6Biuaet+ڛVzI}7e^Ϗ! ;$&L̅,,@=יU@UU)&|u8.1. 9@t `P5$Tsn2H08ȇ\iYSZE& &*Ӆȇd#ء*<삦(hKPx3څ(꒪(} b#P7lT E=WeeN7氾#TKWHmE|JZs2PkLm@-ZNV3gFnnپ[~Vٳz$`磜%-kb[[V\n,er'n`].bHCUuk %0nyS][ySqɚ/2R!.u6krQ88Ak1ndv2ɾ*m]9۬tE;pH4â~ƀUj}u[o=?Sp):,yd&3jUjc5FFfl>Rʗb<\-8!wEC0-96ΖbTפdSV9v+[[^|Qf1۰[ L5[F/6 f+BOTl~q>#A "b Va~3Zf:*0X'Jy22Z'2 B_jQÂUH.ATe2bk0vN7TLu>Eo 5^. <{Or}Z sEġk УWVVp [9~K/sZ]\w^D 6bɤc"Su=[-דc>BA\jdf dkݥ\~p͊k1}䁍~iv㾆FŵfpݚeekVL>= z~Ԡzs.B ^a*%ZS-%j\}U̎ VI.:K&YT!X($XXRfIL`X%L>T * 0oQH͕Q4w4t*p zf<=Ԃ1>괖2 k ;?MiА{V@&ќr> L(oHV귐E$9M[k=p ȃ[R~yzб裷6?޶W_skŦWwlvjknwnf xnV|:֊rD6#VЈm/j9ZYKZ|\^@|/MDͅl0څ%,XD$niH 7#zbհs Ϟӿ}溑5ؽmD:SěokqgsxضdϞ>HN_efXG ێȢ,eGy.%EXw Jڄ5,C5l2>調obOU̿ym#/}sSlSSF_TM̊&ylsiyV\EEڦhf0 i;@⢂ <8T{m{r =r] g٫z5l9˝r88U8Oq\-*G:V7/?kr@1 V8C D#0$72xa! ߿u_T*}w|JFy-:}38A#8z~m/HgWľ1P!irᯯkDLWW҇a/8*vF&T Xkp`WqfSO^p Հ8+G~%vw*`YCmxpxYuޝwԕ+2Ny\V[CK_wsƚ"g{7ۊ~n G sa|/՗|+SM]Ħ`_xFDary}zVYQ3 &y:+gohո#QAW+샣9cB!{ޝpi>m(\,9@j颷BI^8rfߎ;Ck:/׵JʫRxCPT#Bx]w?pab},`1yU=̦ӹ 1jL44 e`=nįN TӨD Y;tKTۻNH2?Me.1D:pUM2V/=BN.tv:=BюVގHA:f?5_##|dXfoA5Gx fCyI]G>A4'pM&~)99Z=:|c{3cK#bgӲ+پ!iS훦Ͼy/ft_@`8|StZقg.KfM3Җ`l1a`@X @rVF[pwA]Pߢ({ƵQ_h K~{OVF Ϩۮv?/Wd? Y_0NL{_PђpIht?$/ch+_!*iAÒF4{VYme:7 qYX.+ VI; c/-HT'Zn a4,+AրzW$ף:&t { w?,~%ɃuWde?+?Q'Ra5qSzƤyV{ Wݯ_B}Ÿ:vjԑV/!"fРIZ´fO4TxHcԅ?&gEZl"-i9D'MH+JiH 7]CUFլHOMPN& DE2]HcTi ""-E*]BePH-E V T A}H+_wLoYk!&2~s-_iHΖ4lU4li#ҀuHζ" 8ni]~(Ҁ3W-Ҁ3AEAGCS(s%Q>Shŀh hO@ԥ@KƐh Z {0628Ea19ʤoM؈8k zp@hV~q!,w\n>IU Qht%h{r#AHڅ/<J|3T!_XkjѕǡV*Zi5.U ,f蛣wkh"7: yAF@ SJ³$#O VDV8N8h&&삶Y Q}o·ځZ98dY!v&sƩIZR?JꉾCj8VC#3:c~nɈ-5T(-`.Sd[RK8$8ml!' jGQW 'g#lGaoĦ@)t%)~W0iH?Bu-.JQ'+yr&A~X컏s\;HT5FdĮʭef{*M2^G<RY9xkAn2TPݦiqTvm~STIJ\LeF\2Ep,[!l|EdΒ!*Z>ZR&D|ga>qIgy;CykQt3 G)qOI梍Y,-xh Fjuґ7R?MP=EskR|޽t}>%7q("XUQ#Lwi1WIvDqUbݓ7z YX4%hz`f! r`y;Rsr#N3b M✐Ũ.#T'aG ܧ.Bԛ:%ZR,CŨpye>]G_;.Nē])/'BX|뙜b$7MF{X"Z M¹qX oҺk$Zڗ-BK_,Ech qx,&.ES.NZ򊻮,9 e:ST4Ʌ#^`өD,l"uxjn&ʭ Ǧ`n8sP/ؓ =Jrc4&c0.2t}2 Չh(吊sn<p&u&&2R\r*x'c7Pe7{cr&βIAP"' B$mX Xb26-,v8½9.Jħ= Hl2MӠPSXBtjd9)=QA$lS!7EgSDS^ 1Ys86sBa*Lqv, *Au1jIHAj&p(D( !8;a9`"E 0,f,ѩ42 h0RElRTb84CA!z0678'TNSɉd$N5φETD49;DE SYh0M&H<xMk2=ũY1^bNщ%-799pᩇJOZ\+*M_gRNZ)v)`/i{᷏9ی"l 7ZK=v=^^恣vz(sY7&k;=L»N,?(uᅪu~6}A~6涃e=:f-eL?2L'fg33!x SpPъFj-3[̆foV5fόf`q3ri)#C3E0`xOB(Ltp@s>yx^QrVUkj:_ [xrE+"NjuzeHUaU2)+E5eJUp ?VDJ.GA]?R> endobj 46 0 obj <> stream x]n0E|"W#!E*M_0YDй>O Sվn_ֽ+ Ek*alcneA,sF\rƺt HNcEGrr"1#3%9B> g33u!Kx Snb!`)zJO_$GTi''<@R#2+tPb]vCx8c?!ڻn,hipz:V a endstream endobj 47 0 obj <> endobj 48 0 obj <> stream x|{|[ŝsdKl(lDz-NJ8GbDŽ؎uK,IN@Hnyl@ l-Ǽj@rϥRPMiaY͜#Yq ܿof~1sd'ti _pq R. vOMLn'di'3#?@800R"zÓi/[= h<+rB;0|ih1n2Hoa}Wh*L!P^?M} CE|/- ܦ\T4wQ#HܤFyC,~"H8̆34Z0| TR!:z|fq_(/_T;DRЍT=loBEt7%QzQ,; $(П!6VPe1Et:.BZDoA_ k,ZӠǷ5(qh_GxauG O"\ vy i4ڳ+RTGm6Z~I}Ng<;~zdm zr Z<#SPS~|;C.dltdxh[z7ohvAkKuކw Ws]UVZb/.Y-fРk5yjR!14j(`#u۩gEgzThw8 㯕F ri`t½|E[l ss UCU{sQ...±.r40[D?CBYYyidCڷd4ۄ*7(HC2} PF2o^O{y z=>%Lψ:45x$J i]<` @syh0DLQvuF|ۃw<pR]e(HJ.A)*F'\y=.!Jv ݤc{lxljg76Y|> `7nSw^8m #B> ?I",n׳·@ݜ^ lz =$و78+#w"^~}`&(A`px={ 5WgO7.x"x?;G{Ξa@0sȍ'=XEEcIv7t a@K,iN< ~hw*(]lKT[xNtkt6@dٔ Ƥ=E;E/gt0TO` җnrn ӛt /wzgzNMOX]t/aXcmcT0'&0d |^s8@7-d'; yvAߌC%vnQ]=X8(qAÁCC828*Y4nC/ %j,FaxTۛfL7CQ眓apGݰ}p5fo}@FgD4b&n)":BzeAy *ãPpy LOU +tFHs yPqvb~w|+,t  x)?va._\ d^p]g͸Y8M~AC5HPK`&20)9 l#~ƋFPUPT2x!?]l lj%乮5!ء EZ<脮`e(QV"'"DJ]Dbiu>ԁ@Qu4 Ш"Ji]}XTC Σ!A4n!AklLY*2Js-/r8rjkp:bDvC?!AT-v:_y*?L'X8SFEEwp]-$^'FUգugFGuE'Wkgfdutt]mTvz};Ӹ¹V: ela^T[+캍l}y:vcצ`{0+ o>>k~k+<g욲R56:j*J{]x[v移e=𮔖"yi]#ƲSeLLϤW TB0|7>˷VxV]⛅-7^Qۀ^F6AYPw}kϗLe,wT(+a4-uuteKa mhjj < gfԺ{{45# cEe>롑v1H+U~j{^&o'~lSUtpn+ oq ;zDB&hztSdLZІuS:].;m £*Uij ?Y)YfvV 0[ǿ}C>xo3fWf|uB/pv؏ .vdCDdQO^kke"A||6=-_]Q3.l6)NbZ/[~|k]]vU'~uOٰ~u/Դ`!&j媵V`@fLRIVzZY[[ vKf[8ׯ9Tz~e';33F! 쓰k¾Z㒅?O :4h .k=vU;vF]-; ]/W5>6TW9:~mmTmkn\rV # Uv<m[ST~TKWe(-` Njޣ eUƣee ^Ck f2`*؃ؿ&1s;p4SFP1`XIJ+= *c\ו+%%CZgޕ/7VSWM EJީq4Z+힅û5$޵U71;\Xfk]I j[MnNG%ɔ %ħ>c,n*P*0vx ^- =3mtO)J벹~ vf0; b2nZУ7 ІV(Usf@{UuE?97F|| yi[5k5w| =4μ|1f]g}v}Uũ*Dy=I&04U2ۨ25T_0dn+|s`K ~]-wG8*]8aRb`,bEO7t;oTEug]]WSg^EjmuCz;neץ5ckjJ/u:ˢk9 wPJB3xWP`eT:h ϛyUN!.D/6澅RuC˭I_{~l۴TPM wj]_ҴTz\ecbbdZגh1u`#6_ixxEv`p軿/(|w4⠯i$ Y6Ix5ltLE4U-Xkޭ쪒z˻`)[m,1yjrYYse`޿p͈ϮTWoOU: T*{|vzIY٣;<ϧh Q JtBxb)e>u5Je1=R 9NR,<^?* (6^kZ`ߦoC6U`ϥMZ?Vߓ^<>2=r0}[y7?:Cdzpgg-]~𽵕mv;O<|bWJTzfT2)Ԭ0Lhඩy\g)궩|JeU*Dۏ솥,g: p)\h3wy7zR, GQdN1@a˨K hDV(A9<%Fߦed#ZŨbT!*aZeHmKt2OG5h6%ZTWH4Kgn}$R$F2GTJ i-Vh%:OI h5r3h r5Χ.4/YZ%djs-ߔh]-K4ly_g\gkDFmm~mH4; 8ZhhySȏh2$ D<7cSN +> 7!G 7Jz:hE1(YA1)躯VR%ZMd#7qI/'ˑKg#O4~;,I͌=2:Q#:N /Yqnnd.}JgA )T3OIq$qrmČ/"ѰnpdQ~G+cdD~Y)"M %Hm3dluɞ{9%7 "zUY#HNt7IvT<Rݛ3 F(1&\64(J"0Sm!svsSPX$ ӔC<'"K*x"{\c@LNJɞP!lyR3οo &OL\*ձQv(2N%١P2뺸DGVVⲘ݊e6rvI6ֵdIH*JMDP"ijLJ&^6{rW֘XÎ")=ťBI' ӱT"J֭(ak<OLؾIn"H"w<7Q:%P(dd"ƫjf'Bx|/;0N%"1#bؾ/aC``r fL%(FvGx"h$&nEv:QPtMD (p<9`rpQ),)n!49D |P-vT}SxR|:-1 Em x x2ؑ`,t#Lb@ ̉A.ba.7$Vx# " a2 Mb6`A6J] IɈAnL`pkv*p0ڬRYK%(UIFqAI8Q+JNGS@A2n̄$6hiV2 "e:%!ʒ?HCLA %Lr]# łG%M6%]3H,Op(ObLAZ\LD%F <*&qGK%Y.2"u@x KNHP)*KQp*5߿n2u'TxLN %m<$f`z܃}p`+\X7 <8v᜹NHr* Q @6Mձ1pq S6tC f?4;hvC2_#*{DmTi( a!t"?CeuPeEgB}JOH.&oH&_'I_ 1#3~?$iR?A9R?H>N4o$u>F꣤אjR!aR_EC$H݋kFU:l Ja(_r<AѠUT9@進 .(q(|=P ;@ WJ+~Sjr h1}op85m2LjwPd]^\*r@Q>k}(wa$Ujɩ'<)Nu+u---la/v6r]rsg)w,uIڭ?ky$Q٘O))9RHO}ʍPSCWW]cz(GB7ۚFs:k6k͊z31:5njgASW] Z?V)*-#kEk JPnu^]Sk.@̘z݅Rߡ{\ T8V uv4ߦ,72Sz((PU(jڪ۪*Vmem6[MצnS1mm;L S0R)x ;$4E}< 4< vSEqDQH.x_-) ԏAt/JY\==N-|F@ٝ{{Nf,2dJbJ ̩:&/C}`, ;;40&hdr]s4Pn,OB)bbRE%J5Y(2VS]m7O?OOs 8oGkk#a*?}|/__R^ endstream endobj 49 0 obj 8776 endobj 50 0 obj <> endobj 51 0 obj <> stream x]n0 E,yu$M_0\ 穵 ֵ eu  <8Oٶ\k`ϫ``ԿZ 4HoY#A<.r'QWԿD)/QsBFM\>ȩ xG[˛sa}t0nL,I endstream endobj 52 0 obj <> endobj 53 0 obj <> stream x}i`[W蹋$ڮ˕eˋlˑvF8NIiXĖ\INi6- Pi;àN'fS C(,o )K&ιWKy?ދ{;sdӳqF7[ e?啫^"B4fbZw? ]'/A5Lƣ~t%B]C$T|;oCvr:{Sy/BP~|*57y(o4iVqPvuA Τ2Y"t|w;=P: 0%eaerE\hu`4-Vᬨ]5:O=%CZoG;b."G]o/-cV/IèǡLΠK1toEDO~zFA)-ŢzY7iat 9nG?@܋T܊BFh*/U_Ei&0r9h.|B9_@ets"* P즚*G@EtXB$=>uCCk=:+m֖foScC]⫫*+j1=jԪreB.cB͔-g8s!_Eꕓys83m=HNu9 ot9룱\Q19Gu7M>rfw9Ś6jBЦ=:s 4Ms_܀-I>8[wP>7(6C1"(;{{ r_@: IJ$eK GaсIℰpǺ\9$Fc@H24,ҏm饀0B>(DJ -cH%u'en~cTL^oi::v՗lKo.VS63y4=EԂmlD4`(y*'X/؜DAܠjO̟ qcT7Fc:3nٍE5OFEvu:]bͿY9~lssO65x''?]9׉M> 61NVr'&R7&1 4SRHt9BQ̣} 9vrR>نTn#'7;?k|3W)?8i ʽzrV/yssp8oN?z9=: b  W(GQ=9ʂUk'44tYR0M.6ùayN+qo׮vt=GrZsڟn!?Oba0q gicad)8E.յWяvodM~%LKedTRS(<^" }@`x\+6PTRd9,)LF:ad47- k⺫ >nqaFn-gmF_L{d34E"gkmr RKZ\ <.a }.#/', s"ue: :PGC+ N*lQ7=6/297FQAݽ(G{R\+wC9;p}X/ wǦ>7ݝ{D23$ru'hÎ8ED&)@x6Ʒ2WkYO\NҔ甭8V)jDDIr*SJip0-wH]rmu6&М EUP, \e xIUIB;rn<9!PdnpeWjH\f"4O\x&@g(zOo4XbԌP; FI[#kQۦ؈lC.@*U 5y&ɫb--mC`w!ߞ :p}ZK{wVWvtU-c6[ޥ[jnM/VkWpBW{ +r&zwiero5nj 6zzW*ɏB1V]#W -b ;:F.wxV;pS%oh]S0Wo Xw=MMmB֞AdWK}ӊb[G=*?~h]Gv`aM'̛ȅe]5V;2UWl?!(5u^[j6W誐`\F.Ż%キ`6Y׹xit\¿ㅕ_ ]66W^NKf\*fS:uD?{۴]hk{|ˇ}״o[?>Ӿ% U}ukw_qS`9a9B 'ێh{hb&S !0SkO5 գ͇U(I;¦4b.P/CTJ]+M-ܹo+_-<5^18E8.i`(Etv3:3VZ΄:);-Ts 02h}}^ul ( T+>(7l1%JP棷8՞Z~ d>2&fN2m-Wi>;join۟~e-RT͆TeG] -rD-\uWIk1O(-w Zۛz\Pt;/[Lv^ T[|,z;c z W^"ﱯǥ=7G]Hk~%n"FFz{ypoY|Vb]ۦºPʍT\?wGItml6ܶkΆvay\SBm:qU>RqLhjW46FsJhkY6a[jOk-[UHHEKzQ#1? a[W5L8vKmU0:yy|rucBkS{llY]m9{|,*zeG{c ,䘇wJkp:8No`n`jCu aMW&yWQ?hxB'Ja10ҺZSkk&jL';{>#md.^fk2օwhJd46S* f\n $VG$~*OAdn1q Qfl 㪩3*$>qE@ai"k0_\&gAiYlPz64gȾE/WPkp=WJCe3Gyfέ[]]zV跞8oXDZnXasJׯl^ظ~m}0D+ͿA"e:2H5#QkxJVB05LSL\4 N7R~. E^HѹWX"TZHƛ!c1f"e5ZܩЄgo\?xwةhU(]{q1O㮬])XZdц}w^81?o ?閡uXv)Ou%hT<*nMvFIjyTa]L4k)5c4 6홰0O}Rpع L_^W#uv N;aaڙlZ&Nj{W4;B]ԸZ߸~xo{Lu 3c%^B?t1kC`%I .ٝ3piݣ䙽2l>ڥա5>jaڭºĀO}ÞӟD/ ybDK+TOٺW<-L˼P Viw3R1-#1Zta*izF_]Y1r{e* X{~[o}U?Z_bj8Zސۈڴ6K1"PuLrm襍!JˠeSBт^dqBJkxdclkUE=}Ks?lW'>)fV|7au Փ"v%FEV6뿲82|fϦ{L8>xPІ[*JG[-doׅ^,7 _Uq+eNTdj˞e\v&,WjW2+O Z|^Y5L,(`V߸H.΁M1^m)@өe붦MwtB02PKWg SM.65[\]c,/,(kE{lZWaU6{^r\:nxPj=.p(YQ֨Bvu*#U~-q!I,X$r{)bAUJO!H)v杯}]){)DZ /K:laPuNr3aٻO 4z3 wOK}06e_q\`' ~,9}ţEǾ9۷JΩTv㣬1;LKϵgkc55^zr#fC/qejƖx6%A{[ MKP{Ĝr<&R|FMGv읐k6W%ɭqZfif\VՅv:C6뙰+uLXRMgMM6}rA @QzQ}@tصcp}e+(Vf\u[46 {o /qoEV'ׯ tBӐ }vRhRӎt'59m6L Qȟ+ rx |< ăl|P +ꩀ\A3>08 1]h' ^<@n\x#u|Wdסp;# ^~v4r>sO?i>y7?~-]cW?zS~U2$X2Jj 7-Yo^uI0R{I xWOu:.+]F-nsI=[ѿqS޻ZMWBt=iev*yG2e^qZcBg(=%;eΊ'zHZO 'Kc.>Ȁu{ѫ{{驯's%.k6u%M +^mzW{_gn V~oѺ,};ݰ1}$+/Ԧ#kFG_Ip58 Wh*ۺ[\Ƕ]Oe8jփ]G AL4̮JQfbFNKi`08j=*(8U+O|(y"Hbt@|Cݟ8R>4 RF~­g@A7E&]Wޱҿg%k֧[P[FU~CH-ך[o䧜7xT6HEJ5jk[^Fp)SQOxOɰ"tգ-68Xb('cIXhpm=O|>}h[떃=~ uTBEVMe~uxs/L bH-67ųrgEL3[<mYi,謥8^Vq9oq_=k~b q3\s%ov_zjMYygfߤ0{tԞ``{Qۢe.N^y'#ᦣן`~8\izO4~2D.mBYv1`CCOP݊6`fO-A<;n.,\fBZ^:řvt=@pA3xUU/K"܇QԿ}ssL_f=+WQx캲)וS]kI=ϴuqwH?jh7~f:'5[GwKEni)1cX `YC̠u̽"ːQ-k` !eI&J4(%rB;H5h͚ u_"%B  K0j fː;#rd` .Cf}Hȭ)̝B^B&sk ^ "dÒ`ElO >[.K0j`u%l` |=/gE >= |$%g%DBQYAq̢I=K$y!_4O@]#cж8rT%߅"4ui(gGp# w{U%+ג%iD ~q19LV߶R%<* Cd5"s zn M͠nt>[ GljeOz' ++ k Gf쇶Y = Q9xOVZ_A2X) u )ʼnaX^!J$WE!?E=#9=s7t$[vװЗւ jtKqtثg5&N QI'H1kJmKEMdJkv(%$KdT2+Q.H9F$GQPԋdId}TXtqӌC3E?'f~ "EUV{DR%TiI —R^w!ŬpylIImm]x:IL*&RV~511[xP<ޗNDC?N%Ƌy/i3\aGN|O'l<t4)RRܿbD4d" ex&c>@"ft"i]T2=2燦̏$)~j3'~_udөD3th* ).q`:%ħg6`8H;dA,t&>u/kdd<90dy`vb<݇D%bd0 \3:OG3q~|2nH$10@$c°D`xOǓޠ6 XKdډQId",> gRfBaLHTQR,vmT0&.)PfYyal 4Rd%dXT4Y1~40 ZỲ(ê1'ǡԔDZ܃H:1XFg9h*2 6أI+IbLQxt7o~ ֹMLljBaA&E\I lP*Klv;|pt[S>蔚HGg&ƳA3%]IwfGA z܂uNda;B<}"\9b`, S1qeDff &x4N%A1`VETBe)"݉g%W6.jqvbHU̒'R=t89N 4G%x,9?fLƧfZеSkpNᮝ¡kpNᮝ];v w)ܵSkpKnEoY7W>tn3pJ`<5Κ?F=c9owKe/}2G)0P:E{Pq~\:kOcSǨ^ۃM]}B>uۭc25wIyOuNTQ3hu+͆v.`VfyQU.{]zmCND5}~k/t/&٫qkkݺj-_K?b+ +S#V˙XJ7Uaf2˜T%zR}RTJ RFCLVzDHA*56CckTR]1sp1^4G{z=sGף0=gs`H(gs[(c9w8ܼ{,E}09sɱwпk9ʎt( @?9|2cW&+}.~9{{ ͽ~5XW0i5 uUxl09[y5gx=m979ܡ+Pؼ;v7z& endstream endobj 54 0 obj 11769 endobj 55 0 obj <> endobj 56 0 obj <> stream x]n0 > endobj 58 0 obj <> stream x xTǕ0ZuիzSkV%v\I-!$V5 $xd{l2fIH2n3`C;xgı=pLNս-&3{RUONս(ҢEBϺyig(t^"|luͫ !V7J#d}7{H/ЌeP1A>w覧nyJ'g օ7 3YUn,J)p$ӀnLC4].~}^A/m~=+}ÈϢM4߅h?P@ r5tPu"A(:!>@v|e{aatfz̈́j^X};qԊnܕMeh AQ FP/-nE-h) TZ`I4!(!%3J8uvAQVfcntW{s7zV.fk6{@MC؃F;XWQƾW wPl-ڮ8An֠X@+brgdaHm00$.e? {PހnA؅ I Pz!.#i.K`_y${^b+ &ɳ&A"YT{8 O,:8Ss5'n?D>vϸ@]('~;M< u3Ӡϣ{п@rA@8p2bx5) t hrky$zLk6_?_?F廲2 _;K h?ߗ~ {'dFYV|}& ^~-dʞc?99?ڈv*Zd2ƒ:"+&]dN>wAN)y=3w܆7]'r9c~g@ 󑘡 ]NdF up;P*\]wٮ! ئנ9OjJ>Đ4PDu,@ 't;[q4Eָ"}@H^)'Nc@tkԼΣu1D QJ4:(I@>A51aW7 jWj_>{jn ,B"1ycL!"ńp 柘}܀Vvw$3ƆQzz;bmvhD7'm!vӯ*FnwT;\'1M1/͒nxN4xSj]$!Mn kZ@XdaWm]F& 1]%RFׄ2t@^5!HG~z/lu7]빶sHlj&b8؋(CN8}i 4A0uIERŤuuDCӘ³CwdD'3^M!']}i9owmۡDSQ|wܴ`|315B8c ЂNЉ*4];ְ]@2%!6pT \DvJĶ"&P&MC,jY+G}+z`!V´T[::%*U8%"s K~6|PÃDKRJ I'Ԋacw># r{cD˔2z3b!Q@' L*@N70=:o"FVQAݵ(ƸkbFц@HyX.' w?(OT} 9qa".?~2X3`y]1g)0*_R<M'Ƕ DLYbgtŔB1FʹSkMA(I;<P*&cʼd@ׄ]L' p#8! uDRh7Tt@maWKs( jTD $c*?٫a@Utumi#RJ:P5;Uy2̼ݽ t MGR@u,3# G쯁wE3EdRY:/vovMy ݰ;wDN!5qmAl N嵥IxbBt"I))@V{ QUa*)j?e(BTZ%P4E|߯/JP0h2uvEug[7MVpp4)6dQ!.-ek;S(ܥeetƒ k,RltI`ּ,ש ;{jSYע0ݍ$g_V[lG XnmO*N-ݟl4sRf=῭waٛa-@TBi!h/p"K%W\^EP(y;mo2z~KyyoI ++猕Ơ ;!{ Q0h4U)}F UZ˔KLv`rjhכgݬ1X J@*|Dck6MHbOu1v=T>e_7: Qp ;,&K%wOr-5Kk9Ѕ`1=a2 i# :kQo:l$NU36xny9wxI.=r[EEZk, lŠY}db ("[v:X%*e[ &Ee2JƦ_}Jg|犋Aπh ޟB[-seA\KJ{yʗk 78`|erkX+8;O?-iUNЌl2. bAD$ȑZ͂p8-Grrr&}?Ph(W*k3Bzi Z3@T߯#:muq%*(5Y e;oδ%)NOavvsPovْĕkt3,+)[PgQ&{d͍!,of̘50ka;jbZdvZPtB 1gl5O`M*Ä&`M7Ťvk2 ěncz h0Tta^ Ʋ 7UUO4צc'5b,n(jWuOo(Tt- w_oM_|||PCEMo{&3Y[?~f",4xnbNQN1 HJ]LuX| =2QZ-G =%!@fnFF.Kh)MəXH]O(ق $u%+2HY"+Sl2}JYMe?&O}\->pl76W\ WUT9u\]tD484%\ccŏ?dǏY.'9qUUX[D|y{ B&fh1 Z}ʨre AOzsJiS*xb+PYwMDhne˃eL0^.'5=ŵd!"?9`ЭN(sV,K4Oue5>#=89!%9=3b=6,Ƙ5ÈZ%~ ,[켤ϒ*-W%5TYe^wj$]웠uI@B]s6e`5hl65l:0߇6 ,Xs>PQ**M 8 rLDr L9x9s ˧l C_s}a/G5X)OR0J1g7 9o1Y[`2̫ݠ]xZEZVжi2L淤i/ceG^1>`_ *󨚜R¢^Q˖X# -&%5dϷ!Pvi:l?rzVy o[t`]mtYTtY2P 7.cU7K|3Wɯ-wWoB2u'X +*,B> d>JF8$I_`삞HqQA/D[X6%HQp(bgz_@P4.F-9M6}0٪iNh81h4wkk`+hYcࠑcͅ昙+1vggpd9,i b-5<0Xeɤ+%S$[h5[e'#XEi,6nɦ6<#I6iݓrr2O=ph-vaW–9+ۺnmTͨhesah.k洵pzn s[MWFYE)I2M{KF\eM*5x=h2ɱG 38{hQ[SkګC3`/PH,WHM5+dJPHa6 kfmded-Z8%[F hNxETxKINQ|Fb>|e=57S|iZsMs5O?74q!?sjY*4٪BRPXn5Y,huʐެ!=wU* jÆ 6Â}>l7j3r1Y.kNdCA5ސrCTW}H;Ӳr~a3/XtM.9fW*r N-Z!dXlJJz(q6ZUrB:]n*' ' 3-Sr $WٗWREr9UMX4̌2cfm34Tƶ#:@}~MP ~ad>VXKRi&n*Ӭl!SEasW:&L!wLyʾ8 >{ IQ'}A0Ţ0VBL byu'~H \QuŰK{n V {ZTy?|R0kkS ,}[ZZG^=Q|ҮE՛^v7XɗE%i=^<,x9B} 6)k:HXb8KT%J9ZB> [ lщBu E&bvBSE^w}[_6gܙf5b̮wU V+=sy~:}(rύEBHjeWâ fMHvي[U3doG]}bT>aQ=;[ (XeX_Q(cUee};n[ Se  CXha[ @[/`Vk3ge$ܬtWCì&`Ƴ;UN7me2KCY˂v?|6j~f~k5v}͟4B) ^B#pVKjc6PMomiCor:qM~sd6?_l,v%.hKſYj Y%)Btw5,tb7~f^hP0$3}޴4hbM6DPLocWN26+rV7Kr9ɔEtW$Lu /*};N 2 X)3glZͥo,xX/KU?Z:}1ѝU=w܉bfXV <2T,;$B$2}lNn)4Y 3TUJ۫{P*$/yD:~{|Ɣk>_d+X>7Y=M| ;=G)s}QKc3:>tEunCQ5ͩ-|[CUk&'y&X<[LC{b_N]{N[jK'_H4 9p _7,*WL3u{&de:YJFFfVj2y5+w6v8q"xv)IB,X6n{CM]|AlpSRS+R}Ysn]9sVFulӪ^nikTf(+ (ͣBdY}Nb32*CW@,sթ3 xޥbg ÆMƠp ~}u)Wj?hVZ}[Iy?ͬ%PS3,XDҽ`˪搩n&Oʃ^ :ݪ 2^Cd$c$2Z #WI6HcگFRF1N؂Lz3${jLd%'l4M)Ҳj큏9rR;|!/4͊B+rڌS}3V/v]e*Wwә 2p];.ߵLK# ʿ۔'Dԧx| 蜰P$Vϑ,K"d1A.++-;jK)8|áz5lIr`IIBNޅ燸P"tVvNbI:izCz9茀wSgi16yDϞ+>ixQBzEgL_ \D/U k|9R@dTe aLrsel.MՐNr}B5q8Rj:-4oz;dˇ7[mڗk^3mC{>s[KsW窛SÕms=hp{'΍83k S6{IuO=/7SnRz*2t+`YOW.x:zdh3t^5cj-ehJ)JJWJ6̔UF[MS=5Oi/W6gF.X~twz3W]w`7 }YYf2'NjgI_\zq[o~@o HeP1ZV!PH'aYlZu@ĩuɩ/tn.Xa*3Ɵe*vQt^UajFzơPz^PUc:ӭʶ7N}9$I.FIJL7ZtҤLs5NҚ[P]+.̀_I뇽|ӥiš<.ҺBt:x<2^Q2kץPLKۂPA>u&b;SLL9KM.,yC1wd#˝S?qBmCm*q- IL mPӜ߆N_劊ƽg+Pq#%!`;$Z$F׉+N/c2dR]aҲ?YAsytp6a3ɸv{6Mвq"̳73@:|7fw I<.Z݅:#fgZmcMl{?S70}(ig{L_ŪYd'fw22 -ْ}UBɄf\ 'w܁ƱWkǯEOˋj3m=/WNKtT 5)~bm+/2(-(G6`ch$=PQob–+pRKx~0iA L gػYe1AٓrJdN!H`1%G(fiԩS?;p %W'5)d*h9"9pH9E-,/N~eg+68DJ>΀tpi*+O(Ȱ[ل} ,r@'|&`cfטּk @}%=SΆ:Yc>vA#B/GgP_P38wa3ݙCn zsqBUc2UzDw25j B*KR\^62f2lvhbm,<;Ɏי>l4{r\{~Ik2A-]Iihփ*x/zlN7)mVe9HvVuY*M[ls<{v"X$ӯyZ5lb v`u+_ů߂*ɧ/_M|/2m>7le#>\R ګz`޴i)x;P=u fz}_c۞iM9V5ڲU3^S̪̻G`Ma5 jSn.D/,z3^h ɖL\gf%?A#t/4 FS;5<>{kxNǩxkڵKsF:;X-+Nȶ[,"V &WTP)-aHYZX{'B Oh|Бd AɆdF򰃱:&%LCk:61:VO`4;0^uP۔AI$NR=J#+=\XQ(oùɋ΄i(~[,RÂ]2eɊV\Ub_oěUYӱ˟ܳډ 4溍{ڀ1ƿg:wy \ZǸ [J&ů *jd ֌iҜ6hwi+iO~!ɰΘdV~e^bɧ? [~n=edαr?;  U% yR`$$1NrJiI0F:W7H0 A,z r(K +QPL+jZ.PT(G{LgmbLY?<)sJ0F Am̂L`$X C V mD V!7DX͎eAɿ} N³_`w "t t`u?`u :[?`m%@g{= tX'@`sFbLs6ԅ:͐D^0r6 C aheGl%KMh꥾Sj 7=PFF:WןW̓=FYGqahFƊ%׮S(zB3]:j(}iS(@V"e7Dk@FA({+QA)W%c1O@W=z)PXH~=TF -IufVDVqFL8UP7a*7зabT?Ȥ$ OzQI6(ջ^J0ݷD{4c0]#T +)>JҾ]:i6F@$MPjѤF\^TM{=8; }!nG,3O_)"1ÀW)U2Jv$UF(WFq6Q~N DBHL $`e>k(-Fr~ c#H#z O6|nSIz1 {3o)qY-%JG%`USF $dhG?\M];w#%Q'1k>&a.Q? I^Aߔ[=< r10egm(u=$:2iD_⊅JIܑ}P4.66%u$I};T~~9|8)Wz>1'O6??|/.,g  ã}~o[;:·GGcxp{tXxxc/UTˤė+˥")Fhhot}#hGkAR3%X}< /Gã>< t#<g XM:}Ã|n^;@7<¯FHto̷2P03LHbApp-zp0oڡcxYڎH3FÛh82I 34<g %=(lH(E 0fP\%n} @ht]t8)FL=!Jd~  9)^0HMrjwp?BP' ih GGG)a٣1i06B:G{JhaQQ2yn:o6(!0)#VKL]K7'#c08Шp`LAUl=< Re*Hh4TD7A"s|o]   dH@t(@au@>P}CU"ѡ@`ƍu = @́U #Sw9Fz#炁]KZ!>ːkȿsʧދNNAr06Q!\+  20}ՖƿCtMV79^6BnAXk %[RWhUDdgw|}czCõ=Ayyyi;=]N0HChXďC_C0Jb߄QJX&@} ss3܄d܀8HoE|#Ed>83tWzn9R詢`Y@qڦrol[ %x(~ )))]%ev#R:,<ַAI,c3+vf>sLŔ0eh]o0G }Hk=0Rni%} ay@1Քjc)_ yTk@9F0Ӡ^ՕK]^A'gG4RcZJ vsNJ$eЂ=_C̒XF>u"=ݝ(LKKN: ڪ1KR`ж LWC!BsQ)") -nAZzI}rq7Iϟȿ*l V>0=^8C>Ee};>Q{~=Iz3+ ߿U}uBgq·‡ |\;McgXHIxI.|iK*a6}v1m.t8~`~I'olܺnn)Ceܓsv@l;^9>c]5q8cg^fZL%}Т-,B  zbEƛt>}[֧g =dLuNS=ZP57 +ZiaHPaUb wЯr Ұ44M.Qm`A iNdW$Y $8x/uO^]<{QcͱaV}/ίΫΩVgUgVj{TVU˫jT1S+jh1bA_qoZc%G11f'sGyԸxIq g@Q{./-!UִX1NBy1wgdt,JEC9ަX^S8%J?W2^5Ny`y;Ԫ|h 6JJFGjx9|⟨^8ruXdGbXGUm lE[cmKc))ȕ-i 0߱(b;2$CdIg}Ep§>p>;Cx»ށpYC +@8 a? 0a'nb]:!t@h0 B+ B@(AAA&E> endobj 61 0 obj <> stream x]M0 <6+EFʡj@I@9nW!c33<<;R| SwK~>tO2%sVa %=>ϿՏK^fus󹝿W_h󡏏S>~> endobj 63 0 obj <> stream xԼy|T?~;vg$I2d\ B,a ّ]@P n+RwA .VOwۯ6ZmM-R[w&y̽ss3aɏ/|+ /-O=bڊnF =Eנh2:їh,bP hY4Bm/ žمɧ7-Do!)zW .QX_t_ 1i4U᷅<~q'.iB3 FtpQp=z!8л]h):`MBGhLt;3 r4אDr8JԌvЃ藸I3-@'[^xyہ@O@{=SIΗ< iVt;9+Vz/ + pv-ܧ~oE=N30&.< ?lT $`)頯2mC{63X$E>Zq W@]@5/J0Zף]h7|Oob/jh$7C `X]xH )@խ@}@%tџЗ |;>yV+ɗ "v|aǢ6j0P>-v, =x/ޏǿm>O{T1+$KI'?\h3µ7M0xƱ^}b <_o;>5GV5d-E4Bw3C |W |nh~τ<r|oq8^j \9pW:pwP}&ex+~X#'?u^?y QI.=$ttljٳ Ň~8Q^7#ӅM  ^,)%ﺀ v4ͅ_O}Cg~}~Og@?ɊW%x-AތGp/~__s&b$IRKZX2L! bl#G3er T%(Jn:Fd3AҗkhcLg20$QET%]!="헾'L&Eeddd#>q r ߋ'} .|E)@=4r|'j#PK#cjé2f,B6 v8f7:B_!=p :9Ņ@v|dh)YG|KYЏ鯁o>O9$6@z~6c/@Ct7Pڇl(ά>! ܛŌň9Gg]Sg }pR9(HCF̯̐ЯI̢eoL%hԅ0|}h?O 3m@2Deml! a׀sIh1p;A&#BG)>@2WXֳb>Ӌl9doL6;] ZGMg~](/Q\>qK<\jri8У@pAwz23R'סup|0ջȰW1z~[/ JBleAEbB¦ o&@HcXϔmʑֲ^(`ФpZW}z{GWCwź]C|2K { 1Ols`cga/tغ[݋;g/m+juzgR)m'ιtPeB𓊜('+-;?R|ON+u>qeSP0&Sg(7`gL;g~ς\a/9 6`oNsG<2\JШ{Q5$ 3&:}3OzhVrUyj}D.r2bX_Hla0Gmr& )1j>FRY,H|MR|M.|MhW|{q*BcP#jm[XU|z>+dз^z[^9h,|F=?*Crl,o*6PvT4LkP,9pstbt^+EWYѨP#Z8I8FTTW{^MA1R16FV0zFV٣Os茑Fޜ'%Iꐃ!~#W8W~8\,MbYKS:l#M׽aM$D"֝>|,^ˣ,Aȁ p.ۘ`ϜޥHHgYhlea٥eVP7^-|^lUeVuXRa{Tj6Yjj9L3ښZR2d_*TWvo"KJtO쬭i>/+|M(}+^;B 0=+ ᲀnW?3kj{eCm"=#7oz+'T OT2Whj2Yy҂đd&˦('{7-{D"ª9xNuLg)fgyrr fftz|rfeNAe`L2jZgE3e@% L.JT3qeǘãղX>uH9Md_Wp%b/V.[VYV8菧beSl6{|.:2QMd->b/^b% $Hȁ{KfB_ &_;ڭg 8njl=unJ֨J$BL"oϩ*L"T`Ot%=UjwXJ䳘i\jtl<ڈilN[4YipޣM{Oy;-ԗ|ܗ!{C/*- M3S=S,דM1cA9*%5 Ŭ*Hp`hU)h~!?s׭o~6!,:x|/)U˜2i Z"9lHG ~JUnSBZt 5q@D`bpz`! \dRK23/GM͔כ)+śTiy8A+TáZ;W ~دJE˺KP(RhYXD2WUSS[M}#plC꒮ЌXllC)6ݒE~,V7C3 P >cT1$xC&.5fEX裼]-unCG}n뱀)R}tJwdˆ7%J^=bhS}nݜ;$I0(*77y Y4by+MlIjE^؄]$T ǫM0f9Ba.pTѢP7Iw XC}[&FgZ4ҶUbbCjY[- 3*4* w/_Hv4F;<.>MXQ~8zRJdv<Ś`eV,v.e1kM)sՑڨ?@A cH蝼_(ҢcwvG8TY:;WGv݁dȱb xOf I'dgd) G@.LUλ 6opBJc٫9Ztz%52y@:/'.0 0&q-(xl%e5EE@HSKW uFAWӒo:uSTu,\C)G8ו^ݴ!,KE_׍{}`Va{y !wᳺ.NTE Xk"Ei(NԱg8}Zv<1]Rite>2eâ~uѓG5nܤmֳᇗ\ױSA?@lE~(TI2d}g購fζvv7>f} 1l3 S2ZdT"ႌ$A3->:Ov@Fd6Vh$F.bdDxFzG8sZne*ڣ/j զLsxbx^0~ |{(H{P,.>ɻ{ P*ޔRo8#U nQHe14-Xm@$i+{Dm T@+׊H[;@D2a˵[|Uwu γ Y'mi|ǺGD{K[Z]jp(FݎB(XUZC rbOV"S4mqн}̉FdD8S$+ f/qrer$P$RyufFD㴠ۣI b-\D00N #BQTtE!&Y^*eBP7 >(Ε 1~ERaȤB$Qd7//-X2jk׽eKr'xskkbןsk7tNX8"fjj-pz\01O~$>X&itbrJzXib}{x0j)KLL^!ؗ` p:7ò(<eeS ^1IA<z`Ⲍ`/t#^{[J9xUM %'(?[] I} h(<KwMՍ!jGIki[2M஻\ 圏!2Jg:q^gv%XrQ빛Ȫ5F?PLF06ԕ.l< ӜӦ,3.(۬l=~>}C?R -O;Qb\蚚e+Z2e SV8{C--=Fq(f̷簓@znQcԞGVdo!fRX,4489njkkƍkhWƦFS66S(A^ @:?HĚz| ts4gzMnUņS GӖÛbȈG,$j+Vebm655pm\lw!+b9`:h,y-̕KQOIU _EYrKqТN5 ox(k'eu$L@bSo&AE.py+^Z2kX~)JdR0֖3F̛ō}+ RiVlflfZO\?CN 5ͽUh980:/_U91+4߲MUʌe;Rx`j>y }aF hcmdTP@WԀd/PKxv˕XfHN;A;iQ6{Z/8ZתSԒ:cCգњ4/"L3`TPTa݂B@!} #]m}t1H#0Z*)b BɫBK |l8p2G,G*> > zWPe xAX"ڧ S P1)>(E5"l݂Ml)ހJw+ܦa,2!LRWEe'G1~a`oLES=WRI*Fj5ϊ:S1E=`0Twl`;p> 8!23z ҭ0p % j1[ek6p[3U <(Jgi9h>nx f.|^`A"T}  dKx?tp,ȿ`3jt=oRC&\:_8%%{eҙ2?pꑅ&?%q>^Kgxs&RT[U6S4+3crZ*lN18*U SKJ 5AO-)% &{0ǘD#(r{4zmJfT)uu>!@sTjæ`0GLz}G"A; P Z**c5Ǔ'OX9@5D܉ |꧱'+NȉhL 11X1N܉[QY }z§@o i3׀.qh*B8%c_VW[Aǽ+WHR/65?ey{o˨hZ+F37)桪m_? S ,.K$YYJsY+y#~aʀa&Ā*Tؓ11!H1%`KDމ ̕)eebN@E1'ʅheeS^a*/T2t L_UrU\^y \r\.L?&;1<KV۴RʼnREQ [XK^-dHW'~ԝ7pzF7k-6+ew@cn2plT rASv12*՞0Y-ߌ|F{TJH* HA&矷2VHA RP)z9RXC)cVqZkRRljPӡ&UCMnF8R! !P\̪} n%iL&U*ZcZFT 0N3-n'arRjYG>e"G2]F-?(IYnp[#߼,\Fh:n2qٺ-p\7kVB*G7 4zˑ~].&.v]0bBpYlwll,:\Fce%pEGT} K95kn- l9O^9c /'ο8o5?oO3&Ya~Jq /g$ː }䷩߯<,?~]~J_*?1*~ِ _7(ge,,#5H)X«tS@u!H}EH9/I|Q^pyhhpB:L1[2:b<ڬ2hX"55MB^Em5yc0tl_r@;z=g')+h[ݲݱM37Qw-Yk d1.-G0W#JeZ86.|;i`*_16*`[סgpK ~\7Zbӏ:Ia`hd?fk Xbau֓9=xTh` ?z+p3,dv 7D ցOOIΓot]4GTuy6y/q#3 n;]n`9m6'UH&Z;:8?H^ cfe Rp|q]ul.T$d@_yzhУf@t i#K||r9̿<>ϾN#8'mHu=ށd0[{qh XWtgq0EEc )V҄KeXCӈ2u2Z. ~%a_ ŁQBdD.5)ڮ5Al%-Yhgui{Cp˜7ާKQe 57aNE+48nT=7md&Q+SHd5,<=u@*hcrLͬkX5倻CIpc*T`yJ^=YT(r gbY_BfReSQ"!ûQY‚ǟfƮP^;]`h+XWXM)NOpNC44`Wof7?~]RQ C@aMV>oЅjUBK#ly3byKw;,bM#37VB&ADSs7 :Lq,|V*ux/dg4 mтǮG9|k\&ŭԩA}P/Eu/e6.Ct ]uq T։)p|+dKhM@ _hcじRp; z{tyu786궺7Y+ c_dHG#p Y@hX='ύ8̎ -]{OSx<75Q(oF8̨1o!sRdۚ|= h="7Gi^mohO7LSX0*X!{bŧݠ. ^XL*JVئbJ,FPw7\BQ@&jKh${IcE p1yiX:glMV_)F쬍Ԇ|Qe^oЮU߳5I87ݓN55UVZu矛*6]U_rYB2/džvd Q F{C'݇dg'QUńubd1d2{^`66 $\hOC\lj*k(X7o U].d)D6W59t\&w]\#Uɐ|VhQ: fu"y>T+$QW;Q{tX^b'a;Hʼn_53;[W`'TѺ-X439*Sqа^%˾9,BDepW\GCm*1UXiIѽ|ٻGFO#!cS&&$)#TF$QP%tRHrLlTŀv%mv0^ElSa-Fچ7D c=t}#zLܙDž7V K (7ʌ!j1ԇǠVX2<m>&k!lx4X &G?8.7X *.sYVGQ7yQg{=9h9>Fe-8Ϛ-rg:h ӥ'tflg i?q/=$5񪤢YAt (Qclrtְ֎ ݗ2GC뫫Q%n}ɾ{ qT[Kyl&}(-?޳#t1׾aJY,ީ=z>%:t0lϦ - a*' >Fl._U!|oO+)?MNˎ+OZ_/E0Ylh":uJMPZWfc2 Џ]W94WHICU+I}` ^z?RH X?Wh7J9@v_ ̓`t n2|ga ǰd2son[},~D);gIo=p]>#1'=;_dJ,jrAQB'$:L=]V6H%K<7Z7yz7>XrXiqa)IvK0G^:ia&^sj? Pi|.@?]-ek)e%LX_vrꈖO#^x%xknzc0oZ?m=Oߐ}ktaǫϟ[D[8'R z`fjle[,ĭ='q)_Dl.{ S,+^|0ΛݪY \cl=u"q}7ޘNi߿A+ XqK/)#W&x<3FۏBn~5# c>_eNk7{ѫ$I0V4*"&FseAc؟2̕.&IgDx¼>m  ` `^AR|q>XR8BoClp)0~D]NRSO(3!ӿӀ^_j{} -Ԃx 'D0[s~=Eg٨Dₐi[PB@FA՗K=p_\F$+x)ob8!jjEvkDӚ,#;TCRq#c.Vd7$FU~j4d:$U`pq&Ѡһ xwr}B>cX+3G<`W8 r&D|bDF:XiLT@Xbɫ6;eʥ'xtl~i] {1xl06مxpo4YhnV/Ǐu ْKT{MpDQD;L4 X PHׄ;_'WTd&o7L?8-vVo,\ ]w7//N^ca9ܬpIDԚb9$nN:-s+=OG%T1{-U_mSLqsw)Ι؊=VdNfĿGmQ%U*%7HZ^?Xo'z'@ M `&8Y(8UQ/rINVy!{DUo,'82r˥rmumډjimx IGS)WX'*WI+2UWJ%KEv 7P_Im;%.䍃2go>'z8-%˥~)/횲+URmC$,k=ixEU:Zdɒliɲep|@b)s\N!!8$l ga2s!rHvfof&0 l $n_!2rUzիWG87'W$F gJz5ᚂE3TuF^s+/0\ĒPk_P+8y4(^yU j5ޛ~rb{6%(dO筳oE\k. lǢZP4jZX}ju:,+(X9s8^]}Vg6Cad:muder! MW.cZmQc ;8oM)*K*XikKMO9mB,)2pE>^M?c^S& k8QyMޚqסigdŇ;䡟zHK]0`r'̵SW~ҧ}|&:Y:tr NNsrw#I 6qs'$]a4AlڥD~ 100<4p2ߝg; †jYl mU/Z|J;YC9{Q㬲P2Zt[Fo#wl=F*oجw~#?NtÂ[u|{ٸJTѵk~V-=?8TtӦ, La 2egaubU:1#Ny5d,QoUd KltCYϴ@a|1F^1y+^5r|Jbx+gG׿ȿ4火{޹Qי;On8ܚh͑敛{Gn#0Vێ0('Z 2jVTsZV-hwnnnfV;AvP1Tj 4Qbr}ˏ1Ê!1.0;&*gu@ePbCi)4;,%UC25Ehj1B֨iQe%BNv{h,`Vv[%Z8a~D*|ͭePք u.W38px,w-fs+G]ۤ :q2}|vuz/.OdoGL lM\"ǟ0=vK|aV7+M.GΪ [z;op;Yb K"5cʟ#T;GxV^?Rg&d'mO ;XG\b7ʶZUXE6XUri|ЕZto)_`ң'…WR2 {r-DdjơΗ9FwL4N0\8XðN2~:?qnF2C4`4w 'kN14!$WE~)#16UAl$LZ,رHH;!i5NVk>FɐAʅ l ITe0Sv=.n{Z6O:Jzߦ'7tѬ8(TrJǤҭkY.39תWe֠A27U/쿹 gW&OmBs/֍v..59X زpc=+>MՉ=~̊ǡT@O `U"2~y;K |=ؔ%17BQhXq*Kc}!@J`@^qYh\8͙ A%';'hsUm7NL`^!֝*h󴅸G6/yed=XIS1=h?nѓ 񩀚;tPVj=9橙 zUf+t-yVzf ޠ3Z5k܏"{XamE ۖ;K;cCvzX k˜ppȨ Oc ӴW~i'Fl$"2ajFM1E[(QIȇ0nyb@|0r WXVteǏGL`V=zU_9O%=m/ċFpu`͊*y?>t8rL6V]R?rU2}w}%\?gh/&?WAS`7\%};SF1#*+jɫѥJXL-Z)CcN)~ H2p ցJ#g052c _ .^p@oadY}h kl~/_1wc/31t p pb B g>,ˢY nD؋U;0dǭLm䥊N%|[ZZ5ld~aQc E|Q{+~e~` (G5I0Qp>f vդGi`Ԋ:)<}Se(uD._ABaϓ`ub$u`n QcLS_$r [0)n`¿ &)S[LbyIA^[)7K0-0TLRKk &xԔ``\bX".5`(J6VP ZR.BmM0s 0a$F hA^)8[b͔+6ҵ4jTuH+LK]V|RTW/&<=@ɂtY'e&/E`L_LSJ^!pZDj([4HP^ʛrl Pi(+M]OL@ s3-:/vRjDI@)H%C5FfJhZ@Tb[iMW"XQ?;^:D64NA aLi{Pi\کD-6Ӽ?bC}h-:(oJXļҒvIX0ݹ5Pmn#$ #BmD^+Wקdq-MJhڗ^>S_~<\LX^x$źvf3yTt4Qq Z>rF6+D++k)aQ+ӻ;%tgzzәܸQX^7+,KeS=pKzS*+,Nme6u-mۘnO^wUu+R=Y(T+t{O& }*7J_\.rntVhz{:Rz6Ϭz+ݛ{zAR[WGEGGhuSg msk3ݞʉЮ-'t + ~a[OGWƢ>aS/@;3@i ݩM^R[hI/LF{2}קOI a}c_$lF\}X3tm"A!i-I5)kE=,(eJTǒKh iȥ7h' vd6wm̴M &a52}}BG(x֧6vS#}х.{ӹ7Vt νa/RmtSxcA({B0b{ jMz6軘+D:.b`q>q/Å<{R)h//w^q'[ZDW4nU6G%e5RNm(kf:ߩ#\9'6\(4ޥ(E4zBJ;ʰRھ2cvghAI5 apcCaQJۓd1ăcc~Tx`>+T#ٳ%`F,-cGGv= 7Ng HGt/j~@6 gYsFx9lY:d4eroYxHƞc"a=_".<"%3apo3 `fk8tOV+s:Ãp|4L8<)Ej.HD P@Sʚs(d|`6SHIX1 `TA2`rd>sAq3_M}[׬kZ㚖f~\S⚤!5 D/KXiAs\'hkMY#hMRgA3_I}CEZ:‚A!)c!rc|(@'B2(Bf7+ |2/G`LǑCNhƿ"4>ld !2Ls07"=|o< z=RF"$yrGyȬ!Qtȿ? }9c#xGC=OF 96rGW//FdT2>Bp\?WKv2kP>ItxzEQ=ߥf(KbOyu\?'?s5__=W{h^aM^AI!$2/~).pDX9NVv* er\VFNNqd!H>["ۼF e1g t6MLSPӈrlpMiX0ӊkGMk?7{FpW= 560sF-+GIqmX?g%\p▻l$lVT_o*pɟrVgv Լrxu8J1Gkfaʣ6Ɔ̍$h]ye5.#xIm"y%wMc"yH_j8ͳqҕ84u*1,uϢ}Z<=Q}(^P+G/qo=-Cr®F"'˓ݙ H.qA&K$ !fKЊ̍,e}gcÖkZCtC_zgz=IT6' Q6B>> endobj 66 0 obj <> stream x]͎@<a=dYkɇ(<TIlt|Lgwsmcs׷S )\>q]3/+od1zjdmӦNS}0u%}=>5s'uچsאYx)>cH֎(ІX7aKHVyNW: }^)L9C] XG-wh_ 9tICWW=ta[;;}ErjfG~#[/ߠ~MNG~/@~}pʁ_rg.¹Bƣ,8W_,!_!7M=W+j Wd}+_Q_ݕ5J*+Yޏ.xJ~{!^)=ay QK41du};0"~q endstream endobj 67 0 obj <> endobj 68 0 obj <> stream xyx[0>3j׽ڬnK,/qNB0q;q6/IaiPRh@[6CqRhi%^( 63#eG<2s̜Μ9ske.d@=[!@[_ci}+-! ʵ[oXb!4B_յt;6 Q 2VoQC8ëm3u3Bӡ>ymௐ uKC#_zS!׻a#" t=Tm҅Y ×~ 4M8^%5Z`4bNۓGU$f}y-XgLVA8+0+ O݈Ct::O Zp1ZxD.Dp %@*C(fvdG3a#ڍJǸ]#h (5]xG:&AOC' ,C Pá h;zM蛪]J;x]~K't}}=^D-xWMt `5B'Pى'# V?! uSy< ̊=wWpȄW aЭ0x7g.̦ -G[1|%!Չ旆@E?D/?@kx>nqb6ȫ%P t#}8#EӡohB q i$׫ƮxEa 1]֢gp+R-|lqg/!zMW+nÿ&_T7O\ MU0ѣh? q9]GoBn[uĖ;PduAtzBC@ 5SP;erW{UfՏ1~ N)Am@*0|_Boc{Zg@KKp7>c|?%Nr;:9@^!aŹ)܃|zwgDΉoM31V!$5t}x#ډ <ߋ~~rw}H F!\`vx3ށů4A@J2\F'Ӝ qMܕܽ/[Te}Zp\Ѽqx=LT, yVsi4dn t < 8-(@{;]6^V$Czٱ4t.Xj|=o}9 $i"SaFR%d9F;7N̜p-Jn7i/`TUKTUR=' naaXPSWշTPĕ\h-0GQ&K؅/@vO[{i*|}@] WVg~ΏmE'عɤQp+ZXxďIloBp_gz +2?{/@ GC‡a}si?k{}|j#w>E`9Lsϡt7AWQ=jBA@3.)Gw9;pmd{1nz-|֡B Q5b4J!:c&S-R%,lGA{9@;h @#p8q4PT=ګgB)vC'_@')gZ{5c7Xz{2`1hzt;G 9:%|:;|9vfa7@;ހ g8o؄F{@ώE`*ux rJԎI9{ :w^'Ȇ yQ}LPjý44T͇}Q01dsPThieGM`'v0$9XWP&_<_ilT_W[S]U./+-I'XaA4~]NGf%d4uZZP%vдiI-et!BA'#_He(,rKzT,?s~ǔ"(Foqĝ+VhC]dڣlۃ !R 5Mit r+.l %qвA<(& jf ̓j֍S4a -LVV,l tÜ~ ::<- _v8{4cvஹ / x"hHkVv`y~ܴh әYej9Ъ;ai;E[[?q [;/ =EKﱡmr)~ׅ%ɢ=9=&1#]g)6󢳜tD ~̩F]hj " W j;wH4TE$ 4Ʌ9Ks9BDQYQ3`"1SQ7ÚX"Yt0y0'P;v? |۰Abp܅ٴ-dJ,$dLbZL!jgReU weg ͜xeGg3_ʖW-a慜0X)egiba? a`9-/f9X0]wAvp0`>Jf_cV@;v;:w,ض,B;=S̊O<gE0U{B{|˼ K2a`9yў0-r\xV aE BX)2Xz0F,Os&$'<Ѝ<KŢ$p竨SF48S/anBZ8x gB:U?V?[:Y6VNCTZ0p>Nӊ {'~X,k(P6j|QzEcW z^G0Hj`  XzA^OE^G@QqiD-&&шI|<68 g1@g&ub^-5k_FF4ґvڗK/Dy~8X}mmN^7`| ָ['.X+S-f8[uW9 m-A<'5/TJ q ӥ-UհUsm4)msF^u[}>qN66NwE ,. ͑W^VUYUiNG x_7t|äVmш{+—^ljmdM%8Vğ=XTLw4 5).lD9ˤ'06)^~q:\"[dr|gbO\; iKyYa(vclBei-,{꫿4ҁ:k5_u;1CWʖE`u.3N)'3 I5_)Sꧤo[@@gtfžcgK<x+y⃤Bݢa^ѭzQx[}o򨡽ay^gÀnhA|AkoXMNh//;j>etEH(V_tr/TV~mgh4Mf':,U[5jӼFx4}fpNcTN@T4Rv/HSzt%^΃NQ'NTLRId5ыErQ/k#2Ji[AZIK") @cήqƒ= T%U2ЬtꄊUSū\/vқTQ9?ٟaГpj=uNKM"TFQiqiMk9{HkzS}=nx`@ IP"&eյ!b Dњ Zj*> BTbVOd?w* "]HGBjl.g S/f!KU^F?}Ka\P ƋXft{|ek/m+e;홳^*8reVZ'NjsFos+CyXHT*U`Sȩ}Q4 ށv[bsnR=v8FJbJ=1 .E\qEpH҈tXRIԲ[c?@Y 3qȍEkRR4%Hc瑞quI5vGx*zn"hH`CF<$D WpkU}>=Ui5knҒVVykսaEL.8[ZuD1gQTyWTUo0늚j](fՕO/,@5kl÷J*GZ=$2έ{(ڏ°*ͬhcO?Ր74U*$+T'eU($ek( PH%t.^G #"iAT!(jj!QR QA!D0D$D>"ɜ>$`Q~@ DBVMa",4E fbhAhBH0I$lAEM3*e@z&28+4:gNgm7t^*9Jj3KG?;8K-`Ls"U,ɽQ8i͹:^Ѐ,fh4)5) "Gb ϴR]^*H9N 4bYg˺| ah%PrXB\ qe#PgAEI/۠-K`MN+Qu{m캣%%pۧ` tX7wgLBSE%>,"x<˺,t ñc1>J9@qD}I0ya˩cO@:9kܫwss9vI8aVz^LtPk5vX|>.i5Yq U:.j5/+fevi)7t{^7aܛ7 k"|ۊ hbL==+PoT K| |'|jxc3/-8I#yvx#{`,Iv["{[EB\4f7a v=KM"y(W!=.rbc@L„0Ȇ=O1i;%y/7!9֘dI(:{g Phn`)pֶBGK$s~#hc[ v ;swZjpRq\֊PbTПU++cn??xbxOWhX)W'K^bWXW*-I{,!j^"xEQE!|HUQʅ*9x [X/AQ)JXRLw5aD!+jq͞?m[ThOCdIt,ܱH"hbGJE9vS3FTG?HD=l #zoٯƳ#z.䧞`A1)/:U܏17vo{Sλh/o( Jdw%)n*_u/ ϨZ3^ԡuSTq`Un~swV#W-Y{NzۤQA6wκce8U*$-U>l02|+- {@ [hldm5zPEJ.-oQH̨ `|}D)mJ# H̲ %`MEM==kWBưlލ$otb"QY/MR R`nRBåT)m/+K-#hQ Ġ #Ur݈!{a]xp72]dFJ9Fڲ#TG둳B9}H"DAw' pa~]3] uaqj:DέѭEFVWP_MCu/@1ۓl/-SyAQB蹋1+Qݎֱ?RZ>}'^meU U5Qiw 8:w\=͟n{UO.SqG%/+3 ĝ/>\kd-g1䨼cu|^w:4jv 5v+]Ha\ W۬+$Idck"JZQmuˮpܝ*y3 \r"+}&0GYr=z&E.Kݞz!ťԾP]V{{_Dq`-mkMnlOymgo&$ - qVK_dn||?b|x݆0Ff4ʵ%(b(ZxkTRFbʊpHp9ՂnWH=!='pP󉍇`Q_vz_>$Q'C?Qc1Ndv'ڊx0,} f 9o{@o7Q%S.0Ϗqǿ*ӑ6SgJ42G#SEϗkS&Ցpa"DKF=ŏgg?20}h>㚱5O05(a-QuN?<ԓ$nKJXEwM_М%D5*5=J♓VO&x( xj1ZAXpx8~d>$J-^ȩt#?nJꊸ~^%Xv\aת]Yg*YYݫtTt:k ѹEEäPY]k0T 5V%䧂W{F##8,El"o+o^T&`4m&o ͈H50}VS>ʧ!OKՏf/.HuT?>`D`~;~XUL H35T!Iy9PGsMr.YvyWL?̏Ym%?z|tA$b75="w$Z H>zGQOL4# ʗ͒Ea|܉7 (ytez7lh|8%uZ !7Hbhw:ziw 8gv,I:R8V|>"3yǧ|;'Z2 l 3 ,ʞ~̄^^2emZ|,^9m-PK!ҔMR@J{maYFr ԅe[Y{ ,'B/&[j0^2tijgcv^mo;d#6zikS+l֦TTBTR 6zuk6zkk U('$S\iHiFd~6MmOD (NEGA.l h6]Բ{Z鼋}Zx^e&=;/3"9s[+3_"x[ }b VOqvKnu6 ܂ dI(/ș[fOYײڈk9޵>pZ}i r8, 1\Q}f/b;9l$轙\^_6[T lyi)LhN^C1+pò)ǫ)PXQ;ҕ_(bϫ;yxs;Շ+zx<ZA&I4?͒ FA)Ho[ҙ=[dz{;ftRn ^}A3^︽bZgcv?VRI .Z=_[HnQK 2ҩ?'v33ҸӍxs=gEM-EP0c{6b(:\}MfT=WkS6a[LTzNzI75;--?m콍X+< lLBW9}n@g5~؂J*hCE sJ֩D۹1E m.t&C m%OPLqa L7C$y o)Ƽ1GiG> PPH_cn?R*PlgHOu榊N@SܘR"D0JFTH[PTAmE $8?G}|"yP?괁vUMrW\|] N)Vkh.hy)vkɤU%'YS=fK*q~|ۂe%SWW_|(@M܊5rحB.~F (6ZZ+{nqn sx1+1Q4mڕ+t{X m|χ^[g?uÄ6-r0cQ:0׋8av5.<5ܻ#EH$вLp_a"}3@ ޶Jt;9I(<>.7G%\_ x?3!]*[ +N'{XGtKu]Vp8`z f vzkZ\3eFX(q^4]sت0\[Ow}7(w3GOSlj 2%&^1d4,hJH"y%wS#zdOv4P$u)vQpNvG򤝾XPK}4F(;00> kc72Аp@o(1l342 :zp 6)N$<^6go$a Haҩ\+ðtɩ'\5إܭ[ }ngS^nGmcir ~s՛gLJOx\˝8duYKjeɕmYĒݛZ͛8&c(k< sSJ;bu!.mA!f@VW77s?E름ZcJ|{DžGO_4arRω}y`l~>-.y2ᓱ$NgPUA-2Kfbn>wEvI K+]z|,y>Q+$}٣m]D,Գ5{ԝ/q[؃ܳv] f-{Z4]$\`HD B2/A8ibNd_EbjE+V5BJqFbژ\-Oo@xf2-<9`9%ժö1e`}RӠD 3mPtICgaXS[uMNF{SꖨWdOKct0Z4z=yzg/ "䁼6y2| _>݂Zm)D [q:2K%LAȭ.{w\` @ElOC[||>>0v#>❈6Sq95V }EC3 c(ƚ4qP f>+fU5g@Y@?RZ;Vp﷯#\T献gpdmS<=o||M֒hAFz{dzYhcc#ΘV5aXT1R4RWBT7)ve" RJӝFl*`{4/TA%\F m7s)6Čo@ TYʽS2Dd"B8 Aoy<"n sǜODPT Qձ  pP 9K`rO}&sQ՚=TE0Kg${&˾3(h(?񊟕4뢮+ⶉe@sWtL#r]R3gc˦7Eƪ2lRvXƥag~7z&y1~ S[%g^ ?~s|{{WC4Ka%K!ld^4l<:V׳.TzamWb-Y۫ج^ Jzux$H7,6Qnfc] 90nZ4yv끗]P+mr0b|RTA_i;f7kq#M1c\;÷eWg8I e9k1Y_!fӔv9w F V%dW-WO并;3evF?eggZm\:-+bV>/zZ=KZt`_N߳޿.^߳kƥWzP2_޻iƁ yi4e`+s{wk@Ձ zog-Xѵ~lQ&[6tx`ݽPtk`]F:e[H[.,7лbtW,_u^]=뗯ݴnз:A XT}k {buhsm?COW9tmV-L9{\[ul=Ʈu=.=SPaήF轢}6Wt]A 4}aFP[65U_v]HmFK띣fT_Jn^^B\@SkL1ٳteg\ 9?֘8Kkkl-hSGԅgِ;zX/wUBv(/_VU^@|_7|5|͗/V9gYsrL @:+b3/sn=_XnX~;4w/?{yÐTFa(C~Ylx  FK p,H-+˕aY> Vgr 'FxːYFtmj4m,.W'3`V0;4%[kr6!G\[.7!퇠@胰 ތRvB N 5M%(%$CHAP'dk+4ƒFeZy?4 rCb32Vq痽s>Td<+AɓsHeu'ˎ6x>@xc8X!q$bLsC zƆDk$qEAh+3R{Hg*3p >C phĘ!km͔Ȑ,koqx^~BH~_^CF6R6 =]=}yo2l?˚t5d׏rk2e]*'CZ='^"ـ8P9dEn=JA3v6a0E1b h{ۆw|>cGpadh+ 1 Me#MZa*!ܟbV(w;*@>}} اL| K)SZčB(ФP AyhrK8!²ܵ5 CW&:k2+#nWTv9=d`ٵW5x]8q *O e[aC;!%8 o2en1<=c*_ԧ1nM؃lSs/f<P%1Be2)yn&nvf cviCյe%ٌ3r(ҚfyHg#e'r[e2i-m9}UUT>)gQ6$Y@WpelFe.xXc!C8rD[& pP5\)jp'APNKNwB b  N 05:%xm!C^QDaq~4AHF[}J-ފd+ߪ*m5kHQF4*SۧݦJ]IZw#Եu#P[vmk,U;jrQA!,AJl5m;v6{G=Ph$yj˪0/ns0rwr̥FSߧߦx9Iד]A^5(c A.t }6aKduJݨVDS3y Amx'$V2aҝq;BP BzA%4 !7NF00Aa|"`x$LFj6#0#lGh0![-{ѽtgy1La!K(Fʄ&yZ\0q#^)yb?TP>? ,g`.[$!4/3ޗGC@dX Ff4 0LL]U{'(/l&Yc&gz,0ٛ) eA&+FF}?⯳>dkJxؤ#3PO#VLaaa#aa> BA@q4g\TxwxY87hM h$^Y8~oƟZ??yjb,x.mFo<̈́/͈H{|)2rLA @- ?i;6i[ncE&&GC!Y/ka<=LLw 44?FY{%Oδ5s^Ԁ#=x!30DzL\Pw2wv83ki{B7Q 6gh }L[54UW=$w8Lw&ҁ Ye<5FYJi2DfjxkEK!\};:Seچ?->(ߍ?_/EÅ66ؽLZ~e' ڻgߌ'{t wv4tS||}:yƶ[ qWxv{ɫ`"+NWJyinyl3ٌ7iɭ0(h0:2Z\q,桟W@ (_Q/SWO@Q>McHƠi4Aki! Q 4.Pk8ZVn&9o`UbzAM `Exr4sԼ0]< MƃhN $ c405nc?¸;<tǢEwżMQlS!%d!cDN0بCZ(""#\!UB:'dawnE&}xGݹol=}fytm_rkoS~{6~V}m3atrEn7hԊiX{ BB[E4BROk܅t@L#0cs 6@ʘ|&xFq.M7r[=pBs0j gnf}w~8?eARL%"X,w\+eQYV$O:@kO[$hiܜ3 >M SU <-Q0|0[ⅿt endstream endobj 69 0 obj 18842 endobj 70 0 obj <> endobj 71 0 obj <> stream x]n0 2O /B%ˀkA%GSr@Sb1]BqWTSRdO[PC?+Aem׆s3[Ffo7;8a=6^ endstream endobj 72 0 obj <> endobj 73 0 obj <> stream xԼy|ř?\U3=LfzhfHYxږ%d#,L, 0#06+ː`#]62 XC d ήC :,Y,Tػ;>G=k ␲qtBغv5'[߿ko/CHCԵ6m]O d>de׭ixFF(xprҐn돺Yw3lڼvGz>V_G5B4A^.{? ߍW_M^7>۠ AHipJ-h:h2ppU$*du*]jƦb󌖙%e9ms_бE]w?=p.D!8}< G ΨD+Np6O!=(:k+h -@OY ݇7>dB[O"hz 8jG.Bѻ4N@VxNGNTtCx^G8o55\(1ul}GyYPmC@VtP<{ z߄?FaԇSW5T'ڪzG{m]xlꃩ?]OZ| תڋ$C jz#zp-LŧfO'H ЎV`4F'߱pY]nm'3ŵE\0Z.DK.8Ytw<_W&KS)P5A/;Nԁ7pU5|FU7q p:~ߓmS˧EB ]Vh }+(+hTEP{1<.J(oC/-X^4 xޅ].Q0 Fr7TS$' {#h9_0BB7p m32́M;vnFuO&ډ0ע(; I|;|LE7[pwrqs?TUUO '2E 5+Ҩ5j ݂v{^E{})|Wݎc7~_oAHR"l q9N&q~n-Q0.xR1OuIO0OXٙꉞMI&_Բ~ՠ t;r7p(0z 78ԐVs|8:Ep,c9^joc_÷x8>> sy8~?? b5$N=m%s"r1f8 _I,9Blpn7+[?x§,/7oPTmGU}zRjKX#$%Lid@CyYj|0bjR$]]9]|mK n4&'y^B> 9k%j"Af0%s83D_p !7z)bQtF%?E07G7աD9ij$h_Xh邶m~$UୟP]%Yc(+wmL}wB[^!կ"B&*Wt){Q ozOC%@[觘3awyzx9@O=Z]ngrfw.콨ܫa3F޷^|7 ab En %ڧr.ђ+mdvd+xwxʑ&\ |sh[(+5c9 {ר@fdr^Bk|M>zelc)24}}LOqhbgֶ̢y;˗w,t\[jWێ%כ^p /H͏]Jn]7qHO9E|{%gL3,^V3_7*hY GľyGitE_VHs5ϰ1ұdΝXw\=:5&"Gn{g[z.H=ЉH#΋++޹ov(\>">RBKi!H4<fa}GUQXf \&N(e +?Kϥ6zj('ҋ_Eiu'#GɏrH'!<%NHė"wJeBtKD *AZ<Am.l [dGg$n쌢B_4_0{(&lm0$eCwk9^NqN緹p/pZgI`FD} ZϣQ*(@Qn֡]=FbJ֮%πgYpRWᘶErc;&nHֺSзT`bgQibtK㟞q\VErA1ikƣ:=)<Ћz-Ea:u .5B5sAQcC#Ph懏m-^wda\z񛻪>Wr2o}0:ၧ쇞/yaF NrdG҆8d0d)2or$B"P bdQ L黎CH9z=*RGSҸwC~j,{l6ۯf 8@AmBm=7jK($@}W{xJNVbFz B?izkVBdr")JԱǠG{{Suc>c]>ۜ#.8ҵ.ׄZ 4l"QϊWg}jvsk{WV-h5cz[ݰS=]-=4f4лڗͧ m>[=uBYРm'sBKдvvxv۾nTsH;1#9a8k  2@c:v0h#JQMYUm= ?`/BQYt/aEi _ěۜ>9Ͱ44h8Qh' ZG;(]qiŚ3).LI2qLD[4[;p`psbEhw %l$'j>ف{{RN ks55!k230X)4,mHѠpjEi+|kӕsZSLڢC=hMz:lS*]"0uN׭۾'=_?vJmX|+kY{}1~,&@pV :S-}_:"p(Gɛ5,% r6,TB>1BӨGE$4JRӑpZؠ -6 @iRxXdSsFGL]gh |3OoZ.[~u$]]MJ2Vyfqa\ SFP݃/#( 542݌ܴaӎN}rH8Hh)ːaZ[ktZ7VMZxFS\›0ԛKZ{>@]lmceJ+R)1uF+5C0 svtTfQTQcޫ& ÅgީF#FBSFBYqڳSi)$>;H/В5;)18ұ^=)%QGFOEUR+JD)󨫫gqSs9ɕb%ֻAۂ*c2h] =`xc CWUU7"G1@#\*pW F1VRE7-64qSn@wǚ="Pbd&} {Kx@iY@0N q'g̨nUO֌O+ U -3&Ҳ?,ūOKs(>?<"HīfM&M?S6kp|NH0O2tL^ǎRtuuM=P2.Wm XXDu -!4>{U:.@Pi\̽Կ*oqwZ [O}g=kN$n5Y`]n+t49,!x ԉ(̲]ɉaJPX K Z0ESacx}36)k;i4YI}g!^de Ȑa j^{; &ZRԊZnj=BQٸwp`b8JOZ+Q86pufށ`MMM@1 A$>ImE(1%[(A_,2F\(_!4x{Yn0>k3}$2s=cͅCM:c٘cK(`c5CP+O~U,WADcUBH 0pF3Jos2w(9)&Az+$hu' A@M4ћv=I?j Rt$hVᬂSWhM>W)?T|?5sXV&`^NS(GY4^uR C^ZҬ監5J"'+rjh 3jXA] 4Bod.f[)COi.(MpU+ +,=zp@F  \@LͣYT%*M2hZ $QΤd"Y`?YlҹQaXG4 ͛^3J^T|| ZJv%I~(9Ir()&I vg}myAHD9-X R pj^p.?V* &Y$ :-Ee$9Mٓ3lJ^nT19^kyq3+Znܺ<؎̋u7|m2 ѹy(n$5̳Z2yy^Rԁԁ>&n񰙊xuVaޚR*IUrjs] ,yqKVDAB QU,Q[ķ E|渆vʏX;TJՍ*9A.xMeMR5u^́Fx,T쥧xhoIb5{PNcӃz,eji9+b;]E9lMkh$u/B.v5mWO:jM+4%ks΋}EŶKrMnoLě+??RzN**-ޣݧ% W@ќ@V92+5f VO VmDNbW} pȭt"Y6|9x/BKk ?Gf|9rB SLQKJ1=W&pBμ ^3o'Q|,RtXV0|>^ LrV?m-L&NlǏ}})Hdjo z_ Qdh)fH돠 7 ̵k|oJg [EO[{Q'.f\H2+3Ck{I7TO%Oދ'ITW"iU8sGP@JWȢDGut"y@yw~Reɐ= Icck`k*,BL ^lxZw*uaYߟ(kTtWE=l) X\Mn9KbyCTM̷܂/٪p(2 J3PX !LeJ1 @I/,?w7CBD.?Y?B~l;9kg.l|pmK]kBiYn ]m77{HĀ11R+E}jNkt"bLN a<n9 MrS[@8)(~Kd=wݳ|Xxda!.l$2P@GTG/T?HJe7 ~\8è%(=h}#o0]'Z,vE 䓵pOY%U2ekL|-K%i#8xGU܌LgLs`/q"enc{CŸB*F-RZn {Z#p7βs.}N$ٖԆT*ҧRSqO NQ.cqA0bQ4J$njǍZ >,Paj緸Th$8:yz_G'e7E| AJq_j:4Qkq_wzef6a[Mo{] /N?<HLk]F^.6groLV]Smv cj?f ?6P,Pӟ"ô@F~wїE@7 amg)KFT8"kZ,v; )a!$TQh6~ (< <ݻdUq>7srq.j,Xi.ΨǮu ].\}~װk/T ɠ 'xdԠIZph$c~e㽽c ^o Z0P\WR x9# ^ȰȸʰwJvnp{ݷs\\`h盎qp쾟!(TIKld#@*j!iY8=AS;*e<{O sr$Qqt죾hyG"ueH/x|"< tWWyW33X6j-v^>/v'mT~bFbЕȘ=c TD/҄b<ƻ2*˔奬2)IjuZKo1n7c$ UDDA a/duȁtv U[mw}BH+EfOxKnKx8 >Gx5AazPt⎑V7/^"'345C\Ǿs{*mllP{%B-@f% p] ب OAĭ݊Zr ;u_^/Z>80 {b*3n1``IAǿz7yÆp=_[rݾ3CO_uJ(͙:ɫ@. QXWRf˦*[NERT^ba9[ϒsl*!Y# :VH9&Pi"[u:vzBV}0Czxtlh!C:ɭ)+LaS/Uac ~o8]2, WDιs볔.g2}ٛT;XVPCYjGjjfIA'`)ۨ[{zoV˞JIBRmKHKM GpDxZY֠m#wsBpO;ب8q҇ L5:C}N.v'.5s>3uku[Ӥs|b&e2>T1M虇 !ViOF75\jLƒVeuQq _T_j 9JK~:E[ySFlW$<ݝ{*;xXf&L|m }!_0|{W|g0 SPmcZ#x!u$O,VUb86#d!XdgYFBSkiО ~)Tˀ(dބ 2R&vT]1%k-tsb[Yo9gIezr p DLQL͟6du5<ҩXfSZFHUj Ų[blme~q6 Sf+\sbN[^ni( ARcعKӲK6ޙgԇ >o46'ͅ'i&7S]9ھmwܼ.z_VԭO嚻',yH*X4:]5tjwy%m`*MKitb%q7TȦg  xi<;\ 3azT<=Ϗ3(|@Y c8mcM*{7iKP+61zfkxš7E%fPɣ(W;,i<#]ё^rEjVmDž5s3=yejDjAU$xxQ<k*Ӗ6Նt:ҧqO$bh퓤.4ԅ춣 5SWY-[J݋.S?+Y?+$R.g Q# \$5B6HV9Ȭ~yG#ϲ+Sw6~i Q]@}ٵ`olE;/ ubǤib$qtu3/De\q7#ɏ/e;5=9i6G/\TZwn"iͪI%5YW|),XcJVgVñRdeK.5%\-N.I3Uj ʖıұ1jn=*F<\ 3Q#TGIdFY*2ڌwʲC=f5jӂU;6-8ϼKps ?׌(c"fxٌپz77RGkY8aګL1qI?ϩ9eNLjޓe҄؛YvgLvdgWd *P=Lwv}RgBpE$bGށ3OL8}h+ e‰'hbb^ˎ];)X_enx{jgڸ;-,,oa[Khڷ+4eS 1C@VyԍbtjQ|s|['t, 281?Mbtw[G#VGMf=s2^ѩo(nޚ7ٓN_EQt{/S'&ġ &۹@Q5Ո+ɖ- Vg%E+77^_ߥu{Wa[vuܱ~݋F#7[y|剕V#/ '5 J> |n^fjdlUj'Ke:}=({}K2'Gu bu{/Q=,[PWq/ (]@iJ >5mo@Ի[q(W< tY yEK0D-pI<is珸ʡ E唐Ûsr{r\Mw= sbZоa@'E;K٨PQBg^"80ߕ0њ鉚JgZienr/j%կ7ԯ4z3o{fgM']l^; t;T뢶%\q]0DPg=zSixx|(uwS,`I15ˤ鞗Ԁx4:mn)hP$݃i@U-EKd(@ME6:8([oX-.7V|m}-[ձe?QGSBqIBJ~UGHxݏƗfT@ kHcAA!`Lŏ/^GIgKwikWIe,LԊ.#D+PoHRyDu$Rbc; E  Adű2qjgN]t9sӡp z7_/^Co)SEXnN}5mϳu/|:_oyTQ.N?t+-s*⁵.kpڵPR} .=xÞܒsљ;4 j# r/w+xh`:IE/|_P+J~fkJ5k۴7\u>!ޣ9S|V+zU*˪&qes$8"C[Lq?&-jJjJvZ&KEIbbn_,./7(]Tͷ }E:KCP65ASH[/VK,Klj9";g̾".^1 DtjO`Wf[C镱X&Sl:GI!XoEv= >ehbDOdxJGA]8# Ba"MR.a""HĎ1[C6ljY'n]#B.m^S$x:}0d ᄁk".fQF̌0FUWe3$T?xӀu/T$&ONK`+f2"p@nʸqo@P]q,QA衲4{ [WKC f8 ^\$X_R4#m9n-E\Yd$CW-L!baZ-6&PU2w<E/0h1|W5Ugdk̗'9i8fuT[[s=@$df;Y.+7LirhԢw/fDH΁f;yI0;.]ƄU(&L#bRӵڧk%LkϚ;՛hY Һpp #PG0nOSl4Fꥢ52Fj Ѫ]g;өkA4WSR~T]}OӪc*zftzumRdBdEK7/ݶ[L=-BKZU^)RMmA5dř*EXۃ} <T’w\ tq)ŬD)VjrXnBjūF8@,7v{!pᴏ$>gW.>wq|Tf݈cIK}#gGnn*z|^8'7SxK)t3ZH(:0ʙFR`n3J!̌,wZ\:GlTɄ e金^P*an{m\^ $/8 1IErq42gYх C]dsNt;;{F mQv}p,G-]6CTbKf%@tq+cF9~l2WX̰ jLa[熬 0˖ T;[۾YWӋ kxOI(@Ť{1^-u%P=RRI$ǒǓB8Ekw|i︇9{.OzA xE4%Sj+v,ˋUg&jhB5.I܈w(M 5n˛nSno?G 6F(Ή4:uUi`Y1TRu]6~*gYG8@yFGy_jjV^bMxsLsn}ZC~*$'B>S8 B@U gDIhsQC$" 3Q \l2a4Vj?]ҶdQxo Xio85kѰq0r:qB0G `oLF#([ְblz-zbk ZZYb)(g FBrM$ǵA2Uy#A?U},kg aeq*щxϡFq볢1xoDv%軤! 3(vĀ xʩspRV S#PtJ=[?VO(b{Fl8?:kdL4yoKt`4c:3 GѰ*58׬A3fԹ58d a>3c;u D@ecyc83I#olw~{'?ٱ6x-׻FJ̻_h}q䖧i?iQGS 1+E=AgU׫DCO }_[Nos$ZwKr.H\S87?0m (ZIKڐh7 ^ug1o3,5wgk_ݻ+ٽdl @+@C HL<P>|T`+_B*VV}I[Z->;3w~~n2sΝ;wysƎ88v2ն8s]z# X"d[q$FY7gϾ}7{o ~wof$੯٧oŸ/;tiqO\+Z9`K'R'REGCC3 h4Ay1_@M->q+|$DcVn Fca:KH/sWRclw ՚'jZҢ& y#7Ӽ6'(yIu -r4F"DE:^t D40H姏]%=sC(tgF?$k`5T/~|l+Qaij@36b`em>iQ3e9K\6b0. `Uu1ZNߚOOb\lƈ43节@4[4bgEyFO4f|Q7B쟀b兵0G0m'*n*"EqI!IBџ"% ZGǰǴ+u_E~U1&ڐ.׫ݤ{TUP0.|Xk F3ꙺ&433<;X.W/r. 5WoRwvߥ'3}q"1Fh2xE[R-'bUcr {k"/9pCˡyO0HTgƘd N*>yo(R^ZJ ! А ;=ؓ uv8CD,HY34N*T5G" _AI1#TZP~"NäZ SdrE.q?+&'\lsioz}<}-/=M&(k֬p p{: 69"L0[ \g^vM9:GpH.ԯdȆ lceM^~c{Ftn=h/ɕX#pF2|4dAZFn2Erav j9p;&ּ&F{ƄxV,`aZMtV+ق9amt}~xÃs}Y۳ݡ٫o7,EA.`%fL$p #d&jeRy _nF}:+5eb*=6 a QD",['Hw1ӮÖ:Ư$s!9%W&6gigkz^hptuPS-}}1ͷv=~Nq Ik:>ui1l/06A"NHDM& eYPnoCI7;M{juܑq@8{åM۱Vg8 .w\q9%әhr5j`LiSM \PO{T -ݮq( cT&٨*!2^kr=t4M3yi9 ~~6 Grf8Xl#p|F8I3Z{gu7* {vd|nT@8B&0QyZ+k0>Pӏ,PdԒ%Ay2FE>\)]X5P=Q=JaP KTV`UQ q&ϴ aQCoI@]D{lFq< ]]ւ0h*fYaﲸՒl*]Qar&Ľ{_7s6nW7ZvkgPxK (ˁS$iS᰹v~PfҾثž]<>!Re# `z-߮IY%|.wrp<$89X a>q<OP'p,ځD"߇}$Y#~qq|~gZɲl+gQ -ƞ 6eNxe՞3JzXtIP+76r敞'ʧhcli :7k߹y}[N\dMGcg?~4m#kD*D_7VW1F׉ /Ѻf0BT)@^)`Hj'ViY5SaBXmd71WIJ8=pRwn54zQx}h]&]('D%?é%)RX vy`; ){DKި3YiLOŸXʺsqƳYvn7ww{no_~11c,Ǟ_7+qǞx=T*x 4[_`w[m3Yݶh/i4RiȖOfN3^ذ|}̰7[:h6|PN՜3F8>;7'T4%fn-QkQY#cy|vSyBqSՎG=FU}(u6ٖKy)G d9+r8`דp&@WW0{r3Xa&-:yj+g1$S5-EU<cGS8p'ۊHh|LG,>5nűhCf5r i@Sa GrMrU LИm+B-)vԇ'F!S)*VZn{9i4(gKQU9I}4S3]$ T*v*8"SƐ1" d4Z17Y6܍5_o'O &_maeAY!jZ3g{ ƻC93Ab #ڨEYaȡb|5ȗL~ňc}x#=>k.q; ԜonrRhrq0⤉Ta8*z?_{Ģ!V8F(\aJfmTkG*Oꀁ,YQKH9;ϴƎ&0wf㊉NYT F9rE-fʠXP_2yPLVt]L 7."qx-9"qFs)WW[\kek*i--nu]}č;cv=wou*x2v,9(b>KP_t=֓q EU$g0zlUkBI0y">OŒ3xlJ .ݜc{犤^ք7  h~mVBcǠhc#jFV6`p2໲wlL-,+g?y{ɝhlw=(rj)Zٍn.['\ODs9d^>o>^Q-W=iظ(  hɾR9]X^v_퐊 ␾TdmeT!8|1^\1H / WTTVRfĊ*Wu&9a=vOSmojzmۅvU{jsx}룷o)qW-j#e@eAr%(YQUIGiM~QngQҳ=) ֕(>k=*.*@iۆY Ns,jra$&J2E%*z@`%ri|0S, Ԅ=2fyA#n$ D7:Flbsj#{isYJu@*f!&T:e8Pp['wQN2*!O).v P:q=qo/aU>@smtچb1ۣeWd7ЬGVBm}} W6o|E/왼<噲lg籫B^vݗ|%!G-2T7XkBknGvDP|1slr7!g%2:b9:x$<0"Ƨ0Na,"[Ze2b3f2T_F[Э_eؾ Ћ 1¥x-pG|u\'g5d@@ /#վlvC5]j m"5Ej|oCץ#z<=8E?Pv܇V<=d3rC$ˁ uipcQPvH_&'Ӎ#E4PO*`2ua|nRE~vOϏ19\nP4Y08IbdM?j7ɺ"6 3B'Fez? ^À50 W}؊Dr.MgG&hk#';r.[$ʑq*e|>?O[2[KEfUN]St%ETMV~mQbĀ`Tjjp816aFU]Oj$he#x bXVZW"N;IHL$|/)\odY3yrPj iԄ˫Dsnj@_@K_Y5s*݅W,&Ȋu;/gZ'A55Ԍ],wN jXj&JBQXמ{k5զ5k)~}kxk@l*[TJ5xF!jc8pPD*5 ˩yxjgI9'}=< ܢ%:P 12Y&ɑfzވ*2;$D+Qtϻ-Fs95/<lZsEu:0dFD{1*3kqԬEs(U ȼA|r*|)31V&*~Z9&{ δyrl5XK˱[ Y-GNmh)7WZA+r˚ܿm/ܸņƊ~O"Uקg3{){ѻ޿ yo҂,ށ2_5:>j,2s)ylqt5ɭ{}ɟ8~xXkRRl"5"p|ngc&j;Q MjKJנfVgv۱3MtO z4tˎ8UzgǟK?D 3ӒKq}QZu8^Jx=AX%"}'ϐc ##lE'Ntɩ5尧$NB.hjRHT3Keg% R\W/%P1y%Y 6Z}6zjNeZ DJdAGmy\yi0pxAwf cZV~pe*@OLg⇣KS47!0觌_8s>Y:6"둑E%M]$W,*RthU06&WZmo!`6R,bV)[J>ZvN&H- ;*`~oYs][yzKW˒^O+deUϰVFC#+[ɶvϞf~ 0G";vl q3f>O'cEw,ΓZÀguQ.ϫoD#wu\9e[E[0yl<~b̐**rOXxCat.GePb /шjEnJvd(5e޲Hw@9@r=>yI|bAϸ4|҇ fNAd 7F<3چ,+Ŭ_YSv\XP o2dcݓ/w?~2dwTyދWZk"(Jz5sE8vJ |ZiL] pEӌnOONsɨHsm.Y8Kn!Ӎ gϜW(soԶ*\KQœZPBQWLz1g6E %wbuC|G ff-ڊ'\'o^j =bAe[ڸ'[;y}-$v_<#s-w.Qvb{b,f͂-i\G}M=pݾ}} l61ښl{m.XN{5mICe3`Fuɸez0лlB>eT7-TWFCɇ\YńZPSKt ~aē,n5aSס->%BcX{[G{: <L:Z#%Kҏ2'^3&};WW`N/cD29ILSD_E$fT'եNq?$75֒c5g rm]kjD0[8Hs:N0&Kp KpIUUa4ї^z)H%R}RRDḹVUn%A.xV3<<ЎngOrMV~Q8fʃJI+9hgB?SU`FWŵ1DD 2`z >OsXGOdc@Z)R)G庻}Dx|h3WquL]ռ2}3fv/SM"r2Be]d{91''"b&ٸ*U;QO4{ޕ-yCI τSL?lQVQNG_2gHTʞoI1LYeZ) mf!> 6UTb"JVRRYWTl=lݴtxuͭQɞ+fge=3{W0}SVl3&fgK3}NxYT̆BZr5޵o(MϾ'TDm6fd"c弋gǀΓnf[m巫lɻNղEC}EQ)b&q'!@,?!Gੲ&1vw6>c#S6"hڋW経6Y8ͨ61&I;^Mya1TzrTh$55`γM5!bv߳rP0 d;[C˭ ϊc+nw|w?x9Cv2n?-Fz/q\|$2BiIbo?ǽT{~@أڣVbFaYv 6_3,n@%]; JZu3 8 QT$Ҙ!2ՑX D+^nR~ZN ]C9 i`!>7T@hQe:nBRN,gCet *'enfI | BI%P/`K?ccRWC<3~cw64+]tNDljberۄhўMɫ0l|eEۚ;] V[*¾h{/E, +DC -=[UgU/hn?kz&3LX S7SS?Vißvtu3YlovL<Rdv-BHqL>y5"<0]K}"8 ΢^tws8sW8 O)BsDנ[kr93Fr8Ppg`|!(ÿ9LQ`BDWsWנ“9\ g̱<$3).hx'Dq Cuk:s8ԡƝá5wpC͡u~:Լá9Pu뢸R\Gf0R<{)nx")͆[i|VPo w] ![wotڙV!&z')CRTJUI tJs7to锦vtvwuoHHuIVwun\XصO۹E߽c՛u_h)_҉TZZ׽3/OF F4/ywIRokU_*R߹RZ9ulX!WZѽiCoWg_2[Hގ-]VKMVu$ :­]}JE]+!+;7K2e-ݛ[M}P(nz:{w-JKp:=+7'oeM׊5 kÊuV­ʮux5 T$={úRH\u) c?H4Jν}PU+H\xZǹ&D)I vSWvoٰB;Gݛ{6K+;7ʅ4k:|`B@ZиߣX@R#wcOD!Gr(~ 'W]+ґ~qsz5&ptn+\悿֢үA{>mw -d?fu6 jgCط[8$BX-//d?P*%(#Cﲿg@䅀4wCS䐊*.Ue aǾ 5MCf#/ cj8.< }jT }=>yz`*Eu}w9pfv08Kk"!!9 n8q_K|1Z{Llw:t6{>]ߗ &\7p7rכM yb%p)p,`Pu -|̮O:zBum7>lw*Ujn;vAԶ4۔4qviAmP+)G$7$S4h '᷀~rnz,Rfzȥ'UP2jYXҕFK"@CIN9#îBBuvDZ+Iqv.ZFv\gKQA4qT m5]ӣаF4knvelM2$?].۫ۯԝԝIpZ8'f]~AWثbu=+$]J'uWd%"p{qPm.׀kUq QpetFHgP#!Ob 1cH  HO`fpT PB| \38T.@4cq2 wDNAb-rMm]l6BmѶ\w;>5BMѦ\m6T=%P2p,?AS+a>iޔK{n)B[ R~.a1|/pqR[.f''Y?E0ϘMjNd cԿ_KlpY[g#0Qɺ:Su:}Qr#36 S.KdOOo>|>$R_G||7gQ?,xJNt4껉ވ4'߁3x; š:١FjP׽1C3:>gr97<xjP͍$p}pmWfz><+wC%lއJS*9_* kC% ^;TS3(Ȑ+P!%{ y C%zKiJh4|V9ӯs"1 @C';6q ,#+C"A6ܾ|;:\t$#PhX ~ChtԷ ?cj=;>'$Y6~Nt#~<<Ǘ9Ӗ.22Gu:D ؘr|i}?!bU?OܦM179hX?tZ߂i.i[ԦoY|5Lw͎=5j6@yOLۿÿǿ/eK55~5gnS!x@8qMKhP(8 +?qfap$GW=yb =ҥU#;V)pR6U`M]Pm7P~ W p<[ʖ7)0(/֏N!&>E :iQ@Do>r&~$gZ endstream endobj 74 0 obj 35967 endobj 75 0 obj <> endobj 76 0 obj <> stream x]͎0<b<"L,fD"o_{Vbs}xp;Cd=%C7[¤].I[3%Y{z;qN}˦S};?5};c~4O:%L_t +xN>5\P;p:t}8ԉ޹/fE(s+u`\` l;plrpzqdF~o8WǷRwʥܳ^ǀd89s ; 0+ kѿa";0E_`W{0K}_lowCl1Y;zWڟF=o9J%2Dx Kd%d%O$1 #k KQ/8k7/c68 llk|,*Ks:~q61KJ c8aV{$ endstream endobj 77 0 obj <> endobj 78 0 obj <> stream x{y|TE𩪻ޒt@ߦtHg# "YY"V%@DCv@OpE#b8QfyD1 :(+(:7*ܺM 3{{N:UuԩSNoF`X9v ĵbmzeކ1)w _]ֶ~epMm3@U-Mͻ<B#8 #WD>F"XD5$`#ɀkE nHi D <vsDz|EG1 KbÅ[ ?$>>!4r { Oĵz 7Er [q0~!טBxB0p A'N~Y6DVCl*;#_#?CMdX.k8tr!Ja&̆X tx =ByN pYL)1'd(™-.xGż3סMTalVZqx^K_߈RS`-t<'g"lK'{ȯ)L@qH:nњO9ca᫑NW ⺹H2Md~v{}3n@c8\B,:o-S a/s~ ou\C~BKh Nt/slb[6,ʅn-)K:!77H]""OG~ 5@&p^В's^7-x>@b%I$& bFr>gҤvF>iXd\ _/*P>E:ıԑgaԓMd!}h~*t4%b!c laڅ~o(!0 n$a+lV ^RId̦CK7z)yST2 t( mC-v(?vwjw5D 4 kCJb^RVD(FV:@K >I|#0$G#sG#*r؁f(L\4<)F/ h/<2~&K"C$=9:Dz/G?aPyOq)Mt/  ܇x)H~(T2FƳ(܇Qy9E鍼OpŸ/i|œQ8քVw ?C#b m} ^G1jw4ݻmJVj~ }Iyxfp/^A=2c_;"a"l-xR+_Nd‚)&dge2&RSoD'r:lRdI*YnTia!-0sf^4!i 1"\s%5\7!JZ%YjU@ XP됾2POrz4^ߏ-*ϪJ5LժpU}U߀\h1ge€قpBs$L' US((1U81PY*u,9\;2 a!.|T0j>M<зyC@sҺ0kpppU=sWEݦIӪžMj~]_}`[ZWCo֭AEtj Tհ)PXwy#.Hb_&&j{0HRҤ@}Se@-X?T5Ya=JXc-u:U`ԜD(0 PQNHAߊ"ç`p3.CkT瘪a1P>\?irT砓s:֟áP8#C uYk@CE:lV?5mz۰˱8(cT__u@kkl\P=!VuV5]ے՛qTl rܲ=xuSoYT7hEcy@ Q4Υ\%!+«hyb)gyV S<|ZHuOFP%I0\(<, *eaw=!3%s9SH;פ\LVف5U8 J 0%mvX(:ZR.Y!qn?͞LKϘi%ØҽH{fz<8\RlVNJ̬'h%,AF,3ӣiIG̱6nej1DArHtD4Vj4L yB89':N79y*΁ғ';+פ\h ] P9ŕ2Q r+pOI L8Di˷lnconΉYy|M㒒1tdȉFҒ}wKIux撇F6|*q# 3֮x邸99qbi^HGMLޞ|$ fzTk(qfb"ʘf:yP2Oƿa\qH-"a]BFSP0/a Zr$Hȴ% jA1%W )9@AZ/çA:ρU1L*7v6_HPw7_ceTcfV8 JA_ ]j?"8B5lad [%kMpb8xtn^O$RT$ǒO,Nm_|xwӛ._I">Gy[^<"3feKpK^{%n̞:.XLOt_0m ζȇLe${-o j&F&G\ v=+Ɏ R:TDײdsX>dTv cԄBsaLA )u˛6N4=hc<#"3 Sj7-J<(Yq 8,VkveV:, |﷒O+U/[ݚc-2պJ4OzDk,栉y/t!J5~3_lkZ=*97a'95(G@dD#ɪ'0ApbB+68W,3eSKe WW9dSbaM?r!FHmda*L!5mjٔpC-̍07CHKHϝ൧:#Pҩ֗rڂu7ߔ.N͞T=~ffG ҳb!1+vbX-/fyגZqLL%z܌xybfv*e) QC[ӽG>://Ie`ɱ[ݢZX"Qkno9e--p:Sp~oI7t}AOtѓ+<8@hTӗ2] >⒖|sA9<8#7OrW-lƵVS/)ÓIpګozd5\U; (3;ǟ<=xC5Zmlyێnn_YwՆ}i-|x__F߇e= =?y\ 4J($Ð{Ű@聫 ؆x)(4n2 oivZR*Uei;uGwȁŨ~]]>+ 7㺚yVn VB_`-(-^27J+K(m>ZcŶ(M@)X4@)Ҹ'ϣ.7Wdhb3JJ%JǐҋNcW&Di2"ˣiʍʓu)Fi;Jc?\NtDi@~LEiX>Qo^Qo7J-FieKF[=6s=q6c, S(-@=V}.K4~%m(9@QZlp:V#;JC~ce q=u};4xn]HFɜ:44lQOg5uqMsHQZ')(zs:Ei]?8l\?J/9[V.u>%(} s rS"X-`&܎ 롓s*ԍnB~+ƚ2hÏ w^jA܂k݌eHb6:݌RPZŠsyLwH>*ƴlKRأ.Ӎ5=+%Y-9r;4!r5c {4-ֿY>\^ny}vT*>3u5X˵եǚܢQK^y8וFzmX\^[ uD^-״r.>#cuTyPgrۮGa#c Vr]{9͜[?j)9\ިڹ-r禎՗>ήH[tZ-=Ff3jac[ȷ(+p5"|'%mJGu\n_ޛG׾ٵ<=6}^Ƭ>c.|~Ϳ嶞nPyu MzKt~ѭڋrkxK]۵lKwPj^nnhU:w}gZў Z/[ۣ.hi^Ҝ]V֬mjk]qT^Qs 9+;z:VN;%cye^!ڣ6M-P;VWo]ź-ަlޜѭv`McM{owkKO:-_MZ/S\ٺERt,Q涮Xԓ6aw+ZԅMkڛq:⢼5ꚞgWP[{:۰R;[kZ7-ݫ[{u՗A+]`G7vvw4Yѫv*Td[WiR*޶^Mo^}nѹx>}yvi|F8Jojݖݭ8jsǺsdLct]:vU[fFU-mZ(s d}q>%{a \kVFcz꫹.^9Oo`'Al{ =X;U+WV_Yji:"^x-KSCsN,Bsz:T5mNcq53|Rg{r笎ߦ𚱖kǷKk]w1N1zsWQ6|taP!E&\ Š ф2^͂އʕ/Uk:2I$w8djxDDsXy 18w,hl\#~+h&O>ۨr}c Oֆټ!G|!Ksr&s<8}2/V28xZ&o+68[bell@A)!܁A!2r46k"o~6 Axqn.WjP~s&84T؊^6ysSl^Nƪ8ޏ2{"lAЈp(=Jc&NǛ!#fb3LTWl2ɛ29\{";ZYApݡW˼]lK 1S2#l}^0=)5Nr:*ը}@b{{{eǤc2/.iLGEEEE{~6ZGYn߻U25$; @ E% ChGB  S:FO!`"@BFgSQJz`k,`e8 |d,8  IE1lvz!jLy0]Eb0=Q`znO|e&r%A!^w,dҝ(AAw  d0ݹE< (ch0%jW/~{%5@닾'Q| w-3|ΐl,æk3v:+ǥd֮kɸn߲ E$uзA dxFFWWzy@$iCa>_~4ߤ@FoB+voq)T?LZ[[_,Osܟ&qrRM*fEQ$EPJp䘖;NrHio(f+jhpQfX,jJ%ul׹+f>00L/rv@͢rO2L`Qz$!ޛnO@zS,WcC5{<0$ d,.b^׋q5 ;Շt"2&|Bui=4AGu{!Z\b. EG(gS@@)\4|4AKyyrZժU2V.12{2HACj;YKeT8; Q$;EH2yGAEGE,"0D؎"l OKyUrRS[7@y}Rӹgxߗ^a%T6Ö4` 4sSa di~ϵI{ ȎVeeUzMhihNۦVOUkvCoOTUO/Ԅ3ք_\7 UaygyqހɄ'z@79'i5h2h/h,h)h&hxkxzkxtkxnkxhkxbo/3|n;=x|N&f &Z8̠|bcz^DF՚9}zCE endstream endobj 79 0 obj 10481 endobj 80 0 obj <> endobj 81 0 obj <> stream x]Mn e8i$R6QEa CJ]aC#kڇV+:#:tPZ:FI^PU[oVHzw+ݜd/NSz uXhOk*a""/|L^'G>%=NEK:$>1۟HX q`1хB endstream endobj 82 0 obj <> endobj 83 0 obj <> endobj 84 0 obj <> endobj 1 0 obj <>/Contents 2 0 R>> endobj 4 0 obj <>/Contents 5 0 R>> endobj 7 0 obj <>/Contents 8 0 R>> endobj 10 0 obj <>/Contents 11 0 R>> endobj 13 0 obj <>/Contents 14 0 R>> endobj 85 0 obj <> endobj 86 0 obj < /Dest[1 0 R/XYZ 56.7 417 0]/Parent 85 0 R/Next 87 0 R>> endobj 87 0 obj < /Dest[1 0 R/XYZ 56.7 144.2 0]/Parent 85 0 R/Prev 86 0 R/Next 88 0 R>> endobj 88 0 obj < /Dest[4 0 R/XYZ 56.7 785.3 0]/Parent 85 0 R/Prev 87 0 R/Next 89 0 R>> endobj 89 0 obj < /Dest[4 0 R/XYZ 56.7 592.4 0]/Parent 85 0 R/Prev 88 0 R/Next 90 0 R>> endobj 90 0 obj < /Dest[4 0 R/XYZ 56.7 490.3 0]/Parent 85 0 R/Prev 89 0 R/Next 91 0 R>> endobj 91 0 obj < /Dest[4 0 R/XYZ 56.7 223.4 0]/Parent 85 0 R/Prev 90 0 R/Next 92 0 R>> endobj 92 0 obj < /Dest[7 0 R/XYZ 56.7 579.1 0]/Parent 85 0 R/Prev 91 0 R/Next 93 0 R>> endobj 93 0 obj < /Dest[10 0 R/XYZ 56.7 785.3 0]/Parent 85 0 R/Prev 92 0 R/Next 95 0 R>> endobj 94 0 obj < /Dest[13 0 R/XYZ 56.7 614.3 0]/Parent 93 0 R>> endobj 95 0 obj < /Dest[13 0 R/XYZ 56.7 491.4 0]/Parent 85 0 R/Prev 93 0 R>> endobj 17 0 obj <> endobj 16 0 obj <> >> endobj 96 0 obj <> endobj 97 0 obj < /Creator /Producer /CreationDate(D:20140728171831+02'00')>> endobj xref 0 98 0000000000 65535 f 0000224449 00000 n 0000000019 00000 n 0000002526 00000 n 0000224593 00000 n 0000002547 00000 n 0000005716 00000 n 0000224755 00000 n 0000005737 00000 n 0000008735 00000 n 0000224899 00000 n 0000008756 00000 n 0000011421 00000 n 0000225045 00000 n 0000011443 00000 n 0000014136 00000 n 0000227281 00000 n 0000227155 00000 n 0000014158 00000 n 0000028520 00000 n 0000028543 00000 n 0000028739 00000 n 0000029158 00000 n 0000029430 00000 n 0000030850 00000 n 0000030872 00000 n 0000031064 00000 n 0000031370 00000 n 0000031539 00000 n 0000049986 00000 n 0000050009 00000 n 0000050209 00000 n 0000050690 00000 n 0000051021 00000 n 0000064293 00000 n 0000064316 00000 n 0000064531 00000 n 0000064921 00000 n 0000065185 00000 n 0000075512 00000 n 0000075535 00000 n 0000075726 00000 n 0000076093 00000 n 0000076312 00000 n 0000087504 00000 n 0000087527 00000 n 0000087729 00000 n 0000088173 00000 n 0000088471 00000 n 0000097334 00000 n 0000097356 00000 n 0000097553 00000 n 0000097918 00000 n 0000098142 00000 n 0000109998 00000 n 0000110021 00000 n 0000110227 00000 n 0000110688 00000 n 0000111010 00000 n 0000128933 00000 n 0000128956 00000 n 0000129149 00000 n 0000129708 00000 n 0000130103 00000 n 0000154361 00000 n 0000154384 00000 n 0000154595 00000 n 0000155161 00000 n 0000155581 00000 n 0000174510 00000 n 0000174533 00000 n 0000174739 00000 n 0000175182 00000 n 0000175484 00000 n 0000211538 00000 n 0000211561 00000 n 0000211762 00000 n 0000212395 00000 n 0000212877 00000 n 0000223445 00000 n 0000223468 00000 n 0000223673 00000 n 0000224022 00000 n 0000224236 00000 n 0000224394 00000 n 0000225191 00000 n 0000225248 00000 n 0000225400 00000 n 0000225554 00000 n 0000225780 00000 n 0000225946 00000 n 0000226096 00000 n 0000226286 00000 n 0000226460 00000 n 0000226621 00000 n 0000227000 00000 n 0000227435 00000 n 0000227550 00000 n trailer < <72090B503D32E15A9F520B44CA46DD97> ] /DocChecksum /C22F28D33857D53895E196896E1F5B53 >> startxref 227811 %%EOF discoSnp/colibreads.png0000644000000000000000000010741212227036510014156 0ustar rootrootPNG  IHDRv>asRGBbKGD pHYs  tIME 7EjtEXtCommentCreated with GIMPW IDATxܽwx\u;g f+ Ah{DQ)iK8uĉ/ǩ8ϱ-VŒ,QEHVbEA`9) {Hw!4s.kwiaa&wkpǦkuRa&QӤ/0.ww3;?76Py.ϐ;TIջ[d,9a~Vau՚z7{ɞ)}l֞:L=WeUZάN=0ku:Vs&{9;DDD{F?UgTօ\%[=$Ku{f:=V2/{UrNonمS/h&RK56GH`Kp/~6TW+h1L3vۅ"2JDblt2ϫz=EgE 2# Z SW;ޢjdYo:[vcjHg[LV^NVd*B|81$$:VdW%3\dMd@+Gcb\՜ b0cG]#! ӤstsCxΞHW3󹿮.iXjq0U(k=Uقy2NXt/  p+VDJDu +qW:U~)B%{G'iFudEުl *l&藕,NGvY9vikɼ٭3UBĈteΕaSY F"a˼x/Cp 5sӌBTsM]D[ "UO7'8vͩǨqxb*IAPrjLG#vEeB2 wR ߨx*dTLpѻ'̹Qq~DPU09-NSbS *J*tud@&=iDx<γS3cnjdK\VTTL:GEXTؔ.jU (! DȄhLT<`Y5>i9egt:NVEaT@NohE\rΪCB;9Pv]湫T QkN֣09N "T=D4~v:+tB4J?OXYQQ+2ĚD A4\Ec , )oAzv6' CL;CUAd 9IQUCMVƸ]lTC;QoUE-ʩO'*R'{5*/e1['ȜjGSMztn*2ndrs֭d[ :. ljh/eYy9^5eJ,'I p"S4n(b[N0 U{eTaAY$mB;DnZͧ͟(6kg;E# ˌb4))#SVIjw'sj*dQ~ UQ/;%'2VDS]A""'C"Nd\;ղ}ؙqەz^VDطne "\vZh'Mmؑ,hw]bMB!4MH<(nZDP(1 ;o.iuc~l<~Kг;+@|)ʹXN@/Ko!jeP+ ~sٸ!qf'w~űUQ;+(Xţ͉2٫dːJ%sR"c*FJPsr;QIIW/^3vvoo<k:hLenmƦ6jW=hTA5t61dҵ*3yV*֥ ӕJlSdY<ee6mOR3>*URI̹Q-JTR$n2nU7RLJ.JF٘ofS.J[Iv29 q :+PY2kgEw!BV4-桫-|#?<~?ݻPt aZjnӝd,-'5"H$"%y0jҗjXNrdhpX)q)]S&ʙK69@!leȈ֑L9MB`,inS]'N <>§.c+uN(,,Wu9bOvL>2elQ.(2!v^2F;Ŧ"dOxHiy*RJɞQq#8ub;/JbۭUjLdƩ tUc*"@F*TD"dJrmX}ꢨ|a!.{;vs1eʊ v5w$kEJv+d$U[QI7L= 'D(T3EГȴdCЉ V'12'pv!.YC&"(3TLXK}oD`gqYvֹ{8>v^l d|QĊbx*ڢqͧJ#;ejU:~6+ZetQnUes*;@HdcǴg(AN mU?cԗp\zlذG}۷ ((㓷_iG=87ϾH`p4Uۘ'.]rٖ=j+a7Y2y*Hv{o0qL%Qi,̡hX)eQɥ]!UeV ?v }s&B:ם]WڭMYͺ,oe`pWH&&gHv|֢a!s#J-L}>_"X=ߨijӟj靖0Msrsśg>Ï~#9]wEcCcɑ̨AU~d6Owx,`[XZ3ܺKXbI<4<]Pd&;T(6U ED'P* g#IWQ뫖 ۢUykGIW-YGLrErUDYAmvD/P鑡_HYhx(dXK!MqfmaH&Î;ğ:M qF>ybƆxkT_UT"U[gU)5cizWy Ǽj#zbҘGQS)uuus-`yqO>uL8p8KC\XZTLr(1/C|g2>:{w(~i>'+  *ZժƎ-pcyh7g"$nZ&lhMQ"˚MtYyvUT cTUI\|֦)~wzSNW(UQQ0+VB$LslIN>6| UBxs\_=.\`llgk jVɨHU6U{q&X}nN;#̦r=+HSj-X!R.2\oYAqZW TzxvMeD"}emR3=vUV|Zqء/nZ9 #76TU[orQXn ,t̛Yx}-,ʮ-!ijxȍO1)1#Se6VIRUNJ1'uZE kR"\"Oj )#R Aj2cV5Y ΛO=*4ұQf8+*e~2EDdh:2q*;#j QiSL2pgjN QntTw*'k,j竺o3KQF%A,$۪$ 7FGeA>zj~q!N:Euu56l`Ŋx^/]v_?wXvKі)Y{JUdƚUِMrRZjƱLWˤn3AT1[Ep蚆&'b466ϳsNΞ=˹sxg[Yv-*X?̙@&z2QnF__7or]gP2$e rRV&eYpQ@5-Vֿǻ*HZڥ$*Zڭt~joXqXê(g%&%]S[ei,[fZ%YŧJ'2;1$-uD<RP%8"DP5N){n]6σ>Ȳex9s ===<### ߇hW4C4Q>2>s%Μ9CSSzo -Y_`V2*&j!TUgL]]K.eҥIFs'&ӴIB4(xz4TʠD itht"a+ UA'"8T}/R>novdkp: ]^r ZPe jΤ%AUuf9Q dLU! \tA#XDei9h uTTU&'cppÇo}H)gxx;w2c -Z;T7Lt *SʽeК]4vW9x*c:N$.Њ Lz*ޘ}ӉDTB*y(V&+[w">9tPE* xNdӚy{cud}b#>K_ H(I,ö:?9j<].b*ȓ`SE;TׂJ>du.5U3 wDD4kegs^Mr}r94X4H+ Ph"IaQ17ofU<3۷/9@ʃ>ʕ+{Ţi###l۶rVZ5_W/rN/߇ ==l;{.sfppkdjW$[wgY_?3+qMu]h+E^iu"| ^|W߿[I¦Iś09ʍ`d ֡*FJ'LJCMFd7N ?;P5>눪:TwXPOe,- ~|vScaYE nI ?cmhə^[s5 LРa<\p! CCC|;ߡ{#Xeڵk}}}s=̙3W;w)i7ԊN=ث2ɈOR5My9w\B(] jMp>]?9b~{|@U^ <ٻ:ly1#(ѱhq jp%!bLaf/Vɣa&V QMŽ/Btf[A"H$TUh{$O2iF0V445t2w|%R*G'! =eϟ>9^|EhzO=ccc<dN˼KTUUqmҔTrd UcP*wQ({o}w)r+}.~,]vvwqi:a0aD GE#LDL&(i"~Wځ|t^0ڂ)Pb IDATr.UDzҘD̘h*=yKlQͲējӈFFlw q;m8h݅T+`[]ś#gyfؓ(̫/r^^^[n^x}v4Mc˖-~[JE'0yꩧBqDV*VT^S/cz<<|=kaiREun/.a~I1s ɡ + ۝o8e8燆990^N >:JO ێn'&ʛox>r=v-tlTj7,TyڵVa*pzC&QO\a0*a$~L!੔MBvZӵo嵫CŜ+q;yXSveqSl^83Gxdyn?fIr)f" X?IbٲeTVV /o u]vzz~<ҥKY~pc\o=S(S%qڮPW\NNwy'?qyYlYF)?a^~e.]aA$! D(**fS+L2޼%n*~?_?t@ ̣%|xSq)ХYۥ,(+e^i ٳ᷹08^g7ޤu`\򜜌}*2C$Sv uhSe9M ݷtM#dD88vP?^CϮ1 o uYe+d&NyDs 7?GN)VY*IO[D>3%I3-ͭy.8>މal.j!0b3gI0zu\PXXȣ>ʅ TWWgSO u 57j|nN↣n<__˄?G7,,|0@1_;t0qo]x*0^[M#R-cT G {ɾϮ0nhRQUvxhQBuU"Y$\4Cطocg< .Fx(((y1>>N{{;g駟fܹ,X* x %2& 絫i:[8޼,%CVb/5TPǽsR8UabXS%i444RB!NגHx-23ݛS~>&WqC Iz쟐a02&UBa]1Snz0 bRr2['$PS383rƉcnkm+t݌}-*@8^ihFMM Ї̅ x';w.UUUBܹstvvS__/6Rvv6477ɓ a&yyyqݱp1FFF' cv'q|KEESVVŝReG˩ u;3L:ķK*l_޼OJS/Y⢓qn]KL2UTr D1]6Oy0 fqC_Xbʏ1icP6%a`4#Af(zd˒TŜ*~0N*agfJߴ@)fn'O \6cW^g :[wq9˕L҈D"Kww7$77QjTTIVg̻gǃ G@4`"mJ(2X'Ť  oUbH瞱1>s?9u:?|u>by25ULۼ'jh128_pl̍8!X*JDIf|}eY5R&ؘ?ӞR6B*ZijG55FeIlC7NʾRuѢEl޼g$>, , ??_x<mD$cN{_rg?LJرc:uH$Buu5 ՑN-++x,<'혺2)W]o1&nmf 9*eŠT nLTp8Ɨ⍏DU*YN'bei"+^6&t | c]~NyO/\4PxX|QY[KԌkA3LtBG{vН;al߾BZuʒqj g!"Q43Ե^ctRVZٳZ@SͩGt7 'Ożhe|q|>aVttfHSۗcq)zbs/#,˶,7QՇeWsx˛MxYKinx;M*;s:)Z1tU?Uu*953w=JjWw6: lFٱhI+a db%p˪Uhܒ޴9nn!چY\Vʇyٸ- Rl۶ .P]]?̼y em'ޢyM&axѧ?0? GHE EE|x3QtxmRo]wVWΤ;iG2 )SE ULX-#eit]_WwQɛB&Q;ʋPwi$HQ4,Dk&NoD8JUvP2bOģ +s <*DEbȘ})N;7'C 2HIyN;o A/AH6pIK&7̓՘̲s%r8Sdw=aI-ЕM;P Y] \& qwbj|q0Ѓ|'ӉϞ=ˋ/H4}{7nB|S- (ciS TmCCq)/1W!)4WqR= R&%~ ݣ\#\?0{qev^u˧<'b^krDh{>:Qyo?UˣYi-RuTF(Nt}" v|Umу0M&64!.3>D$3>t,*sr˜SKvT!Hp\Pl _st }MY\j+(`v~>eٓتWl5@8̥Q s~( 1 M͌lrsgnAyyfg'V_JƧ/\q_o7=t.y)XʫJ}/m62Lv XnGE7WU&ySCnatujG:;9GXH$2J_@CA>Ϛo/3H6Tߤp4K/^ORG jzkc쀤4.Bb޲.đΟkf 泤|R,T (0B&ݥ iн"o'N̹6ο'Jy&+<4Avve;ڙ|6ԓeQԁ4as<~W/urit8\pu΄irfp3<Ƃ"6y4(9 vkzDQ~,>˗<6nAN s,*.Z><,w0E]N'7IsOmD7n-';kqkNavգ8m۶ȦM͝VAH%EcbW{>3+aá {$tNn.EE{VCu56H0ȿ:NHtJKzCOۍI +w|`(pj`֡a_wS˗%Kd<*L0G=LV^\~F:817ӭKM){}ePMcj^ =z O890H/^h/c7-N*,QV!&hFqz X[ky׻И(L!BJ5 ~q][26M>.8t=WD"urA4 0Y^3rsgtB( ]cc1v=ɶ6^+h.)v_Mhkwri|3\j~?9]D p\c"jnAЕ+vi1/+SSMχ[wa&#\' "5x}<ﲥ!n&10oܓ[sq%t #mp.%S%:. O:}{)MYX*pJ<;=>S IeؔcxDlMhM%䤔,syRi̎w{[n,'[ɀI]1z#Uuo3%Gͣ4]WHLuw`K"t]JjLD"|aCWpͭ5\WGK *rzofkfۋr8|!W0_;6]֛G?Cغ 3ӧ={iFYRRg-޺:}| 4M}a!몪E} >6qrW9:?m܀?\:Q!9[:EB2qBw6s}30Msdź*]E;i,7tRjyyYz5ׯX;MnwM @US }چٯn]@P٭$&'seuњI}ly)+_yV>j%s piڤrk },[xeW McN~N%*aNcMJäy>1t&nl`OVbV~>&[3bDOn"֛yN z"r|+NWX`nVY3&=aJ&;]^UIJ0#CD͘w> g{^"P((+JJض7r&>;(̘ͳ1#'Z> _Z„gtNLї^ٳQ[ C=Ghu| ^}E 3==g ]豲KͲ {ݼV%XCu<_C&Fh٣nӻvnj _\l# RS=/}=VWV{ceYY2n:y8 pkʲT$+R,M&@c,bi"qJ*]E]Vilq&nہ~᱌ϩ|&&&x(**b֭%ruUWz$O\.,:]F#gHRV5|PP Y)ܛg- Prb5ڇe\S;vvOO,kzֆ[͛]Pj旖}ʕ[=`>Ͼ>p3HSuM/,1ї^foG'a&>jƁ.~z'1f4_w_߼lm8ʪ}o5x/?D?߼)hD ;{O&-(M(c(gqW]-O}|_GOWwDNN`%9cc?ܖu*bkre.n]oC7DnK.8W*WݗT`ϕDl3k9nwb#Bw|n.'y]n._y=],=mZkgB%{]nrzq͔y$*_._P8szK4Mx1Qjss]c-7]ư{W%Ok˵kuk)JîK]DR2٭% }5e2[ҷ?{ĕe<~H~VV(G +s\.hqm!2)ㄿv{+*ݽ|,??8G_|9L_+gw< ʼgg˗]5м^q?kmE[H]G\NorW]9ıo-"7^:ͷǏh310NέXW<h8tF1s&64S`*4{a'ROǏsN.~]SU+z.Da-3׍XS^T>?%gI]Wh/D4i))jK>+;n7r[BM9\=i&J9 ׯnx0r&vFY>]hժU#,n-_o_ tcwo(Gϝ 矉I4xe8N3ezzt7 x %DL# \}4h4_,IWi_z _k(*i;wQ_YŦ:¶[yOl{7{${~A_^6VÞ!u'풭3gXxE烇 ]M8{Ǐ37gp:=fWaDQgW`EYuxZx@L&Y^>&nU} E2bbi|YP\SHZʎa08E]D2UIJ.^}E-|A^}8џ<[=EpbPUOxqv'ܧaNWOGo>6nȜ9s~iw]v="Yn7Z"I$jL~T&AUi.^loO4VN*ve;||bb'OrvppZmaydaqY2T_Ϳl }4MwtƥNk jnz: q~4F"C!0Mn wXqh}7ViL/YM]QaQg.SDbgs?yg .{M3+x$-!g|]Q!^rt|qN%KB5- ~pU*DV[X׬FOҞXr$4jҵL^V已&o.Y3]<ֻ#mD㵯9,7 DywL>=== [QDcV}Q[> a,dY!&؈eMb['yVVFKBᫌ),>qb pL+(lE&rLdNzd?BSVV\ tʽ_O}K(ca(<usfdB?}. `0ݻHh'ˮ.tNl(n|e~ EtEEI5 *`vJ qѱ6eת< 粚Zwϊ>Z&:>>?Y0%TyeeKM[0 ^ť:b8bq#\~{|fĻY=N(rE:E$8QUzĘ ~ñ{mmf CjvΟݸ&u.ZH ڥN2#$vƃ(i6RyY.߲d.3v*;&eEߺQɣԓ#.h ҤWw : >ZM\!`xM>T_%垈m6 !mFڛ c0^񾯒Ւ}sţY~g42&4s};8ĥxw8̃˖%P0[! VPOǙ1Cwm19]'WyׂFCNko]VqbpJs)wS""./.b4t.& Zʙ{5kp_5anhyfchd@$%%xPqdr@ ;fj熆CvfnShv>kܹC@tu;蒳EKyo5adǮ}}p"~y4t1>> fʅxwfjJrs ^-nI"I D"gR(TC}}tJ* l7tPQVΜF91p9NR%Q񰥮Α ʄ -aK]'.H!`P"ySO}ekX_Etߎc :.$R y(**}{k Ȫ][P$:熆ce"M;QO!iI@M"SIڡHtz]u5A:GR"[v $G]0E]"{cJpǙTQ"w+q@SgY7d&&LoѿzVG *-t&5ee{smƆ5~?VGCasSv[IP$\4YtͫVm- geKYB=˽%+ɗsbU,p j%(^5i:pLhnЅ N+Q$ ey:&bj("j xvt2^E1|Ue$JZ9ē7%)u!OugzPމINߔԯLC+Xϋ;~j4yӼxH"Ѐ5%'6t,$F5vwJdyi8{.0So8~^p]vq}Q__)4 UR_GÈ2,[F-\-%RMc2mPq_aҘZYJf\\$m4TnyZu!,hŋpgp"/Γ$3Fꚳ (I"nEkX]kwW7Y;+gC'02+$$gv}a[dR;ge6-aL kj`غu+{/MMMlrtf7QH;/.)I dcmz 2ö 046ύWC'mm;ʍRbZ$+?t=+=.m+Z V&MCtNB'pǖK3[c2H^WSIYrkj) t>t~V"UUrm, ⦂5p6i7!M?<7tK. {)oH-_Jl祶6ªvaX].I8jU'LBl,+x9COvnG3.#`R|2JT±q`+(1/A i͠o+"_a8 0Uˣ(SBj2;meA"mm7!EII4XʊSrh 9:rkedd_ײf8Xf+\[Y^QigK+QF07Då47')8$:ӪqvUp(H8<`=<++`q3݊p&JO#U雜Lexp {?Ũ[ ǥPF)#TT2[#fTz$.˝\+=w=`NcV>)H=$&BkeYܯJ K#''QN UO}h?~;S]|IѶiW}1+]958ȯΝg"~{͇$Q\Ch$~7 t>:F(e\EAe~>Nv 8C%]#7 `E3rՆ5޾+y(GF-f ׂڑtñ2i[}96G j\.WFHBV IDAT)rC̝[m[6Q]RAY~UD,j[$Q\w7z{v2bPh0}D4-P]]2%kj(.:[[/ [AyK3u"o[/&ɹD7dD#VE'Zj_XʼX`#}ofZj]Ý}!U[u@ja462ʳ-L I|fJ5+5"h$S'O%Zw"֐QUMo썹>49>բIM+)mI̯/4sﲰ_ LwR٦[V'LJa}@V2+%.5 oow7[;rZqOCCLZ'3}>>~~\p\d*Ȏ6p?'''ٵk~4MKFY7@{Ocӟ]׹G?ʊ+(--EVdΞnz''Qs~*ؐ܃#ܽ1 R1ЦQO}׊ >dL(O>B@< 9~Bk6bjd#OtfL\piii!??J~x2Qhkk?!?O_*?Ѣ:;Fqy)S$SÊ˩Na>?Ǥ7=>nYfEdSX(۸7.\!sߢES7/ez!x%:fhi='{41 gWb]UUf1&Y a,;Id?ٶM~x4߿yfWJPիM wsRE55=o75|7cY"@9<8_`3I#sLۡJc:Ƅ/1^DFt_>ͷF唶JBlhFh1u'~LC,/244{^bɒ%ڢiǎ'… l޼G}/nٖVv^B y4t)vY`oOjI (-}gywE ɍo?vo}]8=9 ډj/{FFy[5E99|a (-=Fsh`Li.o&:zzb(yuJuN9pMNRV$f[[;_ڵ Sg'̊O}rllǯɬ*)n=44Ϸ1<9s,}  ޽|l&ljP"T…"A@,|u'_O26>V} gR~$M`Dde=t'xpV xkŋ/,vPUWn*onŧmK=֘\%j[; CND4o*Ny8 Wqs@3𫯱%]tEH4^k/o1]U͛*k5OdrUW':GGyx<} Hth{cu(|q |a:CdXu޵`_G^\)rnSɬe(́H?s_XPc4ʖ|iCpgC=_q}K|m^.d $y >XibIUcc]iJ{S!oddK+pa>ٳgbڵ#G~Fcc#YzbI&EH<:ureL*d.o6ndiI D#v59co/os )(ŶlQ1>v~}'G▯Ju~u:rM%%oN$jW7 O8X<#܉L΁Cӓu[P3Xu/kkmRVN[[/mO^.1r #|r+K JyZ|f(*>e/޵[΅p\ |nN֑߳)W&F@TUy?{e;$_Z_mŪ>5 7+z4ٶ_ l$ag/x ##DX7t;5KԪU$P;Y៎㳯o[Zs<{7~DHU|g&c5IMI,m/[e(Z(ATI_w^uuuD"^|EzrOSWW<@ii-3gxgYƣ1@NԿ'ܘq*îZ&͆Pw2XΒR{04X==]`jcCM eqrIR4Cn 2 Ŭ?Yh;pwcnY ʕxGvfッ|anuKOgl ?x9nqUoݶ-l(%j4ۊ$K*_Fȇ!ٹKw~#=Gj57Sg+rrA8LCQ߻c3iZ`ٹ4GV1|;cзP(̷eץK|dB>x1sN#{MgWg7?;}e>zu<˶jqxdZ,6mbժU8p˗/aÆi?ӔCQZZ*. 8oXÒRF!T]HTMa8dH̬p׆RWǷedsd`CC 糼XQ^Ƃb*q)S;NT8:ɁAr|` !hl* DիuK/,4N eIc]ǜ|:ga8Wt;汴\1d8Ɂ~wS Bvĭe|Q_l89tU!I]v\>c'ͣ(G039u5s[[[΢EشinMxXr%EES_}U)++l0󍽬(/E*DU*gk֕|t il'(` džUk+I£(z.7GO>>`0H@ӓ5cyh:._W7Lc<*ۊ!bMc6 6SB;a ܵeeÌEbX$ʑ!Ng(x>E G tLLWU(J[o宆+t]re,(.KvMI:~^&OQRQBu&B!.Od8&iWĹrϮYׯgN^(bu|n7]Ê2:'ʼn ''y<y>%y^FC {)))i8wImmr{/GV`ia!jd4P HM/5޵wYf]M0u>_q=_׻xB 49ɤ4T]'ODbp)D,SrcU_ĝvRXmn7X?X=~=KU#v}`* enwo$inl t?N$suuu{~_uVyd*Zx\Q/Q%Gt :-0z&'*,x(en~y5I7"[Kj4lD\|;c09s… 48D@@ǎy55JHp8L0b(.jua>=[Q޵%T#X*љVE}|%+㵛 wb<ʭ7$Ykt {`J3IEAvVX(5IDAT4'+6g>F7MbGkI%;F:Q*%NDaum=S+3W\_AFgɹh'D,s&iO׾}xIZ~T/)U;J㊔^TEkC[Yulر!vZVZWVH?2';e1՜9,l*4R=JF&^lٔwttOyyy0?`;:\QI$w2#TTTu)nkrlHp=ـ,.n6EeeuYQYbBv9v֯Y:cg'֧9PlL2$͞mzeu8ί/zN#ffkӬyQ]llLL9 z0߷388Hcc#~ 3M൮n'" h[ 1.]d֋YF+;ac= e+v;||"QM@#3v@U("̭JLF L_KF%֞HY]qǤ?I%/g2R dTXY鈍(gևlZڙV>vYp!X~Hۇⷃ7[ p 3pVuh^&jdZNk v2FH*|@yNr92CJK O<[d+ײ_:f{\2}AM{'8o;ъN|w.LDqoV$AHkĊL㐰 bp/D:EN6hZhχk&l\NKE^^$ д+5UUB`ƅ$I0/ +ʍ3IQ+j N'N;a98+HZ슢"cvV$iE)aw`YV{B6YN+ӊ[@TqXeZVVQxVпe2Sg^) 3u5QQ999( &kGۺ3o%*˯ɊolGU0DGF_UD;TH,(L`ȡe&XDf}tB'mٞ3n%X\D*"6`ͲDIet$[ƩإY).'L]4T|5Njjjj0Kk E' rS+œWfK&dNͬvN.2-! YJ (Sկ3V7 fA%8r3ErG8u[92#2bb 4sNȞh܌}ά"3x>'1\ V]l)Iv.rd:2ugYFIմZ ԹNѩ\·vk_dY T ]2[3N QӉ! 9 DgVLHY.zUMIGc{_;[V;[ĚiL"d'o'0쪐6֓.n j&8)_fg@YV㘉&˝@NLD2݋ <dlimIENDB`discoSnp/run_discoSnp.sh0000755000000000000000000002054512424174652014360 0ustar rootroot#!/bin/bash ########################################################### #################### DEFAULT VALUES ####################### ########################################################### version="1.2.6" read_sets="" # FOR instance: "read_set1.fa.gz read_set2.fq.gz" prefix="discoRes" # all temp and final files will be written will start with this prefix k=31 # size of kmers b=0 # smart branching approach: bubbles in which both paths are equaly branching are discarded, all others are accepted c=4 # minimal coverage d=1 # estimated number of error per read (used by kissreads only) g=10000000 # estimated genome size. Used only to control kissnp2 memory usage. e.g. 3 billion (3000000000) uses 4Gb of RAM. PATH_RS="./tools/" # path were executables kissnp2 and kissreads are. Leave blank if they are located in a directory located in the PATH environnement variable remove=1 # by default: remove waste files ####################################################################### #################### END HEADER ####################### ####################################################################### function help { echo "run_discoSnp.sh, a pipelining kissnp2 and kissreads for calling SNPs from NGS reads without the need of a reference genome" echo "Version "$version echo "Usage: ./run_discoSnp.sh OPT" echo -e "\tMANDATORY:" echo -e "\t \t -r list of reads separated by space, surrounded by the '\"' character. Note that reads may be in fasta or fastq format, gzipped or not." echo -e "\t \t Example: -r \"data_sample/reads_sequence1.fasta data_sample/reads_sequence2.fasta.gz\"." echo -e "\tOPT:" echo -e "\t\t -b value. " echo -e "\t\t\t 0: forbid SNPs for wich any of the two paths is branching (high precision, lowers the recal in complex genomes). Default value" echo -e "\t\t\t 1: (smart branching) forbid SNPs for wich the two paths are branching (e.g. the two paths can be created either with a 'A' or a 'C' at the same position" echo -e "\t\t\t 2: No limitation on branching (lowers the precision, high recall)" echo -e "\t\t -p prefix. All out files will start with this prefix. Example: -p my_prefix" echo -e "\t\t -k value. Set the length of used kmers. Must fit the compiled value. Default=31. Example -k 31" echo -e "\t\t -c value. Set the minimal coverage: Used by kissnp2 (don't use kmers with lower coverage) and kissreads (read coherency threshold). Default=4. Example -c 4" echo -e "\t\t -d value. Set the number of authorized substitutions used while mapping reads on found SNPs (kissreads). Default=1. Example: -d 1" echo -e "\t\t -g value. Estimated genome size. Used only to control kissnp2 memory usage. e.g. 3 billion (3000000000) uses 4Gb of RAM. Default=10 million. Example: -d 10000000" echo -e "\t\t -w: conserve all the intermediate files (waste)" echo -e "\t\t -h: Prints this message and exist" echo "Any further question: read the readme file or contact us: pierre.peterlongo@inria.fr" } ####################################################################### #################### GET OPTIONS ####################### ####################################################################### while getopts ":r:p:k:c:d:g:b:hw" opt; do case $opt in w) remove=0 ;; h) help exit ;; r) echo "use read set: $OPTARG" >&2 read_sets=$OPTARG ;; b) echo "use branching strategy: $OPTARG" >&2 b=$OPTARG ;; p) echo "use prefix=$OPTARG" >&2 prefix=$OPTARG ;; k) echo "use k=$OPTARG" >&2 k=$OPTARG ;; c) echo "use c=$OPTARG" >&2 c=$OPTARG ;; d) echo "use d=$OPTARG" >&2 d=$OPTARG ;; g) echo "use g=$OPTARG" >&2 g=$OPTARG ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done ####################################################################### #################### END GET OPTIONS ####################### ####################################################################### if [ -z "$read_sets" ]; then echo "You must provide at least one read set (-r)" help exit fi ####################################################################### #################### OPTIONS SUMMARY ####################### ####################################################################### MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized if [ -z "$MY_PATH" ] ; then # error; for some reason, the path is not accessible # to the script (e.g. permissions re-evaled after suid) exit 1 # fail fi echo -e "\tRunning discoSnp "$version", in directory "$MY_PATH" with following parameters:" echo -e "\t\t read_sets="$read_sets echo -e "\t\t prefix="$prefix echo -e "\t\t c="$c echo -e "\t\t k="$k echo -e "\t\t b="$b echo -e "\t\t d="$d echo -e "\t\t g="$g echo -e -n "\t starting date=" date echo ####################################################################### #################### END OPTIONS SUMMARY ####################### ####################################################################### ######### CHECK THE k PARITY ########## rest=$(( $k % 2 )) if [ $rest -eq 0 ] then echo "k=$k is even number, to avoid palindromes, we set it to $(($k-1))" k=$(($k-1)) fi ####################################### ####################################################################### #################### KISSNP2 ####################### ####################################################################### echo -e "\t############################################################" echo -e "\t#################### KISSNP2 MODULE #######################" echo -e "\t############################################################" $PATH_RS\kissnp2 $read_sets -T -k $k -c $c -g $g -o $prefix -l -b $b # see also options for kissnp with kissnp -h (filtration with max occurrence numbers (-C), filtration with respect to size of contig (-e), possibility to output only unitig (-t instead of -T), ...) if [ $? -ne 0 ] then echo "there was a problem with kissnp2, command line: $PATH_RS\kissnp2 $read_sets -t -k $k -c $c -g $g -o $prefix" exit fi ####################################################################### #################### KISSREADS ####################### ####################################################################### echo echo -e "\t#############################################################" echo -e "\t#################### KISSREADS MODULE #######################" echo -e "\t#############################################################" i=4 #avoid modidy this (or increase this if memory needed by kissread is too high. Min 1. Large i (7-10) decreases memory and increases time). smallk=$(($k-$i-1)) # DON'T modify this. $PATH_RS\kissreads $prefix\_k_$k\_c_$c.fa $read_sets -k $smallk -i $i -O $k -c $c -d $d -n -o $prefix\_k_$k\_c_$c\_coherent -u $prefix\_k_$k\_c_$c\_uncoherent #no need to see kissreads option in theory. if [ $? -ne 0 ] then echo "there was a problem with kissnp2, command line: $PATH_RS\kissreads $prefix\_k_$k\_c_$c.fa $read_sets -k $smallk -i $i -O $k -c $c -d $d -n -o $prefix\_k_$k\_c_$c\_coherent -u $prefix\_k_$k\_c_$c\_uncoherent " exit fi echo -e "\t###############################################################" echo -e "\t#################### DISCOSNPs FINISHED #######################" echo -e "\t###############################################################" ####################################################################### #################### SORT AND FORMAT COHERENT RESULTS ################# ####################################################################### sort -rg $prefix\_k_$k\_c_$c\_coherent | cut -d " " -f 2 | tr ';' '\n' > $prefix\_k_$k\_c_$c\_coherent.fa if [ $? -ne 0 ] then echo "there was a problem with the result sorting, command line: sort -rg $prefix\_k_$k\_c_$c\_coherent | cut -d " " -f 2 | tr ';' '\n' > $prefix\_k_$k\_c_$c\_coherent.fa" exit fi ####################################################################### #################### REMOVE USELESS FILES ################# ####################################################################### if [ $remove -eq 1 ] then echo "I removed " $prefix\_k_$k\_c_$c."*" $prefix\_k_$k\_c_$c\_coherent $prefix\_k_$k\_c_$c\_uncoherent rm -f $prefix\_k_$k\_c_$c.* $prefix\_k_$k\_c_$c\_coherent $prefix\_k_$k\_c_$c\_uncoherent fi echo -e -n "\t ending date=" date echo -e "\t SNPs are stored in \""$prefix\_k_$k\_c_$c\_coherent.fa"\"" echo -e "\t Thanks for using discoSnp - http://colibread.inria.fr/discoSnp/" discoSnp/data_sample/0000755000000000000000000000000012232437324013612 5ustar rootrootdiscoSnp/data_sample/reads_sequence1.fasta0000644000000000000000000052135512227036510017710 0ustar rootroot>read0_contig0_position268_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCT >read1_contig0_position729_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCT >read2_contig0_position653_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAA >read3_contig0_position190_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCT >read4_contig0_position530_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGT >read5_contig0_position177_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGG >read6_contig0_position84_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCA >read7_contig0_position522_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGG >read8_contig0_position15_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCTA >read9_contig0_position654_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAG >read10_contig0_position309_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACC >read11_contig0_position487_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCG >read12_contig0_position449_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACT >read13_contig0_position520_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCA >read14_contig0_position882_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCTCA >read15_contig0_position696_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCT >read16_contig0_position642_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTG >read17_contig0_position354_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATAT >read18_contig0_position326_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCAC >read19_contig0_position323_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCG >read20_contig0_position700_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGG >read21_contig0_position553_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAG >read22_contig0_position553_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTT >read23_contig0_position768_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCA >read24_contig0_position895_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCTCAACGGTATCCGCAA >read25_contig0_position707_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGA >read26_contig0_position232_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTT >read27_contig0_position468_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCG >read28_contig0_position242_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCA >read29_contig0_position588_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACT >read30_contig0_position479_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTA >read31_contig0_position373_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGAC >read32_contig0_position444_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTC >read33_contig0_position652_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGA >read34_contig0_position364_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCC >read35_contig0_position88_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGA >read36_contig0_position127_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATG >read37_contig0_position100_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGG >read38_contig0_position437_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTC >read39_contig0_position518_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGC >read40_contig0_position603_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAG >read41_contig0_position524_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCC >read42_contig0_position840_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTC >read43_contig0_position621_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGA >read44_contig0_position425_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCT >read45_contig0_position133_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTA >read46_contig0_position322_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGG >read47_contig0_position463_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCT >read48_contig0_position693_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAA >read49_contig0_position732_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAG >read50_contig0_position95_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGT >read51_contig0_position128_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGAT >read52_contig0_position556_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGG >read53_contig0_position384_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCT >read54_contig0_position67_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAAC >read55_contig0_position739_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGA >read56_contig0_position475_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGC >read57_contig0_position692_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACT >read58_contig0_position502_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGC >read59_contig0_position258_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAAC >read60_contig0_position766_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGG >read61_contig0_position881_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCTC >read62_contig0_position461_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAA >read63_contig0_position146_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGAT >read64_contig0_position766_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGG >read65_contig0_position606_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAA >read66_contig0_position67_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAAC >read67_contig0_position418_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAAC >read68_contig0_position613_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGC >read69_contig0_position357_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAG >read70_contig0_position470_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTC >read71_contig0_position147_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACT >read72_contig0_position741_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAA >read73_contig0_position831_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAA >read74_contig0_position194_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACG >read75_contig0_position124_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAG >read76_contig0_position798_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAG >read77_contig0_position147_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATA >read78_contig0_position13_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCTATA >read79_contig0_position801_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGC >read80_contig0_position91_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCG >read81_contig0_position843_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTC >read82_contig0_position754_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACG >read83_contig0_position496_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACA >read84_contig0_position774_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGT >read85_contig0_position54_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCA >read86_contig0_position338_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATA >read87_contig0_position245_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTA >read88_contig0_position532_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGA >read89_contig0_position628_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCAC >read90_contig0_position113_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTA >read91_contig0_position417_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTG >read92_contig0_position661_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAG >read93_contig0_position492_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTT >read94_contig0_position452_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTT >read95_contig0_position534_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACT >read96_contig0_position652_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGA >read97_contig0_position864_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCG >read98_contig0_position869_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCAC >read99_contig0_position420_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAA >read100_contig0_position401_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCG >read101_contig0_position454_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTC >read102_contig0_position642_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAAT >read103_contig0_position36_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGT >read104_contig0_position10_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCTATAGCA >read105_contig0_position527_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCC >read106_contig0_position473_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCAC >read107_contig0_position633_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCAC >read108_contig0_position284_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCG >read109_contig0_position468_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCA >read110_contig0_position89_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAG >read111_contig0_position43_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTG >read112_contig0_position121_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTG >read113_contig0_position451_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATA >read114_contig0_position836_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGG >read115_contig0_position136_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGA >read116_contig0_position283_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATA >read117_contig0_position609_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATC >read118_contig0_position122_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGC >read119_contig0_position188_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGC >read120_contig0_position138_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACA >read121_contig0_position434_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATG >read122_contig0_position488_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTC >read123_contig0_position420_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAA >read124_contig0_position842_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGC >read125_contig0_position773_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGG >read126_contig0_position852_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAA >read127_contig0_position718_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTC >read128_contig0_position738_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTG >read129_contig0_position430_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTT >read130_contig0_position595_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTT >read131_contig0_position330_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCG >read132_contig0_position16_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCT >read133_contig0_position873_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATA >read134_contig0_position315_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCA >read135_contig0_position493_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGT >read136_contig0_position773_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGG >read137_contig0_position366_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGA >read138_contig0_position333_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAA >read139_contig0_position787_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCG >read140_contig0_position175_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGC >read141_contig0_position730_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTT >read142_contig0_position866_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTA >read143_contig0_position531_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACT >read144_contig0_position312_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCG >read145_contig0_position416_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTT >read146_contig0_position810_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGC >read147_contig0_position186_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCG >read148_contig0_position183_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGA >read149_contig0_position852_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAA >read150_contig0_position579_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGA >read151_contig0_position203_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGT >read152_contig0_position860_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCA >read153_contig0_position33_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGG >read154_contig0_position711_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACG >read155_contig0_position395_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAAC >read156_contig0_position592_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTT >read157_contig0_position660_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTT >read158_contig0_position827_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAA >read159_contig0_position734_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTT >read160_contig0_position105_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCAT >read161_contig0_position156_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGT >read162_contig0_position565_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGG >read163_contig0_position284_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATAC >read164_contig0_position545_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAA >read165_contig0_position656_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCG >read166_contig0_position569_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCA >read167_contig0_position781_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAG >read168_contig0_position149_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAAT >read169_contig0_position794_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGG >read170_contig0_position32_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCAT >read171_contig0_position173_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCAC >read172_contig0_position863_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGT >read173_contig0_position881_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCTC >read174_contig0_position107_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATA >read175_contig0_position859_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCAT >read176_contig0_position566_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGT >read177_contig0_position510_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAAC >read178_contig0_position398_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACC >read179_contig0_position281_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCA >read180_contig0_position97_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAG >read181_contig0_position406_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTG >read182_contig0_position24_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTT >read183_contig0_position367_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAA >read184_contig0_position400_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTC >read185_contig0_position444_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTC >read186_contig0_position881_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCTC >read187_contig0_position124_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAA >read188_contig0_position507_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTT >read189_contig0_position662_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAA >read190_contig0_position874_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCAT >read191_contig0_position239_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAG >read192_contig0_position71_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATC >read193_contig0_position189_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTC >read194_contig0_position691_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAAT >read195_contig0_position104_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGG >read196_contig0_position113_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTA >read197_contig0_position644_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTT >read198_contig0_position457_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTC >read199_contig0_position197_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCT >read200_contig0_position269_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACC >read201_contig0_position134_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAAT >read202_contig0_position9_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTGCTATAGCCCTTGAACGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTA >read203_contig0_position355_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATG >read204_contig0_position640_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGC >read205_contig0_position772_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTA >read206_contig0_position380_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGT >read207_contig0_position195_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGA >read208_contig0_position682_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATT >read209_contig0_position526_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCC >read210_contig0_position790_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCG >read211_contig0_position880_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCT >read212_contig0_position2_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCTATAGCAATTCCGAC >read213_contig0_position457_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTC >read214_contig0_position92_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATG >read215_contig0_position168_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGAT >read216_contig0_position779_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGAC >read217_contig0_position271_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTC >read218_contig0_position426_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGC >read219_contig0_position366_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGA >read220_contig0_position471_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGT >read221_contig0_position98_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGC >read222_contig0_position665_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGA >read223_contig0_position798_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAG >read224_contig0_position780_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAA >read225_contig0_position855_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCAT >read226_contig0_position782_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGC >read227_contig0_position752_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCT >read228_contig0_position364_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCC >read229_contig0_position572_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCG >read230_contig0_position665_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGA >read231_contig0_position252_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCC >read232_contig0_position604_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAA >read233_contig0_position36_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGT >read234_contig0_position234_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGT >read235_contig0_position261_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAAC >read236_contig0_position782_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGC >read237_contig0_position166_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTAT >read238_contig0_position288_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAA >read239_contig0_position897_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCTCAACGGTATCCGCAACT >read240_contig0_position120_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCAC >read241_contig0_position166_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTAT >read242_contig0_position835_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCAC >read243_contig0_position237_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACT >read244_contig0_position52_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTT >read245_contig0_position420_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGC >read246_contig0_position255_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACA >read247_contig0_position349_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCA >read248_contig0_position470_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCT >read249_contig0_position714_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAAT >read250_contig0_position283_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATA >read251_contig0_position765_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCC >read252_contig0_position273_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGA >read253_contig0_position64_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAA >read254_contig0_position442_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGT >read255_contig0_position859_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCAT >read256_contig0_position445_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATAT >read257_contig0_position338_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGAC >read258_contig0_position340_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAA >read259_contig0_position91_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCG >read260_contig0_position423_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGC >read261_contig0_position713_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATG >read262_contig0_position765_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGC >read263_contig0_position349_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGG >read264_contig0_position502_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGC >read265_contig0_position258_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCG >read266_contig0_position92_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGC >read267_contig0_position320_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGAC >read268_contig0_position167_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATC >read269_contig0_position96_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTA >read270_contig0_position121_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCA >read271_contig0_position747_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGG >read272_contig0_position53_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCAT >read273_contig0_position779_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGAC >read274_contig0_position734_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTT >read275_contig0_position553_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTT >read276_contig0_position797_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGAT >read277_contig0_position270_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGT >read278_contig0_position376_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACT >read279_contig0_position376_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTG >read280_contig0_position313_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCG >read281_contig0_position136_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGA >read282_contig0_position73_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAA >read283_contig0_position705_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATA >read284_contig0_position629_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTG >read285_contig0_position824_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACA >read286_contig0_position193_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTAC >read287_contig0_position648_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTC >read288_contig0_position815_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGT >read289_contig0_position858_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATC >read290_contig0_position401_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCG >read291_contig0_position195_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCT >read292_contig0_position14_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATAGCCCTTGAACGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGT >read293_contig0_position498_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGT >read294_contig0_position77_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTA >read295_contig0_position882_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGAGACATCTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTA >read296_contig0_position855_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCAT >read297_contig0_position442_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACA >read298_contig0_position437_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTC >read299_contig0_position265_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCA >read300_contig0_position143_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGAT >read301_contig0_position562_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAG >read302_contig0_position165_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTA >read303_contig0_position10_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCTATAGCCCTTGAACGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTAT >read304_contig0_position563_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCT >read305_contig0_position185_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCT >read306_contig0_position66_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAA >read307_contig0_position586_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATT >read308_contig0_position808_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGT >read309_contig0_position287_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGA >read310_contig0_position854_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATT >read311_contig0_position443_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCG >read312_contig0_position852_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAA >read313_contig0_position821_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCA >read314_contig0_position591_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTG >read315_contig0_position143_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGAT >read316_contig0_position881_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAGACATCTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAG >read317_contig0_position361_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTG >read318_contig0_position787_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCG >read319_contig0_position281_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCA >read320_contig0_position780_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAA >read321_contig0_position5_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGAATTGCTATAGCCCTTGAACGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGC >read322_contig0_position462_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTA >read323_contig0_position308_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAA >read324_contig0_position580_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCAC >read325_contig0_position25_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCC >read326_contig0_position316_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAA >read327_contig0_position407_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGT >read328_contig0_position57_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGT >read329_contig0_position367_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAA >read330_contig0_position728_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTC >read331_contig0_position847_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCC >read332_contig0_position373_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGAC >read333_contig0_position294_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGT >read334_contig0_position858_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCAT >read335_contig0_position48_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAA >read336_contig0_position613_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGC >read337_contig0_position198_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCA >read338_contig0_position602_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCC >read339_contig0_position810_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCC >read340_contig0_position514_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGG >read341_contig0_position865_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCT >read342_contig0_position278_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAG >read343_contig0_position580_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGG >read344_contig0_position360_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCA >read345_contig0_position256_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAA >read346_contig0_position515_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCA >read347_contig0_position52_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATA >read348_contig0_position610_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCA >read349_contig0_position406_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGT >read350_contig0_position496_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGG >read351_contig0_position856_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCA >read352_contig0_position196_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGAC >read353_contig0_position752_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCT >read354_contig0_position761_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAAC >read355_contig0_position559_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATC >read356_contig0_position93_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACAT >read357_contig0_position450_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTT >read358_contig0_position776_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAAC >read359_contig0_position219_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACA >read360_contig0_position690_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATG >read361_contig0_position728_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGC >read362_contig0_position372_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAA >read363_contig0_position564_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGC >read364_contig0_position411_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCG >read365_contig0_position116_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACT >read366_contig0_position188_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGC >read367_contig0_position326_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCAC >read368_contig0_position363_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTT >read369_contig0_position686_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAG >read370_contig0_position107_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATA >read371_contig0_position851_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAG >read372_contig0_position610_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTA >read373_contig0_position194_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACG >read374_contig0_position856_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCA >read375_contig0_position562_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAG >read376_contig0_position673_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGT >read377_contig0_position179_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGAT >read378_contig0_position17_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCCTTGAACGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACA >read379_contig0_position323_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCG >read380_contig0_position540_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGC >read381_contig0_position308_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACAC >read382_contig0_position157_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTG >read383_contig0_position197_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACC >read384_contig0_position81_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAG >read385_contig0_position745_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGAC >read386_contig0_position399_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGA >read387_contig0_position46_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATT >read388_contig0_position139_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAG >read389_contig0_position206_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTG >read390_contig0_position535_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGA >read391_contig0_position800_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAG >read392_contig0_position392_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATC >read393_contig0_position471_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGT >read394_contig0_position790_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAG >read395_contig0_position248_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGA >read396_contig0_position748_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTG >read397_contig0_position370_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTG >read398_contig0_position859_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCAT >read399_contig0_position259_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACC >read400_contig0_position619_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGC >read401_contig0_position72_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACC >read402_contig0_position312_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCG >read403_contig0_position502_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGC >read404_contig0_position202_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATG >read405_contig0_position311_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGG >read406_contig0_position848_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATC >read407_contig0_position323_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTT >read408_contig0_position756_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAA >read409_contig0_position717_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTT >read410_contig0_position621_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAG >read411_contig0_position207_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGC >read412_contig0_position612_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCC >read413_contig0_position567_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGC >read414_contig0_position389_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTT >read415_contig0_position847_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATA >read416_contig0_position314_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACT >read417_contig0_position859_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATT >read418_contig0_position135_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAA >read419_contig0_position811_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCC >read420_contig0_position54_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTT >read421_contig0_position797_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGAT >read422_contig0_position575_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAA >read423_contig0_position290_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTA >read424_contig0_position589_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTT >read425_contig0_position811_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCC >read426_contig0_position488_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTC >read427_contig0_position158_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGC >read428_contig0_position237_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGAC >read429_contig0_position547_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAA >read430_contig0_position479_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTA >read431_contig0_position758_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATG >read432_contig0_position487_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCG >read433_contig0_position178_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGA >read434_contig0_position682_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATT >read435_contig0_position331_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACG >read436_contig0_position733_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTT >read437_contig0_position443_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACAT >read438_contig0_position166_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTAT >read439_contig0_position699_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGG >read440_contig0_position752_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCT >read441_contig0_position485_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCA >read442_contig0_position398_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACC >read443_contig0_position484_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAG >read444_contig0_position857_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCC >read445_contig0_position798_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAG >read446_contig0_position294_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGA >read447_contig0_position743_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAG >read448_contig0_position381_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTT >read449_contig0_position842_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATT >read450_contig0_position96_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTA >read451_contig0_position788_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTC >read452_contig0_position660_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGG >read453_contig0_position818_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCA >read454_contig0_position124_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAG >read455_contig0_position602_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCC >read456_contig0_position95_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGT >read457_contig0_position406_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGT >read458_contig0_position382_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTT >read459_contig0_position181_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCA >read460_contig0_position288_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAA >read461_contig0_position230_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAA >read462_contig0_position90_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTT >read463_contig0_position681_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTC >read464_contig0_position128_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGG >read465_contig0_position761_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAAC >read466_contig0_position76_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTG >read467_contig0_position816_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGA >read468_contig0_position374_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACG >read469_contig0_position184_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAG >read470_contig0_position615_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCT >read471_contig0_position561_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCC >read472_contig0_position146_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTT >read473_contig0_position600_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGAC >read474_contig0_position243_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCC >read475_contig0_position38_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTC >read476_contig0_position636_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAG >read477_contig0_position88_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGA >read478_contig0_position684_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTA >read479_contig0_position163_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTT >read480_contig0_position47_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTA >read481_contig0_position102_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACT >read482_contig0_position118_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTA >read483_contig0_position290_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGA >read484_contig0_position33_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGG >read485_contig0_position604_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTA >read486_contig0_position703_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATT >read487_contig0_position419_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAA >read488_contig0_position383_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCG >read489_contig0_position838_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGC >read490_contig0_position759_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGG >read491_contig0_position824_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACA >read492_contig0_position142_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATA >read493_contig0_position766_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGG >read494_contig0_position556_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGG >read495_contig0_position267_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGC >read496_contig0_position88_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAA >read497_contig0_position402_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGA >read498_contig0_position584_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCT >read499_contig0_position330_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGC >read500_contig0_position171_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGG >read501_contig0_position274_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCG >read502_contig0_position735_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTC >read503_contig0_position152_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAA >read504_contig0_position711_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACG >read505_contig0_position869_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCAC >read506_contig0_position862_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCG >read507_contig0_position830_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGC >read508_contig0_position763_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGG >read509_contig0_position885_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGTTGAGACATCTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTA >read510_contig0_position130_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCG >read511_contig0_position279_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGT >read512_contig0_position310_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAG >read513_contig0_position532_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGA >read514_contig0_position384_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCT >read515_contig0_position162_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCG >read516_contig0_position514_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAA >read517_contig0_position214_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCG >read518_contig0_position325_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCA >read519_contig0_position329_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCT >read520_contig0_position246_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGT >read521_contig0_position9_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCTATAGCAA >read522_contig0_position298_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGT >read523_contig0_position683_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAAT >read524_contig0_position672_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAG >read525_contig0_position806_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAAT >read526_contig0_position257_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGG >read527_contig0_position410_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGC >read528_contig0_position765_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCC >read529_contig0_position536_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAA >read530_contig0_position559_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATC >read531_contig0_position818_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCA >read532_contig0_position650_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAG >read533_contig0_position637_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCA >read534_contig0_position699_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGG >read535_contig0_position761_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGAT >read536_contig0_position85_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTA >read537_contig0_position207_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGC >read538_contig0_position883_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCTCAA >read539_contig0_position91_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCG >read540_contig0_position659_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGG >read541_contig0_position700_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGG >read542_contig0_position631_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCC >read543_contig0_position164_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTT >read544_contig0_position722_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTAT >read545_contig0_position822_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAA >read546_contig0_position880_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCT >read547_contig0_position150_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATC >read548_contig0_position112_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTAC >read549_contig0_position877_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CATCTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTC >read550_contig0_position727_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCA >read551_contig0_position658_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTT >read552_contig0_position405_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTG >read553_contig0_position640_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGC >read554_contig0_position604_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTA >read555_contig0_position603_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCT >read556_contig0_position278_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAG >read557_contig0_position214_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCG >read558_contig0_position863_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGT >read559_contig0_position50_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACA >read560_contig0_position143_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGAT >read561_contig0_position868_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACT >read562_contig0_position474_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCG >read563_contig0_position343_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACT >read564_contig0_position792_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCG >read565_contig0_position200_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAG >read566_contig0_position62_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGAC >read567_contig0_position456_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTT >read568_contig0_position784_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTA >read569_contig0_position798_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGA >read570_contig0_position730_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTT >read571_contig0_position669_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGAT >read572_contig0_position232_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTT >read573_contig0_position826_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGA >read574_contig0_position399_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGA >read575_contig0_position425_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCT >read576_contig0_position701_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAG >read577_contig0_position118_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTA >read578_contig0_position642_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTG >read579_contig0_position127_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAG >read580_contig0_position662_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAA >read581_contig0_position548_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAAC >read582_contig0_position729_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCT >read583_contig0_position350_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCAC >read584_contig0_position553_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTT >read585_contig0_position772_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTA >read586_contig0_position236_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTT >read587_contig0_position783_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTAT >read588_contig0_position72_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCA >read589_contig0_position220_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTAC >read590_contig0_position735_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTC >read591_contig0_position545_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTG >read592_contig0_position598_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTT >read593_contig0_position344_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCAC >read594_contig0_position576_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATAC >read595_contig0_position523_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTC >read596_contig0_position31_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATC >read597_contig0_position762_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAA >read598_contig0_position716_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACT >read599_contig0_position828_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAAC >read600_contig0_position690_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATG >read601_contig0_position536_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAA >read602_contig0_position49_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACAT >read603_contig0_position608_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACA >read604_contig0_position880_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGACATCTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGC >read605_contig0_position864_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCG >read606_contig0_position188_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGC >read607_contig0_position473_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCAC >read608_contig0_position88_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAA >read609_contig0_position735_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTC >read610_contig0_position685_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGA >read611_contig0_position798_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGA >read612_contig0_position48_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATA >read613_contig0_position622_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGG >read614_contig0_position730_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTT >read615_contig0_position252_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTC >read616_contig0_position200_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGT >read617_contig0_position703_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATT >read618_contig0_position499_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCG >read619_contig0_position839_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCG >read620_contig0_position208_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCC >read621_contig0_position780_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGA >read622_contig0_position89_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTA >read623_contig0_position245_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTA >read624_contig0_position139_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAAC >read625_contig0_position445_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATAT >read626_contig0_position798_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGA >read627_contig0_position830_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAA >read628_contig0_position372_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGA >read629_contig0_position438_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCG >read630_contig0_position673_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGT >read631_contig0_position339_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGA >read632_contig0_position743_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAG >read633_contig0_position695_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTA >read634_contig0_position564_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTT >read635_contig0_position566_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGT >read636_contig0_position600_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGC >read637_contig0_position495_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAAC >read638_contig0_position585_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAAT >read639_contig0_position450_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATAT >read640_contig0_position409_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTG >read641_contig0_position468_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCA >read642_contig0_position26_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCG >read643_contig0_position737_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTT >read644_contig0_position730_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTG >read645_contig0_position681_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGT >read646_contig0_position599_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCT >read647_contig0_position861_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCC >read648_contig0_position72_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCA >read649_contig0_position3_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCTATAGCAATTCCGA >read650_contig0_position153_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAA >read651_contig0_position1_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGTCGGAATTGCTATAGCCCTTGAACGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCC >read652_contig0_position860_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCA >read653_contig0_position41_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGT >read654_contig0_position826_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACA >read655_contig0_position545_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAA >read656_contig0_position454_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTC >read657_contig0_position109_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCAC >read658_contig0_position493_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCA >read659_contig0_position817_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAG >read660_contig0_position749_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGT >read661_contig0_position139_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAG >read662_contig0_position686_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATA >read663_contig0_position259_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACC >read664_contig0_position243_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATC >read665_contig0_position286_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGAC >read666_contig0_position81_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAG >read667_contig0_position249_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAA >read668_contig0_position251_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCA >read669_contig0_position839_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCG >read670_contig0_position577_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATA >read671_contig0_position583_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGA >read672_contig0_position665_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGA >read673_contig0_position478_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAAC >read674_contig0_position627_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACA >read675_contig0_position350_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCAC >read676_contig0_position342_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACG >read677_contig0_position714_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGA >read678_contig0_position791_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTA >read679_contig0_position830_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAA >read680_contig0_position633_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTA >read681_contig0_position367_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACA >read682_contig0_position375_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTC >read683_contig0_position377_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGAC >read684_contig0_position344_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCAC >read685_contig0_position563_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCA >read686_contig0_position665_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGA >read687_contig0_position852_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATT >read688_contig0_position165_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTA >read689_contig0_position244_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCA >read690_contig0_position852_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAA >read691_contig0_position121_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCA >read692_contig0_position119_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACT >read693_contig0_position70_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTA >read694_contig0_position840_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGA >read695_contig0_position567_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTC >read696_contig0_position6_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCTATAGCAATTC >read697_contig0_position354_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTT >read698_contig0_position262_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTG >read699_contig0_position730_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTT >read700_contig0_position367_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACA >read701_contig0_position250_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCAT >read702_contig0_position178_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGA >read703_contig0_position752_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCT >read704_contig0_position343_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGA >read705_contig0_position393_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCAT >read706_contig0_position502_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGC >read707_contig0_position367_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACA >read708_contig0_position328_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGC >read709_contig0_position875_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGA >read710_contig0_position669_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGAT >read711_contig0_position579_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGA >read712_contig0_position383_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTC >read713_contig0_position825_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAA >read714_contig0_position394_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAA >read715_contig0_position855_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCG >read716_contig0_position444_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTC >read717_contig0_position36_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGT >read718_contig0_position342_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACG >read719_contig0_position652_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACA >read720_contig0_position175_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTC >read721_contig0_position18_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCCTTGAACGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAG >read722_contig0_position88_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAA >read723_contig0_position819_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCAC >read724_contig0_position739_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGA >read725_contig0_position372_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAA >read726_contig0_position236_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTT >read727_contig0_position425_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCG >read728_contig0_position135_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAA >read729_contig0_position177_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGG >read730_contig0_position636_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAG >read731_contig0_position192_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTA >read732_contig0_position807_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTA >read733_contig0_position487_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCG >read734_contig0_position218_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTT >read735_contig0_position639_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCG >read736_contig0_position611_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCAC >read737_contig0_position873_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAA >read738_contig0_position851_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAG >read739_contig0_position884_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCTCAAC >read740_contig0_position354_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTT >read741_contig0_position769_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAG >read742_contig0_position621_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAG >read743_contig0_position637_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCA >read744_contig0_position193_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTAC >read745_contig0_position418_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAAC >read746_contig0_position194_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACG >read747_contig0_position872_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATAC >read748_contig0_position485_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTA >read749_contig0_position887_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACCGTTGAGACATCTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGC >read750_contig0_position620_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGA >read751_contig0_position76_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTAT >read752_contig0_position86_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACT >read753_contig0_position672_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTA >read754_contig0_position247_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGAT >read755_contig0_position224_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCC >read756_contig0_position445_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATAT >read757_contig0_position58_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTA >read758_contig0_position797_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGA >read759_contig0_position171_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTT >read760_contig0_position426_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTA >read761_contig0_position458_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACAC >read762_contig0_position619_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGC >read763_contig0_position282_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCT >read764_contig0_position821_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCA >read765_contig0_position424_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCC >read766_contig0_position277_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGAT >read767_contig0_position563_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCA >read768_contig0_position246_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATT >read769_contig0_position226_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCC >read770_contig0_position398_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAG >read771_contig0_position555_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGA >read772_contig0_position666_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGG >read773_contig0_position118_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTA >read774_contig0_position684_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAA >read775_contig0_position687_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAA >read776_contig0_position544_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCA >read777_contig0_position813_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGT >read778_contig0_position741_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGG >read779_contig0_position139_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAAC >read780_contig0_position26_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCG >read781_contig0_position411_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCG >read782_contig0_position805_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAA >read783_contig0_position119_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACT >read784_contig0_position679_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGG >read785_contig0_position270_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGT >read786_contig0_position550_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAA >read787_contig0_position785_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTT >read788_contig0_position327_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACG >read789_contig0_position660_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGG >read790_contig0_position878_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACATCTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTT >read791_contig0_position741_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAA >read792_contig0_position806_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAAT >read793_contig0_position131_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCC >read794_contig0_position358_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACG >read795_contig0_position336_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTG >read796_contig0_position620_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGA >read797_contig0_position230_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAG >read798_contig0_position779_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGAC >read799_contig0_position571_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGA >read800_contig0_position490_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAG >read801_contig0_position807_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATC >read802_contig0_position207_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGT >read803_contig0_position773_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGG >read804_contig0_position130_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGA >read805_contig0_position10_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCTATAGCCCTTGAACGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTAT >read806_contig0_position9_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTGCTATAGCCCTTGAACGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTA >read807_contig0_position799_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGA >read808_contig0_position36_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGT >read809_contig0_position826_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGA >read810_contig0_position847_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCC >read811_contig0_position163_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGT >read812_contig0_position308_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACAC >read813_contig0_position696_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCA >read814_contig0_position402_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGA >read815_contig0_position477_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACC >read816_contig0_position276_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGG >read817_contig0_position734_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTT >read818_contig0_position639_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCG >read819_contig0_position681_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGT >read820_contig0_position616_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCAT >read821_contig0_position803_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGT >read822_contig0_position235_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTT >read823_contig0_position656_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGCCAAAATTCTGTCCACAAGCG >read824_contig0_position346_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTC >read825_contig0_position756_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAA >read826_contig0_position119_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACT >read827_contig0_position365_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAG >read828_contig0_position246_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGT >read829_contig0_position361_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATC >read830_contig0_position547_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAG >read831_contig0_position267_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGC >read832_contig0_position501_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAG >read833_contig0_position866_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTG >read834_contig0_position46_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATT >read835_contig0_position806_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAA >read836_contig0_position455_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCT >read837_contig0_position443_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACAT >read838_contig0_position145_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTA >read839_contig0_position158_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTG >read840_contig0_position458_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCA >read841_contig0_position781_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAG >read842_contig0_position381_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTT >read843_contig0_position32_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCAT >read844_contig0_position351_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTG >read845_contig0_position198_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTC >read846_contig0_position603_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCT >read847_contig0_position480_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAA >read848_contig0_position100_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGG >read849_contig0_position297_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGG >read850_contig0_position751_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTT >read851_contig0_position542_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGC >read852_contig0_position196_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTC >read853_contig0_position40_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTG >read854_contig0_position570_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAA >read855_contig0_position172_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACT >read856_contig0_position242_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCC >read857_contig0_position204_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTA >read858_contig0_position42_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGG >read859_contig0_position198_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCA >read860_contig0_position756_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAA >read861_contig0_position663_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACA >read862_contig0_position103_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTC >read863_contig0_position327_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACG >read864_contig0_position521_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGC >read865_contig0_position111_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACT >read866_contig0_position706_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGAT >read867_contig0_position106_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAG >read868_contig0_position433_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAG >read869_contig0_position400_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTC >read870_contig0_position299_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTC >read871_contig0_position156_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGT >read872_contig0_position134_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAA >read873_contig0_position893_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGGATACCGTTGAGACATCTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCAC >read874_contig0_position340_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGG >read875_contig0_position699_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGG >read876_contig0_position612_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACA >read877_contig0_position225_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCT >read878_contig0_position735_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGG >read879_contig0_position634_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTT >read880_contig0_position88_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGA >read881_contig0_position412_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGT >read882_contig0_position194_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACG >read883_contig0_position553_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTT >read884_contig0_position74_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAG >read885_contig0_position673_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTT >read886_contig0_position802_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATG >read887_contig0_position581_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGG >read888_contig0_position570_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAA >read889_contig0_position343_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGA >read890_contig0_position810_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGC >read891_contig0_position167_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATC >read892_contig0_position894_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTCCGCATTGCGTCTACTTATAAGATGTCTCAACGGTATCCGCA >read893_contig0_position654_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCC >read894_contig0_position307_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACA >read895_contig0_position692_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAA >read896_contig0_position427_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGG >read897_contig0_position459_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACA >read898_contig0_position243_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCC >read899_contig0_position56_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTC >read900_contig0_position158_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGC >read901_contig0_position169_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGA >read902_contig0_position469_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCC >read903_contig0_position266_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACC >read904_contig0_position724_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATT >read905_contig0_position453_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCA >read906_contig0_position125_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAA >read907_contig0_position283_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATA >read908_contig0_position854_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATT >read909_contig0_position565_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTG >read910_contig0_position301_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATAC >read911_contig0_position615_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCA >read912_contig0_position167_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGCCGGGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATC >read913_contig0_position629_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTG >read914_contig0_position121_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTG >read915_contig0_position151_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCA >read916_contig0_position218_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAG >read917_contig0_position834_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACG >read918_contig0_position131_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGAC >read919_contig0_position314_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGTTCCGTCCGGTTAAGCGTGACAGTCCCAGTGAACCCACAAACCGTGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGC >read920_contig0_position91_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACGATCAAGTGCACTTCCACAGAGCG >read921_contig0_position626_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAA >read922_contig0_position807_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATC >read923_contig0_position329_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGCGTGAAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCT >read924_contig0_position591_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTG >read925_contig0_position636_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATTGCCACTGC >read926_contig0_position401_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGCGTGAAAACTGGTGCGCCGGTGTCTG >read927_contig0_position825_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACAC >read928_contig0_position16_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCT >read929_contig0_position360_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGT >read930_contig0_position574_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAG >read931_contig0_position553_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAG >read932_contig0_position0_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCTATAGCAATTCCGACGG >read933_contig0_position789_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGC >read934_contig0_position670_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGA >read935_contig0_position813_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGT >read936_contig0_position86_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACT >read937_contig0_position270_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACAC >read938_contig0_position216_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAG >read939_contig0_position245_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCCAG >read940_contig0_position809_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCG >read941_contig0_position731_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGT >read942_contig0_position243_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTCCGTCCGGTTAAGCGTGACAGTCCC >read943_contig0_position156_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TACAGCAAAACGATCAAGTGCACTTCCACAGAGCGCGGTAGAGACTCATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGT >read944_contig0_position546_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAA >read945_contig0_position486_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGC >read946_contig0_position628_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAATT >read947_contig0_position554_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTC >read948_contig0_position731_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACTGCCAAAATTCTGTCCACAAGCGTTTTAGTTCGCCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTT >read949_contig0_position300_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACG >read950_contig0_position808_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCA >read951_contig0_position511_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAA >read952_contig0_position100_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGG >read953_contig0_position563_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCT >read954_contig0_position718_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTC >read955_contig0_position203_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGT >read956_contig0_position399_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCT >read957_contig0_position426_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGTCGTTTATGCTTTCGGC >read958_contig0_position550_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACAT >read959_contig0_position219_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTATGCCTTCTCGAGTTC >read960_contig0_position853_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGTGTCCACCAACACAACGCTATCGGGCGATTCTATAAGATTC >read961_contig0_position800_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTCTCACCCGCGCTATTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCG >read962_contig0_position61_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACC >read963_contig0_position110_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GGTGGATGAGTCTCTACCGCGCTCTGTGGAAGTGCACTTGATCGTTTTGCTGTAGAAAAAACTTAATAAACAGAATGCCGATGAAGGCACTACTGTACTA >read964_contig0_position737_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTT >read965_contig0_position576_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATAC >read966_contig0_position362_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGT >read967_contig0_position212_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGAGCTGC >read968_contig0_position360_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGATGGCTGTCCTTGGAGTCATACGCAAGAAGGATGGTCTCCAGACACCGGCGCACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGT >read969_contig0_position204_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TCCACCCGGCAGCTCTGTAATAGGGACTAAAAAAGTGATGATAATCATGAGTGCCGCGTTATGGTGGTGTCGGATCAGAGCGGTCTTACGACCAGTCGTA >read970_contig0_position57_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCT >read971_contig0_position481_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGA >read972_contig0_position879_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GACATCTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCT >read973_contig0_position26_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CGCTACATGCACGATACCAAGTTATGTATGGACCGGGTCATCAATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCT >read974_contig0_position413_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CACCAGTTTTCACGCCGAAAGCATAAACGACGAGCACATATGAGAGTGTTAGAACTGGACGTGCGGTTTCTCTGCGAAGAACACCTCGAGCTGTTGCGTT >read975_contig0_position495_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAAGCAAAAGTGATATGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGT >read976_contig0_position554_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 GAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAAGCGCTTACTGTTGACTGTCTAGGGATACAGCGAAAGCGGCAGTCGTTGAA >read977_contig0_position323_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 AAAACTGGTGCGCCGGTGTCTGGAGACCATCCTTCTTGCGTATGACTCCAAGGACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCG >read978_contig0_position876_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ATCTTATAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCC >read979_contig0_position604_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATGTTTTGGCGCAGTTAGTCACAGGGGGAGCCCCTGCCTACAAAAA >read980_contig0_position647_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACAGAATTTTGGCAGTGGCAATTAATCTCTAATGATGTGATATTAGGGTCTAAAATGTAAGAATTCGGTGAGTTAGATTGGACAAGGGGATCCGAAGATG >read981_contig0_position495_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAAC >read982_contig0_position68_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AATAGGTTATAGCCTTGTAGTTAACATGTAGCCCGGCCCTATTAGTACAGTAGTGCCTTCATCGGCATTCTGTTTATTAAGTTTTTTCTACAGCAAAACG >read983_contig0_position567_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GCTTTCGCTGTATCCCTAGACAGTCAACAGTAAGCGCTTTTTGTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTC >read984_contig0_position490_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AGAACACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAG >read985_contig0_position712_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CCGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGA >read986_contig0_position813_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 ACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGGTATGGAAGCTAATAGCGCGGGTGAGAGGGTAATCAGCCGT >read987_contig0_position269_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACC >read988_contig0_position773_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 AAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCGCAGGTGG >read989_contig0_position785_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TTAGCTTCCATACCACCTGCGGCCATCCATTAAGATCCGCTGCTCCTCACGAAAAAAGAATTAATAAGAAGTCCCGTAACATGCGGATTTGGTAGTCGTT >read990_contig0_position494_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CACCTCGAGCTGTTGCGTTGTTGCGCTGCCTAGATGCAGTGTCGCACATATCACTTTTGCTTCAACGACTGCCGCTTTCGCTGTATCCCTAGACAGTCAA >read991_contig0_position711_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 CGTAACATGCGGATTTGGTAGTCGTTATAGACAACTTTACTGGGGCGAACTAAAACGCTTGTGGACAGAATTTTGGCAGTGGCAATTAATCTCTAATGAT >read992_contig0_position870_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TAAGTAGACGCAATGCGGAATCTTATAGAATCGCCCGATAGCGTTGTGTTGGTGGACACGGCTGATTACCCTCTCACCCGCGCTATTAGCTTCCATACCA >read993_contig0_position217_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACACCACCATAACGCGGCACTCATGATTATCATCACTTTTTTAGTCCCTATTACAGA >read994_contig0_position442_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 TGTGCGACACTGCATCTAGGCAGCGCAACAACGCAACAGCTCGAGGTGTTCTTCGCAGAGAAACCGCACGTCCAGTTCTAACACTCTCATATGTGCTCGT >read995_contig0_position627_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 TGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATCACATCATTAGAGATTAAT >read996_contig0_position270_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACAGCCATCACGGTTTGTGGGTTCACTGGGACTGTCACGCTTAACCGGACGGAACTCGAGAAGGCATACGACTGGTCGTAAGACCGCTCTGATCCGACAC >read997_contig0_position766_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 CCCCAGTAAAGTTGTCTATAACGACTACCAAATCCGCATGTTACGGGACTTCTTATTAATTCTTTTTTCGTGAGGAGCAGCGGATCTTAATGGATGGCCG >read998_contig0_position14_M0_I0_D0_NG0______er0__indel0__rgeom0_rev1 ACTAATAGGGCCGGGCTACATGTTAACTACAAGGCTATAACCTATTGATGACCCGGTCCATACATAACTTGGTATCGTGCATGTAGCGTTCAAGGGCTAT >read999_contig0_position609_M0_I0_D0_NG0______er0__indel0__rgeom0_rev0 GTAGGCAGGGGCTCCCCCTGTGACTAACTGCGCCAAAACATCTTCGGATCCCCTTGTCCAATCTAACTCACCGAATTCTTACATTTTAGACCCTAATATC discoSnp/data_sample/reads_sequence2.fasta.gz0000644000000000000000000003221112227036510020314 0ustar rootroot%kQreads_sequence2.fasta}]Hr5"%~eB?O|ob{/}*T!AV6ݝݧCT2322o??8?oz/~?_>;} mox߿xv{o>/_?s7!U>CvK7@f/@! ho>7dyΠZz?fr ?0d` 9Bwow /|!|5<2{z ju՞۳ p^2şC8zv4q # '@PvTv8f|'L'OUz~CM5?U}֟:)-h!F_pU7c v?C|87J k:({`ҙ{·ۇbl fO}J5W5W }v7٥eg3g7ݥ1[^`™]Zn8왇9a^O;AVVi oto5Y}-W3m~ȩ♼ۥk˲:񼤯c~1 ;f k^: 1b,D% %yЪ,/E 쭱*[[nϮ]0t'I5ZzC5`. Z٧jDV m.!tG%WQ;k{:MX+A!%1>[xBz Z ^&+쮲 k5/c<<7#r%Ų5[β ( 5[E v^^ kΪp`5շ9MX* o$"+pLEYšǭs>2=7J5[EH_M@}2T[' Y||JV+Ƃ!5[VzrgveqK]0kWšǭ,[m.V놄)ॸU/$&4 ޏ>Qšǭp݃#+G * [_#9%$liځ}BudJ؃|% 38IgV#NXj to$y[L&ّH7Ēb@S )mIwk$U j*&vd>_ +VliMӚ5YM--ɷtOXui8wq^JFkmpJ\Յڄ9k=% (+:)e+89AKZ-6&7H`ƹ䒅򪷕.2.F3%`ÿ^OL/g`Iji9v, P.,)4s۟p a&O\yd%PYXNK?UojXbqV+=`CDá]]+S]+KF]a&, mmne<`QN_n`6`ኻ>\mCzBXn.gl%6QTmX6FrGK7.ڠ)`,)~n-\M,?w%.Ykvn,^> 8+X`U);L+6,_gm֋7\$K◢Vt Hc`2 D$z, ܔ3v%M0:Y`߸b DWu#嫈Gp]B y E/`%QљWa,)eI*tL"ؚp'G X j>RX JNX^JS $~i3>Rǀ $~ie#Kz10M2Q3tĄUӱҡXR<9XbqQm+A<~"x80O 5hC,QpӾy;KL1"MyQYi%c`"ePjV j% `dba{}J+O 6s Xwg$ĄhF.A%.^rlG? XBer/ `Y۟k+6qI4 ,ia ćCsq*j"av`I%6~B>$I.qǓT&')F0`%`b:, ^ϳQ &` yIFd19kvÊ|k`uV &tH>KM(eZ&[,X4GW7z_BZ@,8zq.!%VZu-{%/m^#y:꿚XptEhktk׬//5&%ʫ\ǯFKp>JlړV}C$XqX\M,8*m9OxOlwWeZ<} f*/Xl~Q `{EkOQkq\8pH[3)dY#VICʚM ,szT&.G-%qO ̀pT\cXLJ.!+3i<+Jw`#D}6`&9*^`M֕a4rK*8;[t(Xb^E 8:m3g [ D>=Y-I 8^^(*zۖX4J րpt0WL^Ύ=j]%eԆy;%̚ K􇚗sHophI7 8RY,5h{n=L!ZOF /?|.eK`FH vQgbщ쬫,GKT W?`%VZ,봠]OqԊuD< D-yp/qhs>`^+ /1ErMq`F8*q[:c L]-ԂsHḱi(, `Եd=%N~V0KJ0s}h7,Qq(6(ChnL,!jO$iЍ^]ax&N҄]lܖoj%Jz17I,!y%sv,!*!V杈XqH6޻X"мn_)(/n-;/Vq3^r%^RvPln$`Q dY!Z2F3,4DGQE2Af͸љ0XjGUWo8qT'].%N(*1EX LK)AK`X.HxQ3KUg'Kd,sZM lw,9}, %V6\U\~:Q~!%Vk^g_ċt= %EW\LI5ONeԨ7" ߖ) !d }qXB!V*-չLWJrvK(DEk`sI%̚5^$fe+A_%M`G.)#<~0%MV)dQMgČu|Sj* NJ4qo.N"1hjIS@<v֙qwqt)ZEbQ+bq[} vK8Tq`n 3nӄG .#6"!yE%JzE uKj0%9}9$Y)y; qЌ DX⑰3ebܤQ%zZ+YRiʏe UefR˅6\^lK(DudSpXwxb;DmCl',?ڏ S,k `IҖe^Xqm*4U/3M%25{k1%2a疽I0q@/V+iv|>|!^m3SE8jgDg|qQ!™?H`ǥG0%̚`W;KukˀXqH&uW,_'Fd0l)WA<{+_=Xlud L;}ZDؠȐeS ,1⨴0[qhyADqZ׀=u%^ϵ W0E , _~N *%/›[Ĉ# ?ۑ|7u*6s]}XdaL6Vq`K|8*eYΖ'4,%hX2,%g*pʪиdKZ `Q pUhK|8=X,3=jp"({WS7rpͿ@/0D0O,hE56 $` יwT6`Vsqu RDá`>r\`0U+/;.^0RrpX[՞M sP[[zt'}˫`ֶurx%Ѫ[:a GxU3$KDgeB,!pJ+6`'Lg?AKj05M`6^*^+ph|L'8J֩(>g9^Mu5K*09.Md0``»;`2l-N R,3␘.qg`6sN|T`ʔJf$z1W#J!-:eFJYC ;-z,c> 1ZqXv&,YɬM Ro=%b+ RDe+-Eᬧf+ `yDcK~SєGʼn""؆pḦ́_ieWC|8.=>D,!j1ET,!*''IY89*!u?l_Ѷֱ+XRi_H^+ 4>6`@Ƅ#JW`I;ꆒ8qtrrk`|Zu'%d/| HӔ'j+,-$X4}u Vm q.~ZNQ\<բ=*qVn`t_HP'. mǁ,J!8SHK`] Fxqԝ6MxqT OE0qw=_#^ ʍB?%5Q jWDm,Z~D0ͥ= Fb![<]4#IEX&LX&uk(,ĥ?MN`G#^]N!vyD0`z9LJ`%*MЙo:,ii)`*u`$ev;S7m.Nh.kX>0X)}YqhË%D1XTdY+۠%Qtr=/)%ֆ䰰tx+f,d>Xq <"B÷mˬ8ևͳ~YdL ~- W$ї  "rLKh,kk4\D'l:myya~,q^0ל 1NKCqhm:ӌyv,`̳ 1%Vg.BOVKR)c0X2ʬ*yo`%TMF_2ayA,,i)JcQdJer>ĉC$\ZC8.5[Xb[KDW{Co`IL5]'2~r',[&;211VRx7`qBI@KydX>(DMI@Âa` =& Q7i4Ċ{bq8]Jȕ DK8Zm77`IL3kTA~D⽯.,3od  ݶxK"X'zbP9!,qTu`I $`e^4@G`C4U>eĊԶaٽv'h=E3-OrL&6XQE ˵.lTG}` X`ײI%M0 0)6:&̊$:x&!j+oZevu6 L\ 2,3:^K8$OXLm6`Բ@+czdfЮrbj6`gmW!/%2߸ř%V_T XSf֢S+9ZbQiM]ji%~}drǥl ^yň{eBDuc8eɈ+ `-Qp(g.]Et%FB{90T`W*:dq4 ѝ-14qXR#Fe5ǀd`^<]58ZbiO0F7%2FK K%:Dmֱ1}iK`XIܻ ,3⨴eŗEBe2WjG[}NRX!&]#~IXJTڂ/9K5%K*^[GM`ViE8v%L }$%Vg 7,`I")XR)ൣ2f|h1/eEś^/&t-ZhK2e`,s-VLe7" `IS^0i))#\2q\gԸÛ?<Պu.X2 &)<}xkm&-pta쁕G^|[,qh{\r'r`yя 7)eC\ {̀xqWM8;oXq9_YHLJ ؇W%{nlXӜQ5;%K,S`(J[D7D1"YXB!J RKJ4r@otmHys>L({K52UAK8ZM/ꛪQ {SJ 90=fתlaލ%`%dҽTD^@8T$pVLy$K^aYiDѫXQlZ 5\,^Zsھ)!.vKh .W%ąCGp*$.{۟X77˭tNR6[ңG%.g͡hd(NDQSe"W YiX6,X0OOj ߳( G4laқ5,YjݫaK&U2Y̅CKˋvk`ҷIY_,\:`I39%CE/rxpA᫂`~CSf $KfY\f߻Vi=dO`"wb.jG~9, `dB8؝&=H56 XbDya:{,՚ߟBK,8z9:,iOPXIEDzn0UXnoIDxeT`GG-m<K&˹l`՛D.x8[Kl|EA ^gL`G':fRZ%T{ֻJ vTa_G<8.g ` R f`7JŬGy\sǎXpT ӗ<_y ,hťn1v#` k;ϦԀXpHn;ڛ~I, `Zέ;֎p(lJ&K`hGVXS"ٌ P,!xVf׽ZK\8jMG_y%2m9˟%K`G A:bqъbq 1]e8,J&6by.HBAӗͪ]%V*sXb!MEvNgpHAH;|GĆm$fe4'l(:7ֱ&X⃨KΣd((=%`ֈTੱӌwp﫹[%BDkKG]+U\<,&ń.y9y;" )&'>mK8DJO/!9q5K8J;%&Y Wg˻DơZ/TMF,"^4&\੏ċ㬹䄏Qf6bX"P2)އ6K̤[F͔"ċFog9튲4ŤGӡJTJK+IXbU,`CLTg_Gn3+ņ<:wjO`ILtm},`vXqԪ1ʏ`ƃ/X`.0-(i{[;eV 0Lu,ߐWIz`( g}fgXRړu{syj4 X"7˾2 o>.Q`d`v؝=qږߌEec`x{#21>/u|x1kJ2#K#Jp 3,*\tN&ErO8| T'zb:Ո`I&΄\%HLgmSwImMzK8z Jl`IX}6#I f`Iwi)VG8;#FJW J4ZS#\JS@|8zQuxK(lMir >fR&Qyp(C*i~zl )0sf`BJͪt `B06x-)v:Y ,p[/%S``׳V"%F&9L"1h4-j9` xҤU 0*73C8B(Ջ bNkΪ `%"ǼEg%=0rֹa)0޺+W㋀JցUZ׶9~Xb(Lf#]HAxuBOl8.g)\Al8+&6q'P%S̪FYySnXR8&!OiYEw\` ӗ.f\Wb^%Vs`f)6KTl'{XLQLFh{dL,jJ Q.ޘ߸VDgK: DEn%( b9%ҝWb!119q Vp,ۦ0U*)&.F˽6ᔚ`Cs+ڙ{<ՊQ[ڟ5:ƸD!x*fXb嫼`q9u/x{?WXXbQ+iy:|K8:z%Vu+Z)nĵ`/%Ltdq%%Vi^>Ka@>m>ĈF52 LOOO'X0]ž ,qY1pH K4bӤ{PgM?E +ҢTbU Q1d1]%;׏K4DX"?;3Cl5Ggw|fI-Jӓ%*Dmњs ~[pĉw~xG"NU!^GD1˧ 8qE|czykk+y26ii-X2ɬ|2 %` k`ckG#X#EMu>֔#a%VE]IggTI}%V6TS* 1`!/+h3PKJZ_GU.1<]U(X6ɬ q R F8?&%Ve=]' S}yf6 ^8=-Z`<:_*Á,'UU}5+j4Fg%jK8|>V2Ȭ́x,_rQEzdZ5)3 VIR,b2%u*A12+/Qi ")&*L l~JĉCZ :X $|) !$9&UD I;`UkA܋6ć<&w^%J.kypֲq %*zy_,zs,dV3BX2f1Ĉm4jֱ?@ ü'sl˽:_tMdiscoSnp/kissreads/0000755000000000000000000000000012412740146013327 5ustar rootrootdiscoSnp/kissreads/include/0000755000000000000000000000000012232437324014753 5ustar rootrootdiscoSnp/kissreads/include/outputs.h0000644000000000000000000000456012363161234016653 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * outputs.h * * Created on: 27 oct. 2010 * Author: ppeterlo */ #ifndef OUTPUTS_H_ #define OUTPUTS_H_ void print_results_2_paths_per_event(FILE * coherent_out, FILE * uncoherent_out, const p_fragment_info * results_against_set, int number_of_read_sets, int nb_events_per_set, int qual); void print_results_invs(FILE * coherent_out, FILE * uncoherent_out, const p_fragment_info * results_against_set, int number_of_read_sets, int nb_events_per_set, int qual); void print_generic_results(FILE * coherent_out, FILE * uncoherent_out, const p_fragment_info * results_against_set, const int number_of_read_sets, int nb_events_per_set, int qual); #endif /* OUTPUTS_H_ */ discoSnp/kissreads/include/coherence_algorithm.h0000644000000000000000000000414512147164464021140 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * coherence_algorithm.h * * Created on: 15 sept. 2010 * Author: peterlongo chikhi */ #ifndef COHERENCE_ALGORITHM_H_ #define COHERENCE_ALGORITHM_H_ char read_coherent_generic (const int pwi, const char * fragment, const char * read, const int subst_allowed); char read_coherent_SNP(const int pwi, const char * fragment, const char * read, const int subst_allowed); #endif /* COHERENCE_ALGORITHM_H_ */ discoSnp/kissreads/include/couple.h0000644000000000000000000000514712424174356016430 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * couple.h * * Created on: 17 sept. 2010 * Author: ppeterlo */ //#include #ifndef COUPLE_H_ #define COUPLE_H_ typedef struct { int a; int b; } couple, * p_couple; typedef struct { char* a; int b; } charint_couple, * p_charint_couple; typedef struct { void *a; void *b; } pointers_couple, * p_pointers_couple; //typedef struct { // p_node t; // int b; //} node_couple, * p_node_couple; // used to store the info of a seed maping one position (b) of a fragment // p_couple create_couple(int a,int b); void free_couple (const void * v_c); p_charint_couple create_charint_couple(char* a,int b); void free_charint_couple (const void * v_c); p_pointers_couple create_pointers_couple(void* a, void * b); void free_pointers_couple (const void * v_c); // ////p_node_couple create_node_couple(p_node t, int pos);//, int fragment_id); //void free_node_couple( const void * v_sc); #endif /* COUPLE_H_ */ discoSnp/kissreads/include/commons.h0000644000000000000000000001010112424137006016565 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * commons.h * * Created on: 17 sept. 2010 * Author: ppeterlo */ #ifndef COMMONS_H_ #define COMMONS_H_ //#define GET_ONLY_UPPER_CHARS // can be used for analysing outputs of kissnp where the extension is in lower case while the 2k+1 snp is in upper case. On wants only to analyse the 2k+1 snp #include #include #include typedef uint64_t kmer_type; //int artificial_overlap; char comp ['t'+1]; char nuc [4]; char standard_fasta; char silent; char quality; int kmer_size; int size_seeds; int minimal_read_overlap; kmer_type mask_code_seed; #ifdef INPUT_FROM_KISSPLICE int min_overlap; int countingOption; #endif int valid_character(const char c); int average_size_reads; int nb_event_sets; int number_of_read_sets; int size_before_reads_starting; // see fragment_info.h char * anykmer; char ** sort_strings (char ** strings, int number); void * mymalloc(const int size); void * mycalloc(const int size, const int size_2); char * mystrdup (const char *s1); void print_rev_comp(char s[], FILE* out); void revcomp(char s[], int len); void rev(char s[], int len); void init_static_variables(const int k); char * to_upper (char * word); char * to_lower (char * word); char * format_comment(char * raw_comment); int get_next_sequence_and_comments (gzFile file, char * sequence, char * comment, char * line); int get_next_sequence_and_comments_for_starters (char * sequence, char * comment, const char input_only_upper, char * line); int get_next_fasta_sequence (gzFile file, char * read, char * line); int get_next_sequence_and_comments_for_fastq (gzFile file, char * sequence, char * comment, char * quality, char * line); int get_next_sequence_for_fastq (gzFile file, char * read, char * quality, char * line); int number_of_sequences_in_file(gzFile file, char * line); gzFile file; uint64_t sum_memory; uint64_t sum_memory_strdup; uint64_t mask_nbseed ; uint64_t mask_offset_seed; unsigned int nbits_nbseeds; // macro to test if a variable is null (i.e., a malloc failed) #define test_alloc( variable) { if(variable == NULL){ fprintf(stderr,"cannot allocate memory for variable %s, exit\n",#variable); exit(1); }} kmer_type codeSeed(const char *seq); kmer_type updateCodeSeed(const char *seq, kmer_type *x); //saturated increment of unsigned char #define Sinc8(a) ((a == 0xFF ) ? 0xFF : a++) #define Sinc24(a) ((a == 0xFFFFFF ) ? 0xFFFFFF : a++) #endif /* COMMONS_H_ */ discoSnp/kissreads/include/fragment_index.h0000644000000000000000000000456112410743430020120 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * fragment_index.h * * Created on: 15 sept. 2010 * Author: ppeterlo */ #ifndef FRAGMENT_INDEX_H_ #define FRAGMENT_INDEX_H_ #include #include #include int number_of_starters; hash_t seeds; // hash table seed -> (fragment id, position) hash_t seeds_count; couple * seed_table; p_fragment_info * index_starters_from_input_file (const int k, int nb_events_per_set, const int nb_fragment_per_event, const char input_only_upper, const int index_stride); // read and store all starters presents in the pointed file. Index by seeds of length k all these starters. void free_seeds_index (); #endif /* FRAGMENT_INDEX_H_ */ discoSnp/kissreads/include/hash.h0000644000000000000000000001104612412737602016053 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * hashing used by mapsembler * this is a generic file, which defines an interface between mapsembler and a hash table implementation */ #include #include #include #include "commons.h" #ifndef _HASH_H #define _HASH_H /* * generic types: we typecast in hash_*.c functions for specific implementations */ typedef unsigned int *hash_t; typedef long* hash_iter; //typedef struct { // unsigned int offset_seed; // unsigned int nb_seeds; //} seedinfo, * p_seedinfo; typedef uint64_t hash_val; #define NBITS_OFFSET_SEED 40 #include "couple.h" /* * basic functions: * - create hash table * - insert element into table * - return element from table * - delete table */ extern hash_t hash_create(unsigned int nbuckets); extern hash_t hash_create_binarykey(unsigned int nbuckets); extern int hash_insert(hash_t map, const char *key, const void * data, size_t len); extern ssize_t hash_entry_by_key(hash_t map, const char *key, void **data); extern int hash_delete(hash_t map, void (*specific_free)(const void *)); void hash_clear(hash_t map, void (*specific_free)(const void *)); /* * iterator functions: * - start iterator * - return current element from iterator * - test for end of iterator */ extern hash_iter hash_iterator_init(hash_t map); extern ssize_t hash_iterator_return_entry(hash_t map, hash_iter iter, char **key, void **data); extern hash_iter hash_iterator_next(hash_t map, hash_iter iter); extern hash_iter hash_iterator_is_end(hash_t map, hash_iter iter); /* * more advanced functions: * - search for an element having specific value in the hash table * - maintain a list inside each element of the hash table * - return a list of sorted reads by position */ void hash_increase_int_value_if_exists(hash_t map, char * key); int* hash_get_int_value(hash_t map, char * key); void hash_set_int_to_key(hash_t map, char * key, int value); extern ssize_t hash_search_key_int_value(hash_t map, const char *key, const int value_to_search); void hash_add_int_to_list(hash_t map, char * key, int value); void hash_add_something_to_list(hash_t map, const char * key, void *something); void hash_incr_kmer_count(hash_t map, const kmer_type * key); void iterate_and_fill_offsets(hash_t map); //int get_seed_info(hash_t map, const char * key, uint64_t * offset_seed, uint64_t * nb_seeds); int get_seed_info(hash_t map, const kmer_type * key, uint64_t * offset_seed, uint64_t * nb_seeds); void hash_fill_kmer_index(hash_t map, const kmer_type * key, couple * seed_table, const int fragment_id, const int position_on_fragment); void * hash_list_sorted_by_positions(hash_t map); void get_offset_and_nb_from_sinfo(hash_val sinfo, uint64_t * offset_seed,uint64_t * nb_seeds ); void set_offset_and_nb_into_sinfo(hash_val * sinfo, uint64_t offset_seed,uint64_t nb_seeds ); #endif /* _HASH_H */ discoSnp/kissreads/include/list.h0000644000000000000000000000563612424137006016106 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * list.h * * Created on: 16 sept. 2010 * Author: ppeterlo */ #ifndef LIST_H_ #define LIST_H_ #include #include #include #include #include typedef struct CELL { void * val; struct CELL *prox; } cell, * p_cell; typedef struct { int size; p_cell first; } list; list *list_create(void); void list_add(list *l, void* val); void list_free(const void *list, void (*specific_free)(void *)); void list_of_generic_free(const void *v_list); void list_of_generic_empty(const void * v_list); int numberInList (list *l); ///////////////////////////////////////////////////////////////////////////////// ///////// For speed purpose, here is a list dedicated to int only /////////////// ///////////////////////////////////////////////////////////////////////////////// typedef struct CELLINT { int val; struct CELLINT *prox; } cellint, * p_cellint; typedef struct { int size; p_cellint first; } listint; listint *listint_create(void); void listint_add(listint *l, int val); char listint_contains(listint *l, int val); void listint_free(const void *v_list); void listint_empty(const void * v_list); int numberInListint (listint *l); #endif /* LIST_H_ */ discoSnp/kissreads/include/extension_algorithm.h0000644000000000000000000000510412424137006021203 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * extension_algorithm.h * * Created on: 15 sept. 2010 * Author: ppeterlo */ #ifndef EXTENSION_ALGORITHM_H_ #define EXTENSION_ALGORITHM_H_ #include #include #include float read_coherence (gzFile reads_file, char * reads_file_name, const int k, const int min_coverage, p_fragment_info * all_starters, const int number_starters, int read_file, int qual, int nb_events_per_set, int nb_fragment_per_event, FILE * sam_out, int subst_allowed, const char no_subsutitution_on_central_position, const int minimal_read_overlap); #endif /* EXTENSION_ALGORITHM_H_ */ discoSnp/kissreads/include/fragment_info.h0000644000000000000000000000766712424174356017770 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * fragment_info.h * * Created on: 15 sept. 2010 * Author: ppeterlo */ #ifndef FRAGMENT_INFO_H_ #define FRAGMENT_INFO_H_ #include #include "list.h" //with CHARQUAL, use an unsigned char to store qual values. To avoid overflow, compute average value 'on the fly' #ifndef INTQUAL // if compilation was NOT done with CFLAGS=-DINTQUAL, use the CHARQUAL option #define CHARQUAL #endif #ifndef CLASSICAL_SPANNING #define KMER_SPANNING // ask more than only all position covered by at least min_coverage reads. Each kmer spanning each position should be covered by at least min_coverage reads. #endif typedef struct { // fixed once at the beggining: char * w; // the fragment //#ifdef GET_ONLY_UPPER_CHARS char * left_extension; char * right_extension; char * mapped_with_current_read; // For every read set (because of parrallelization): in run time, set to 1 if a match was seen with a current read. Avoid multiple matches of the same read on this starter. listint ** tested_pwis_with_current_read; // For every read set (because of parrallelization): in run time, all tested positions of the current read on this starter are stored. Avoids the computation redundances. //#endif char * comment; // first line of the comment (fasta format) char * read_coherent; // =for every set of reads, 1 if the fragment is detected as read coherent, else =0 unsigned char ** read_coherent_positions; // number of reads covering this position can be a char, min coverage required is low #ifdef INPUT_FROM_KISSPLICE char upperpath; // are we dealing with ASB path (==upper path) (else it's an AB path) int * nb_reads_fully_in_S; int * nb_reads_overlapping_AS; int * nb_reads_overlapping_SB; int * nb_reads_overlapping_both_AS_and_SB; // also used as junction AB for lower paths. #endif #ifdef CHARQUAL unsigned char ** sum_quality_per_position; //for every set of reads, " " sum of the qualitites of reads mapping at that position if read coherent #else int ** sum_quality_per_position; #endif int * number_mapped_reads; //for every set of reads, number of reads starting (REPLACE reads_starting) } fragment_info, *p_fragment_info; #endif /* FRAGMENT_INFO_H_ */ discoSnp/kissreads/include/libchash.h0000644000000000000000000003015412062133076016702 0ustar rootroot/* Copyright (c) 1998 - 2005, Google Inc. * 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 Google Inc. 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 THE COPYRIGHT * OWNER OR CONTRIBUTORS 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: Craig Silverstein * * This library is intended to be used for in-memory hash tables, * though it provides rudimentary permanent-storage capabilities. * It attempts to be fast, portable, and small. The best algorithm * to fulfill these goals is an internal probing hashing algorithm, * as in Knuth, _Art of Computer Programming_, vol III. Unlike * chained (open) hashing, it doesn't require a pointer for every * item, yet it is still constant time lookup in practice. * * Also to save space, we let the contents (both data and key) that * you insert be a union: if the key/data is small, we store it * directly in the hashtable, otherwise we store a pointer to it. * To keep you from having to figure out which, use KEY_PTR and * PTR_KEY to convert between the arguments to these functions and * a pointer to the real data. For instance: * char key[] = "ab", *key2; * HTItem *bck; HashTable *ht; * HashInsert(ht, PTR_KEY(ht, key), 0); * bck = HashFind(ht, PTR_KEY(ht, "ab")); * key2 = KEY_PTR(ht, bck->key); * * There are a rich set of operations supported: * AllocateHashTable() -- Allocates a hashtable structure and * returns it. * cchKey: if it's a positive number, then each key is a * fixed-length record of that length. If it's 0, * the key is assumed to be a \0-terminated string. * fSaveKey: normally, you are responsible for allocating * space for the key. If this is 1, we make a * copy of the key for you. * ClearHashTable() -- Removes everything from a hashtable * FreeHashTable() -- Frees memory used by a hashtable * * HashFind() -- takes a key (use PTR_KEY) and returns the * HTItem containing that key, or NULL if the * key is not in the hashtable. * HashFindLast() -- returns the item found by last HashFind() * HashFindOrInsert() -- inserts the key/data pair if the key * is not already in the hashtable, or * returns the appropraite HTItem if it is. * HashFindOrInsertItem() -- takes key/data as an HTItem. * HashInsert() -- adds a key/data pair to the hashtable. What * it does if the key is already in the table * depends on the value of SAMEKEY_OVERWRITE. * HashInsertItem() -- takes key/data as an HTItem. * HashDelete() -- removes a key/data pair from the hashtable, * if it's there. RETURNS 1 if it was there, * 0 else. * If you use sparse tables and never delete, the full data * space is available. Otherwise we steal -2 (maybe -3), * so you can't have data fields with those values. * HashDeleteLast() -- deletes the item returned by the last Find(). * * HashFirstBucket() -- used to iterate over the buckets in a * hashtable. DON'T INSERT OR DELETE WHILE * ITERATING! You can't nest iterations. * HashNextBucket() -- RETURNS NULL at the end of iterating. * * HashSetDeltaGoalSize() -- if you're going to insert 1000 items * at once, call this fn with arg 1000. * It grows the table more intelligently. * * HashSave() -- saves the hashtable to a file. It saves keys ok, * but it doesn't know how to interpret the data field, * so if the data field is a pointer to some complex * structure, you must send a function that takes a * file pointer and a pointer to the structure, and * write whatever you want to write. It should return * the number of bytes written. If the file is NULL, * it should just return the number of bytes it would * write, without writing anything. * If your data field is just an integer, not a * pointer, just send NULL for the function. * HashLoad() -- loads a hashtable. It needs a function that takes * a file and the size of the structure, and expects * you to read in the structure and return a pointer * to it. You must do memory allocation, etc. If * the data is just a number, send NULL. * HashLoadKeys() -- unlike HashLoad(), doesn't load the data off disk * until needed. This saves memory, but if you look * up the same key a lot, it does a disk access each * time. * You can't do Insert() or Delete() on hashtables that were loaded * from disk. */ #include /* includes definition of "ulong", we hope */ #include #define ulong u_long #define MAGIC_KEY "CHsh" /* when we save the file */ #ifndef LOG_WORD_SIZE /* 5 for 32 bit words, 6 for 64 */ #if defined (__LP64__) || defined (_LP64) #define LOG_WORD_SIZE 6 /* log_2(sizeof(ulong)) [in bits] */ #else #define LOG_WORD_SIZE 5 /* log_2(sizeof(ulong)) [in bits] */ #endif #endif /* The following gives a speed/time tradeoff: how many buckets are * * in each bin. 0 gives 32 buckets/bin, which is a good number. */ #ifndef LOG_BM_WORDS #define LOG_BM_WORDS 0 /* each group has 2^L_B_W * 32 buckets */ #endif /* The following are all parameters that affect performance. */ #ifndef JUMP #define JUMP(key, offset) ( ++(offset) ) /* ( 1 ) for linear hashing */ #endif #ifndef Table #define Table(x) Sparse##x /* Dense##x for dense tables */ #endif #ifndef FAST_DELETE #define FAST_DELETE 0 /* if it's 1, we never shrink the ht */ #endif #ifndef SAMEKEY_OVERWRITE #define SAMEKEY_OVERWRITE 1 /* overwrite item with our key on insert? */ #endif #ifndef OCCUPANCY_PCT #define OCCUPANCY_PCT 0.5 /* large PCT means smaller and slower */ #endif #ifndef MIN_HASH_SIZE #define MIN_HASH_SIZE 512 /* ht size when first created */ #endif /* When deleting a bucket, we can't just empty it (future hashes * * may fail); instead we set the data field to DELETED. Thus you * * should set DELETED to a data value you never use. Better yet, * * if you don't need to delete, define INSERT_ONLY. */ #ifndef INSERT_ONLY #define DELETED -2UL #define IS_BCK_DELETED(bck) ( (bck) && (bck)->data == DELETED ) #define SET_BCK_DELETED(ht, bck) do { (bck)->data = DELETED; \ FREE_KEY(ht, (bck)->key); } while ( 0 ) #else #define IS_BCK_DELETED(bck) 0 #define SET_BCK_DELETED(ht, bck) \ do { fprintf(stderr, "Deletion not supported for insert-only hashtable\n");\ exit(2); } while ( 0 ) #endif /* We need the following only for dense buckets (Dense##x above). * * If you need to, set this to a value you'll never use for data. */ #define EMPTY -3UL /* steal more of the bck->data space */ /* This is what an item is. Either can be cast to a pointer. */ typedef struct { ulong data; /* 4 bytes for data: either a pointer or an integer */ ulong key; /* 4 bytes for the key: either a pointer or an int */ } HTItem; struct Table(Bin); /* defined in chash.c, I hope */ struct Table(Iterator); typedef struct Table(Bin) Table; /* Expands to SparseBin, etc */ typedef struct Table(Iterator) TableIterator; /* for STORES_PTR to work ok, cchKey MUST BE DEFINED 1st, cItems 2nd! */ typedef struct HashTable { ulong cchKey; /* the length of the key, or if it's \0 terminated */ ulong cItems; /* number of items currently in the hashtable */ ulong cDeletedItems; /* # of buckets holding DELETE in the hashtable */ ulong cBuckets; /* size of the table */ Table *table; /* The actual contents of the hashtable */ int fSaveKeys; /* 1 if we copy keys locally; 2 if keys in one block */ int cDeltaGoalSize; /* # of coming inserts (or deletes, if <0) we expect */ HTItem *posLastFind; /* position of last Find() command */ TableIterator *iter; /* used in First/NextBucket */ FILE *fpData; /* if non-NULL, what item->data points into */ char * (*dataRead)(FILE *, int); /* how to load data from disk */ HTItem bckData; /* holds data after being loaded from disk */ } HashTable; /* Small keys are stored and passed directly, but large keys are * stored and passed as pointers. To make it easier to remember * what to pass, we provide two functions: * PTR_KEY: give it a pointer to your data, and it returns * something appropriate to send to Hash() functions or * be stored in a data field. * KEY_PTR: give it something returned by a Hash() routine, and * it returns a (char *) pointer to the actual data. */ #define HashKeySize(ht) ( ((ulong *)(ht))[0] ) /* this is how we inline */ #define HashSize(ht) ( ((ulong *)(ht))[1] ) /* ...a la C++ :-) */ #define STORES_PTR(ht) ( HashKeySize(ht) == 0 || \ HashKeySize(ht) > sizeof(ulong) ) #define KEY_PTR(ht, key) ( STORES_PTR(ht) ? (char *)(key) : (char *)&(key) ) #ifdef DONT_HAVE_TO_WORRY_ABOUT_BUS_ERRORS #define PTR_KEY(ht, ptr) ( STORES_PTR(ht) ? (ulong)(ptr) : *(ulong *)(ptr) ) #else #define PTR_KEY(ht, ptr) ( STORES_PTR(ht) ? (ulong)(ptr) : HTcopy((char *)ptr)) #endif /* Function prototypes */ unsigned long HTcopy(char *pul); /* for PTR_KEY, not for users */ struct HashTable *AllocateHashTable(int cchKey, int fSaveKeys); void ClearHashTable(struct HashTable *ht); void FreeHashTable(struct HashTable *ht); HTItem *HashFind(struct HashTable *ht, ulong key); HTItem *HashFindLast(struct HashTable *ht); HTItem *HashFindOrInsert(struct HashTable *ht, ulong key, ulong dataInsert); HTItem *HashFindOrInsertItem(struct HashTable *ht, HTItem *pItem); HTItem *HashInsert(struct HashTable *ht, ulong key, ulong data); HTItem *HashInsertItem(struct HashTable *ht, HTItem *pItem); int HashDelete(struct HashTable *ht, ulong key); int HashDeleteLast(struct HashTable *ht); HTItem *HashFirstBucket(struct HashTable *ht); HTItem *HashNextBucket(struct HashTable *ht); int HashSetDeltaGoalSize(struct HashTable *ht, int delta); void HashSave(FILE *fp, struct HashTable *ht, int (*write)(FILE *, char *)); struct HashTable *HashLoad(FILE *fp, char * (*read)(FILE *, int)); struct HashTable *HashLoadKeys(FILE *fp, char * (*read)(FILE *, int)); discoSnp/kissreads/LICENSE0000644000000000000000000005115412227036510014337 0ustar rootroot CeCILL FREE SOFTWARE LICENSE AGREEMENT Notice This Agreement is a Free Software license agreement that is the result of discussions between its authors in order to ensure compliance with the two main principles guiding its drafting: * firstly, compliance with the principles governing the distribution of Free Software: access to source code, broad rights granted to users, * secondly, the election of a governing law, French law, with which it is conformant, both as regards the law of torts and intellectual property law, and the protection that it offers to both authors and holders of the economic rights over software. The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) license are: Commissariat à l'Energie Atomique - CEA, a public scientific, technical and industrial research establishment, having its principal place of business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. Centre National de la Recherche Scientifique - CNRS, a public scientific and technological establishment, having its principal place of business at 3 rue Michel-Ange, 75794 Paris cedex 16, France. Institut National de Recherche en Informatique et en Automatique - INRIA, a public scientific and technological establishment, having its principal place of business at Domaine de Voluceau, Rocquencourt, BP 105, 78153 Le Chesnay cedex, France. Preamble The purpose of this Free Software license agreement is to grant users the right to modify and redistribute the software governed by this license within the framework of an open source distribution model. The exercising of these rights is conditional upon certain obligations for users so as to preserve this status for all subsequent redistributions. In consideration of access to the source code and the rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors only have limited liability. In this respect, the risks associated with loading, using, modifying and/or developing or reproducing the software by the user are brought to the user's attention, given its Free Software status, which may make it complicated to use, with the result that its use is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the suitability of the software as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions of security. This Agreement may be freely reproduced and published, provided it is not altered, and that no provisions are either added or removed herefrom. This Agreement may apply to any or all software for which the holder of the economic rights decides to submit the use thereof to its provisions. Article 1 - DEFINITIONS For the purpose of this Agreement, when the following expressions commence with a capital letter, they shall have the following meaning: Agreement: means this license agreement, and its possible subsequent versions and annexes. Software: means the software in its Object Code and/or Source Code form and, where applicable, its documentation, "as is" when the Licensee accepts the Agreement. Initial Software: means the Software in its Source Code and possibly its Object Code form and, where applicable, its documentation, "as is" when it is first distributed under the terms and conditions of the Agreement. Modified Software: means the Software modified by at least one Contribution. Source Code: means all the Software's instructions and program lines to which access is required so as to modify the Software. Object Code: means the binary files originating from the compilation of the Source Code. Holder: means the holder(s) of the economic rights over the Initial Software. Licensee: means the Software user(s) having accepted the Agreement. Contributor: means a Licensee having made at least one Contribution. Licensor: means the Holder, or any other individual or legal entity, who distributes the Software under the Agreement. Contribution: means any or all modifications, corrections, translations, adaptations and/or new functions integrated into the Software by any or all Contributors, as well as any or all Internal Modules. Module: means a set of sources files including their documentation that enables supplementary functions or services in addition to those offered by the Software. External Module: means any or all Modules, not derived from the Software, so that this Module and the Software run in separate address spaces, with one calling the other when they are run. Internal Module: means any or all Module, connected to the Software so that they both execute in the same address space. GNU GPL: means the GNU General Public License version 2 or any subsequent version, as published by the Free Software Foundation Inc. Parties: mean both the Licensee and the Licensor. These expressions may be used both in singular and plural form. Article 2 - PURPOSE The purpose of the Agreement is the grant by the Licensor to the Licensee of a non-exclusive, transferable and worldwide license for the Software as set forth in Article 5 hereinafter for the whole term of the protection granted by the rights over said Software. Article 3 - ACCEPTANCE 3.1 The Licensee shall be deemed as having accepted the terms and conditions of this Agreement upon the occurrence of the first of the following events: * (i) loading the Software by any or all means, notably, by downloading from a remote server, or by loading from a physical medium; * (ii) the first time the Licensee exercises any of the rights granted hereunder. 3.2 One copy of the Agreement, containing a notice relating to the characteristics of the Software, to the limited warranty, and to the fact that its use is restricted to experienced users has been provided to the Licensee prior to its acceptance as set forth in Article 3.1 hereinabove, and the Licensee hereby acknowledges that it has read and understood it. Article 4 - EFFECTIVE DATE AND TERM 4.1 EFFECTIVE DATE The Agreement shall become effective on the date when it is accepted by the Licensee as set forth in Article 3.1. 4.2 TERM The Agreement shall remain in force for the entire legal term of protection of the economic rights over the Software. Article 5 - SCOPE OF RIGHTS GRANTED The Licensor hereby grants to the Licensee, who accepts, the following rights over the Software for any or all use, and for the term of the Agreement, on the basis of the terms and conditions set forth hereinafter. Besides, if the Licensor owns or comes to own one or more patents protecting all or part of the functions of the Software or of its components, the Licensor undertakes not to enforce the rights granted by these patents against successive Licensees using, exploiting or modifying the Software. If these patents are transferred, the Licensor undertakes to have the transferees subscribe to the obligations set forth in this paragraph. 5.1 RIGHT OF USE The Licensee is authorized to use the Software, without any limitation as to its fields of application, with it being hereinafter specified that this comprises: 1. permanent or temporary reproduction of all or part of the Software by any or all means and in any or all form. 2. loading, displaying, running, or storing the Software on any or all medium. 3. entitlement to observe, study or test its operation so as to determine the ideas and principles behind any or all constituent elements of said Software. This shall apply when the Licensee carries out any or all loading, displaying, running, transmission or storage operation as regards the Software, that it is entitled to carry out hereunder. 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS The right to make Contributions includes the right to translate, adapt, arrange, or make any or all modifications to the Software, and the right to reproduce the resulting software. The Licensee is authorized to make any or all Contributions to the Software provided that it includes an explicit notice that it is the author of said Contribution and indicates the date of the creation thereof. 5.3 RIGHT OF DISTRIBUTION In particular, the right of distribution includes the right to publish, transmit and communicate the Software to the general public on any or all medium, and by any or all means, and the right to market, either in consideration of a fee, or free of charge, one or more copies of the Software by any means. The Licensee is further authorized to distribute copies of the modified or unmodified Software to third parties according to the terms and conditions set forth hereinafter. 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION The Licensee is authorized to distribute true copies of the Software in Source Code or Object Code form, provided that said distribution complies with all the provisions of the Agreement and is accompanied by: 1. a copy of the Agreement, 2. a notice relating to the limitation of both the Licensor's warranty and liability as set forth in Articles 8 and 9, and that, in the event that only the Object Code of the Software is redistributed, the Licensee allows future Licensees unhindered access to the full Source Code of the Software by indicating how to access it, it being understood that the additional cost of acquiring the Source Code shall not exceed the cost of transferring the data. 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE When the Licensee makes a Contribution to the Software, the terms and conditions for the distribution of the resulting Modified Software become subject to all the provisions of this Agreement. The Licensee is authorized to distribute the Modified Software, in source code or object code form, provided that said distribution complies with all the provisions of the Agreement and is accompanied by: 1. a copy of the Agreement, 2. a notice relating to the limitation of both the Licensor's warranty and liability as set forth in Articles 8 and 9, and that, in the event that only the object code of the Modified Software is redistributed, the Licensee allows future Licensees unhindered access to the full source code of the Modified Software by indicating how to access it, it being understood that the additional cost of acquiring the source code shall not exceed the cost of transferring the data. 5.3.3 DISTRIBUTION OF EXTERNAL MODULES When the Licensee has developed an External Module, the terms and conditions of this Agreement do not apply to said External Module, that may be distributed under a separate license agreement. 5.3.4 COMPATIBILITY WITH THE GNU GPL The Licensee can include a code that is subject to the provisions of one of the versions of the GNU GPL in the Modified or unmodified Software, and distribute that entire code under the terms of the same version of the GNU GPL. The Licensee can include the Modified or unmodified Software in a code that is subject to the provisions of one of the versions of the GNU GPL, and distribute that entire code under the terms of the same version of the GNU GPL. Article 6 - INTELLECTUAL PROPERTY 6.1 OVER THE INITIAL SOFTWARE The Holder owns the economic rights over the Initial Software. Any or all use of the Initial Software is subject to compliance with the terms and conditions under which the Holder has elected to distribute its work and no one shall be entitled to modify the terms and conditions for the distribution of said Initial Software. The Holder undertakes that the Initial Software will remain ruled at least by this Agreement, for the duration set forth in Article 4.2. 6.2 OVER THE CONTRIBUTIONS The Licensee who develops a Contribution is the owner of the intellectual property rights over this Contribution as defined by applicable law. 6.3 OVER THE EXTERNAL MODULES The Licensee who develops an External Module is the owner of the intellectual property rights over this External Module as defined by applicable law and is free to choose the type of agreement that shall govern its distribution. 6.4 JOINT PROVISIONS The Licensee expressly undertakes: 1. not to remove, or modify, in any manner, the intellectual property notices attached to the Software; 2. to reproduce said notices, in an identical manner, in the copies of the Software modified or not. The Licensee undertakes not to directly or indirectly infringe the intellectual property rights of the Holder and/or Contributors on the Software and to take, where applicable, vis-à-vis its staff, any and all measures required to ensure respect of said intellectual property rights of the Holder and/or Contributors. Article 7 - RELATED SERVICES 7.1 Under no circumstances shall the Agreement oblige the Licensor to provide technical assistance or maintenance services for the Software. However, the Licensor is entitled to offer this type of services. The terms and conditions of such technical assistance, and/or such maintenance, shall be set forth in a separate instrument. Only the Licensor offering said maintenance and/or technical assistance services shall incur liability therefor. 7.2 Similarly, any Licensor is entitled to offer to its licensees, under its sole responsibility, a warranty, that shall only be binding upon itself, for the redistribution of the Software and/or the Modified Software, under terms and conditions that it is free to decide. Said warranty, and the financial terms and conditions of its application, shall be subject of a separate instrument executed between the Licensor and the Licensee. Article 8 - LIABILITY 8.1 Subject to the provisions of Article 8.2, the Licensee shall be entitled to claim compensation for any direct loss it may have suffered from the Software as a result of a fault on the part of the relevant Licensor, subject to providing evidence thereof. 8.2 The Licensor's liability is limited to the commitments made under this Agreement and shall not be incurred as a result of in particular: (i) loss due the Licensee's total or partial failure to fulfill its obligations, (ii) direct or consequential loss that is suffered by the Licensee due to the use or performance of the Software, and (iii) more generally, any consequential loss. In particular the Parties expressly agree that any or all pecuniary or business loss (i.e. loss of data, loss of profits, operating loss, loss of customers or orders, opportunity cost, any disturbance to business activities) or any or all legal proceedings instituted against the Licensee by a third party, shall constitute consequential loss and shall not provide entitlement to any or all compensation from the Licensor. Article 9 - WARRANTY 9.1 The Licensee acknowledges that the scientific and technical state-of-the-art when the Software was distributed did not enable all possible uses to be tested and verified, nor for the presence of possible defects to be detected. In this respect, the Licensee's attention has been drawn to the risks associated with loading, using, modifying and/or developing and reproducing the Software which are reserved for experienced users. The Licensee shall be responsible for verifying, by any or all means, the suitability of the product for its requirements, its good working order, and for ensuring that it shall not cause damage to either persons or properties. 9.2 The Licensor hereby represents, in good faith, that it is entitled to grant all the rights over the Software (including in particular the rights set forth in Article 5). 9.3 The Licensee acknowledges that the Software is supplied "as is" by the Licensor without any other express or tacit warranty, other than that provided for in Article 9.2 and, in particular, without any warranty as to its commercial value, its secured, safe, innovative or relevant nature. Specifically, the Licensor does not warrant that the Software is free from any error, that it will operate without interruption, that it will be compatible with the Licensee's own equipment and software configuration, nor that it will meet the Licensee's requirements. 9.4 The Licensor does not either expressly or tacitly warrant that the Software does not infringe any third party intellectual property right relating to a patent, software or any other property right. Therefore, the Licensor disclaims any and all liability towards the Licensee arising out of any or all proceedings for infringement that may be instituted in respect of the use, modification and redistribution of the Software. Nevertheless, should such proceedings be instituted against the Licensee, the Licensor shall provide it with technical and legal assistance for its defense. Such technical and legal assistance shall be decided on a case-by-case basis between the relevant Licensor and the Licensee pursuant to a memorandum of understanding. The Licensor disclaims any and all liability as regards the Licensee's use of the name of the Software. No warranty is given as regards the existence of prior rights over the name of the Software or as regards the existence of a trademark. Article 10 - TERMINATION 10.1 In the event of a breach by the Licensee of its obligations hereunder, the Licensor may automatically terminate this Agreement thirty (30) days after notice has been sent to the Licensee and has remained ineffective. 10.2 A Licensee whose Agreement is terminated shall no longer be authorized to use, modify or distribute the Software. However, any licenses that it may have granted prior to termination of the Agreement shall remain valid subject to their having been granted in compliance with the terms and conditions hereof. Article 11 - MISCELLANEOUS 11.1 EXCUSABLE EVENTS Neither Party shall be liable for any or all delay, or failure to perform the Agreement, that may be attributable to an event of force majeure, an act of God or an outside cause, such as defective functioning or interruptions of the electricity or telecommunications networks, network paralysis following a virus attack, intervention by government authorities, natural disasters, water damage, earthquakes, fire, explosions, strikes and labor unrest, war, etc. 11.2 Any failure by either Party, on one or more occasions, to invoke one or more of the provisions hereof, shall under no circumstances be interpreted as being a waiver by the interested Party of its right to invoke said provision(s) subsequently. 11.3 The Agreement cancels and replaces any or all previous agreements, whether written or oral, between the Parties and having the same purpose, and constitutes the entirety of the agreement between said Parties concerning said purpose. No supplement or modification to the terms and conditions hereof shall be effective as between the Parties unless it is made in writing and signed by their duly authorized representatives. 11.4 In the event that one or more of the provisions hereof were to conflict with a current or future applicable act or legislative text, said act or legislative text shall prevail, and the Parties shall make the necessary amendments so as to comply with said act or legislative text. All other provisions shall remain effective. Similarly, invalidity of a provision of the Agreement, for any reason whatsoever, shall not cause the Agreement as a whole to be invalid. 11.5 LANGUAGE The Agreement is drafted in both French and English and both versions are deemed authentic. Article 12 - NEW VERSIONS OF THE AGREEMENT 12.1 Any person is authorized to duplicate and distribute copies of this Agreement. 12.2 So as to ensure coherence, the wording of this Agreement is protected and may only be modified by the authors of the License, who reserve the right to periodically publish updates or new versions of the Agreement, each with a separate number. These subsequent versions may address new issues encountered by Free Software. 12.3 Any Software distributed under a given version of the Agreement may only be subsequently distributed under the same version of the Agreement or a subsequent version, subject to the provisions of Article 5.3.4. Article 13 - GOVERNING LAW AND JURISDICTION 13.1 The Agreement is governed by French law. The Parties agree to endeavor to seek an amicable solution to any disagreements or disputes that may arise during the performance of the Agreement. 13.2 Failing an amicable solution within two (2) months as from their occurrence, and unless emergency proceedings are necessary, the disagreements or disputes shall be referred to the Paris Courts having jurisdiction, by the more diligent Party. Version 2.0 dated 2006-09-05. discoSnp/kissreads/src/0000755000000000000000000000000012412740230014110 5ustar rootrootdiscoSnp/kissreads/src/commons.c0000644000000000000000000003271612424137006015744 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * commons.c * * Created on: 17 sept. 2010 * Author: ppeterlo */ #include #include #include #include #include #include // Added by Pierre Peterlongo on 10/09/2012. #include #include #include // DEBUG //#define GET_ONLY_UPPER_CHARS // can be used for analysing outputs of kissnp where the extension is in upper case while the 2k+1 snp is in upper case. On wants only to analyse the 2k+1 snp #define MAX_SIZE_LINE 1048576 //char line[MAX_SIZE_LINE]; extern kmer_type mask_code_seed; static int cmpstringp(const void *p1, const void *p2) { /* Les arguments de cette fonction sont des "pointeurs de pointeurs sur des caractères", mais les arguments de strcmp(3) sont des "pointeurs sur des caractères", d’où le forçage de type et l’utilisation de l’astérisque */ return strcmp(* (char * const *) p1, * (char * const *) p2); } char ** sort_strings (char ** strings, int number) { qsort(strings,number, sizeof(char *), cmpstringp); return strings; } char * mystrdup (const char *s1) { sum_memory_strdup+=strlen(s1); //printf("Strdup %i \n", strlen(s1)); return strdup(s1); } void * mymalloc(const int size){ sum_memory+=size; // printf("Allocate %d, sum=%lli = %lli Mo\n", size, sum_memory, sum_memory /1024LL/1024LL); return malloc(size); } void * mycalloc(const int size, const int size_2){ sum_memory+=size*size_2; //printf("Allocate %d, sum=%lli = %lli Mo\n", size*size_2, sum_memory, sum_memory /1024LL/1024LL); return calloc(size,size_2); } void init_static_variables(const int k){ int i; for (i=0;i<'T'+1;i++) comp[i]=i; // for other iupac alphabet letters comp['A']='T'; comp['T']='A'; comp['C']='G'; comp['G']='C'; comp['a']='t'; comp['t']='a'; comp['c']='g'; comp['g']='c'; nuc[0]='A'; nuc[1]='C'; nuc[2]='G'; nuc[3]='T'; anykmer = (char *) malloc(k+1); test_alloc(anykmer); mask_code_seed=1; // don't know why but 1<<(2*k) does not work with k>32. This is why I made this stupid loop/ int z; for (z=0;z<(2*k);z++){ mask_code_seed = mask_code_seed<<1; } mask_code_seed = mask_code_seed-1; } int valid_character(const char c){ if(c=='A' || c=='C' || c=='G' || c=='T') return 1; return 0; } void print_rev_comp(char s[], FILE* out){ int i; const int len=strlen(s); for(i=len-1;i>-1;i--)fprintf(out, "%c",comp[(int)s[i]]); } void revcomp(char s[], int len) { int i; char t; for (i=0;i' character * remove eventual last '\n' character * duplicate the raw_comment */ char * format_comment(char * raw_comment){ if(raw_comment[0]=='>') raw_comment++; int l = strlen(raw_comment); if(raw_comment[l-1]=='\n') raw_comment[l-1]='\0'; return strdup(raw_comment); } int get_next_sequence_and_comments_for_starters_fasta (char * sequence, char * comment, const char input_only_upper, char * line){ char *rv; char *p; int nextchar=0; rv=gzgets(file,(char *)comment,MAX_SIZE_LINE);// read comment ('>read00xxxx...\n') if(rv == NULL) return 0; do{ rv=gzgets(file,(char *)sequence,MAX_SIZE_LINE); // }while(sequence[0]=='>'); p = (char *)strchr((char*)sequence, '\n'); if (p) *p = '\0'; p = (char *)strchr((char*)sequence, '\r'); if (p) *p = '\0'; nextchar=gzgetc(file); // cheat, reads the next '>' character in order to induce EOF while (nextchar!='>' && !gzeof(file)) { gzseek(file, -1, SEEK_CUR); rv=gzgets(file,(char *)line,MAX_SIZE_LINE);// read comment ('>read00xxxx...\n') rv = strchr(line, '\n'); // find the last \n char if(rv) *rv = '\0'; // change it into \0 rv = strchr(line, '\r'); // find the last \r char if(rv) *rv = '\0'; // change it into \0 strcat(sequence, line); // concat the restult in the sequence nextchar=gzgetc(file); // cheat, reads the next '>' character in order to induce EOF } gzseek(file, -1, SEEK_CUR); // Go back to previous read character //#ifndef GET_ONLY_UPPER_CHARS if(!input_only_upper) to_upper(sequence); //#endif //printf("return sequence %s\n",sequence); // free(line); return strlen(sequence); // readlen } int get_next_sequence_and_comments_for_starters_fastq (char * sequence, char * comment, const char input_only_upper, char * line){ char *rv, *qv; char *p; char quality[96000]; //does not work if the sequence is written on several lines // char * line = malloc(sizeof(char)*1048576); rv=gzgets(file,(char *)comment,MAX_SIZE_LINE);// read comment1 ('@read00xxxx...\n') if(rv == NULL) return 0; do{ rv=gzgets(file, (char *)sequence,MAX_SIZE_LINE); // }while(sequence[0]=='@'); qv=gzgets(file, (char *)line,MAX_SIZE_LINE);// read comment2 ('+read00xxxx...\n') if(qv == NULL) return 0; qv=gzgets(file, (char *)quality,MAX_SIZE_LINE); // p = (char *)strchr((char*)sequence, '\n'); if (p) *p = '\0'; p = (char *)strchr((char*)sequence, '\r'); if (p) *p = '\0'; //nextchar=gzgetc(file); // cheat, reads the next '>' character in order to induce EOF //#ifndef GET_ONLY_UPPER_CHARS if(!input_only_upper) to_upper(sequence); //#endif //printf("return sequence %s\n",sequence); // free(line); return strlen(sequence); // readlen } int get_next_sequence_and_comments_for_starters (char * sequence, char * comment, const char input_only_upper, char * line){ char nextchar=gzgetc(file); gzseek(file, -1, SEEK_CUR); // Go back to previous read character if(nextchar=='@') return get_next_sequence_and_comments_for_starters_fastq(sequence, comment, input_only_upper,line); if(nextchar=='>') return get_next_sequence_and_comments_for_starters_fasta(sequence, comment, input_only_upper,line); gzgets(file, sequence,MAX_SIZE_LINE); fprintf(stderr,"could not determine if the file is fasta or fastq in line %s, exit\n", sequence); exit(1); } int get_next_sequence_and_comments_for_fastq (gzFile file, char * sequence, char * comment, char * quality, char * line){ char *rv, *qv; char *p; //does not work if the sequence is written on several lines //char * line = malloc(sizeof(char)*1048576); rv=gzgets(file,(char *)comment,MAX_SIZE_LINE);// read comment1 ('@read00xxxx...\n') if(rv == NULL) return 0; do{ rv=gzgets(file, (char *)sequence,MAX_SIZE_LINE); // }while(sequence[0]=='@'); qv=gzgets(file, (char *)line,MAX_SIZE_LINE);// read comment2 ('+read00xxxx...\n') if(qv == NULL) return 0; qv=gzgets(file, (char *)quality,MAX_SIZE_LINE); // p = (char *)strchr((char*)sequence, '\n'); if (p) *p = '\0'; p = (char *)strchr((char*)sequence, '\r'); if (p) *p = '\0'; // nextchar=gzgetc(file); // cheat, reads the next '>' character in order to induce EOF to_upper(sequence); //printf("return sequence %s\n",sequence); //free(line); return strlen(sequence); // readlen } int get_next_fasta_sequence (gzFile file, char * sequence , char * line){ char *rv; char *p; int nextchar=0; //char * line = malloc(sizeof(char)*1048576); rv=gzgets(file, (char *)line,MAX_SIZE_LINE);// read comment ('>read00xxxx...\n') if(rv == NULL) return -1; do{ rv=gzgets(file,(char *)sequence,MAX_SIZE_LINE); // }while(sequence[0]=='>'); p = (char *)strchr((char*)sequence, '\n'); if (p) *p = '\0'; p = (char *)strchr((char*)sequence, '\r'); if (p) *p = '\0'; nextchar=gzgetc(file); // cheat, reads the next '>' character in order to induce EOF while (nextchar!='>' && !gzeof(file)) { gzseek(file, -1, SEEK_CUR); rv=gzgets(file, (char *)line,MAX_SIZE_LINE);// read comment ('>read00xxxx...\n') rv = strchr(line, '\n'); // find the last \n char if(rv) *rv = '\0'; // change it into \0 rv = strchr(line, '\r'); // find the last \r char if(rv) *rv = '\0'; // change it into \0 strcat(sequence, line); // concat the restult in the sequence nextchar=gzgetc(file); // cheat, reads the next '>' character in order to induce EOF } // gzseek(file, -1, SEEK_CUR); // Go back to previous read character to_upper(sequence); //free(line); return strlen(sequence); // readlen } int get_next_sequence_for_fastq (gzFile file, char * sequence, char * quality, char * line){ char *rv, *qv; char *p; //does not work if the sequence is written on several lines //char * line = malloc(sizeof(char)*MAX_SIZE_LINE); rv=gzgets(file,(char *)line,MAX_SIZE_LINE);// read comment ('@read00xxxx...\n') if(rv == NULL) return -1; do{ rv=gzgets(file,(char *)sequence,MAX_SIZE_LINE); // }while(sequence[0]=='@'); qv=gzgets(file,(char *)line,MAX_SIZE_LINE);// read comment ('+read00xxxx...\n') if(qv == NULL) return -1; qv=gzgets(file,(char *)quality,MAX_SIZE_LINE); // p = (char *)strchr((char*)sequence, '\n'); if (p) *p = '\0'; p = (char *)strchr((char*)sequence, '\r'); if (p) *p = '\0'; // nextchar=gzgetc(file); // cheat, reads the next '@' character in order to induce EOF to_upper(sequence); //printf("return sequence %s\n",sequence); //free(line); return strlen(sequence); // readlen } int number_of_sequences_in_fasta_file(gzFile file, char * line){ int sequences_number=0; int previous_is_a_comment=0; gzrewind(file); // char line[1048576]; //char * line = malloc(sizeof(char)*1048576); do{ if(gzgets(file,line,MAX_SIZE_LINE) == NULL) break; if(line[0]=='>'){ if(!previous_is_a_comment){ previous_is_a_comment=1; sequences_number++; } } else previous_is_a_comment=0; } while(1); gzrewind(file); //free(line); return sequences_number; } int number_of_sequences_in_fastq_file(gzFile file, char * line){ int sequences_number=0; int previous_is_a_comment=0; int line_number=0; gzrewind(file); // char line[1048576]; do{ if(gzgets(file,line,MAX_SIZE_LINE) == NULL) break; line_number++; if(line[0]=='@' && line_number%4 == 1){ //this does not work if the sequence is given on several lines, is this possible for fastq??? if(!previous_is_a_comment){ previous_is_a_comment=1; sequences_number++; } } else previous_is_a_comment=0; } while(1); gzrewind(file); return sequences_number; } int number_of_sequences_in_file(gzFile file, char * line){ gzrewind(file); if(gzgets(file,line,MAX_SIZE_LINE) == NULL) return 0; gzrewind(file); if(line[0]=='@') return number_of_sequences_in_fastq_file(file,line); if(line[0]=='>') return number_of_sequences_in_fasta_file(file,line); fprintf(stderr,"Error, read file starts with line %s, witch is not fastq nor fasta format\n", line); return 0; } // binary code of any character coded on 2 bits. // Among them: N or n or G or G=11 --- A or a = 00 --- C or c = 01 --- T or t = 10 inline int NT2int(const char nt) { return (nt>>1)&3; } // update a code of a seed with a new character O(1) kmer_type updateCodeSeed(const char *seq, kmer_type *x) // update of a seed (shift and adding a new character) { // printf("seed2 %" PRIu64 " mask %" PRIu64 "\n", *x, mask_code_seed); *x = (*x)*4 + NT2int(seq[size_seeds-1]); // add the code of the new nucleotid *x = *x & mask_code_seed; // remove the leftmost couple of bits // printf("seed3 %" PRIu64 " mask %" PRIu64 "\n", *x, mask_code_seed); return *x; } // transform a character seed into a code seed O(size seed) kmer_type codeSeed(const char *seq) // initialisation of a seed { int i; kmer_type x=0; for (i=0; i #include #include #include #include #include // MAXINT #include /* sleep(1) */ #include // strdup #include #include //#define OMP #ifdef OMP #include "omp.h" #endif char * getVersion(){ return "kissreads module 1.2.6 - Copyright INRIA - CeCILL License"; } void print_usage_and_exit(char * name){ fprintf (stderr, "NAME\nkissReads, version %s\n", getVersion()); #ifdef INPUT_FROM_KISSPLICE fprintf (stderr, "\nSYNOPSIS\n%s [ [ [ [original fasta comment|C1:mins\n"); fprintf (stderr, " With A:min32){ fprintf(stderr,"Sorry kissreads does not accept k>32, exit\n"); exit(1); } if(size_seeds>minimal_read_overlap) minimal_read_overlap=size_seeds; if(!silent){ printf("This is kissreads, version %s\n", getVersion()); printf("COMMAND LINE:\n"); for(i=0;i1?"s":""); for (i=0;i max_threads) nbthreads = max_threads; if(!silent){ printf("Mapping.\n"); } int silented=0; #ifdef OMP if (!silent) silented=1; silent=1; // avoids melting messages #endif #ifdef OMP #pragma omp parallel for if(nbthreads>1 && sam_out==NULL) num_threads(nbthreads) private(i) #endif for (i=0;iread_coherent); free(results_against_set[i]->number_mapped_reads); int read_set_id; for (read_set_id=0;read_set_idread_coherent_positions[read_set_id]); free(results_against_set[i]->sum_quality_per_position[read_set_id]); } free(results_against_set[i]->read_coherent_positions); free(results_against_set[i]->sum_quality_per_position); free(results_against_set[i]); } free(results_against_set); gzclose(file); fclose(coherent_out); fclose(uncoherent_out); if(sam_out) fclose(sam_out); if(!silent) { printf("Results are in %s and %s", coherent_file_name, uncoherent_file_name); if(sam_out) printf(" (mapped reads are in %s)", samout_file_name); printf(".\n"); after_all = time(NULL); printf("Total time: %.0lf secs\n", difftime(after_all, before_all)); } return 0; } discoSnp/kissreads/src/libchash.c0000644000000000000000000020076512062133076016050 0ustar rootroot/* Copyright (c) 1998 - 2005, Google Inc. * 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 Google Inc. 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 THE COPYRIGHT * OWNER OR CONTRIBUTORS 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: Craig Silverstein * * This library is intended to be used for in-memory hash tables, * though it provides rudimentary permanent-storage capabilities. * It attempts to be fast, portable, and small. The best algorithm * to fulfill these goals is an internal probing hashing algorithm, * as in Knuth, _Art of Computer Programming_, vol III. Unlike * chained (open) hashing, it doesn't require a pointer for every * item, yet it is still constant time lookup in practice. * * Also to save space, we let the contents (both data and key) that * you insert be a union: if the key/data is small, we store it * directly in the hashtable, otherwise we store a pointer to it. * To keep you from having to figure out which, use KEY_PTR and * PTR_KEY to convert between the arguments to these functions and * a pointer to the real data. For instance: * char key[] = "ab", *key2; * HTItem *bck; HashTable *ht; * HashInsert(ht, PTR_KEY(ht, key), 0); * bck = HashFind(ht, PTR_KEY(ht, "ab")); * key2 = KEY_PTR(ht, bck->key); * * There are a rich set of operations supported: * AllocateHashTable() -- Allocates a hashtable structure and * returns it. * cchKey: if it's a positive number, then each key is a * fixed-length record of that length. If it's 0, * the key is assumed to be a \0-terminated string. * fSaveKey: normally, you are responsible for allocating * space for the key. If this is 1, we make a * copy of the key for you. * ClearHashTable() -- Removes everything from a hashtable * FreeHashTable() -- Frees memory used by a hashtable * * HashFind() -- takes a key (use PTR_KEY) and returns the * HTItem containing that key, or NULL if the * key is not in the hashtable. * HashFindLast() -- returns the item found by last HashFind() * HashFindOrInsert() -- inserts the key/data pair if the key * is not already in the hashtable, or * returns the appropraite HTItem if it is. * HashFindOrInsertItem() -- takes key/data as an HTItem. * HashInsert() -- adds a key/data pair to the hashtable. What * it does if the key is already in the table * depends on the value of SAMEKEY_OVERWRITE. * HashInsertItem() -- takes key/data as an HTItem. * HashDelete() -- removes a key/data pair from the hashtable, * if it's there. RETURNS 1 if it was there, * 0 else. * If you use sparse tables and never delete, the full data * space is available. Otherwise we steal -2 (maybe -3), * so you can't have data fields with those values. * HashDeleteLast() -- deletes the item returned by the last Find(). * * HashFirstBucket() -- used to iterate over the buckets in a * hashtable. DON'T INSERT OR DELETE WHILE * ITERATING! You can't nest iterations. * HashNextBucket() -- RETURNS NULL at the end of iterating. * * HashSetDeltaGoalSize() -- if you're going to insert 1000 items * at once, call this fn with arg 1000. * It grows the table more intelligently. * * HashSave() -- saves the hashtable to a file. It saves keys ok, * but it doesn't know how to interpret the data field, * so if the data field is a pointer to some complex * structure, you must send a function that takes a * file pointer and a pointer to the structure, and * write whatever you want to write. It should return * the number of bytes written. If the file is NULL, * it should just return the number of bytes it would * write, without writing anything. * If your data field is just an integer, not a * pointer, just send NULL for the function. * HashLoad() -- loads a hashtable. It needs a function that takes * a file and the size of the structure, and expects * you to read in the structure and return a pointer * to it. You must do memory allocation, etc. If * the data is just a number, send NULL. * HashLoadKeys() -- unlike HashLoad(), doesn't load the data off disk * until needed. This saves memory, but if you look * up the same key a lot, it does a disk access each * time. * You can't do Insert() or Delete() on hashtables that were loaded * from disk. * * See libchash.h for parameters you can modify. Make sure LOG_WORD_SIZE * is defined correctly for your machine! (5 for 32 bit words, 6 for 64). */ #include #include #include /* for strcmp, memcmp, etc */ #include /* ULTRIX needs this for in.h */ #include /* for reading/writing hashtables */ #include #include "libchash.h" /* all the types */ /* if keys are stored directly but cchKey is less than sizeof(ulong), */ /* this cuts off the bits at the end */ char grgKeyTruncMask[sizeof(ulong)][sizeof(ulong)]; #define KEY_TRUNC(ht, key) \ ( STORES_PTR(ht) || (ht)->cchKey == sizeof(ulong) \ ? (key) : ((key) & *(ulong *)&(grgKeyTruncMask[(ht)->cchKey][0])) ) /* round num up to a multiple of wordsize. (LOG_WORD_SIZE-3 is in bytes) */ #define WORD_ROUND(num) ( ((num-1) | ((1<<(LOG_WORD_SIZE-3))-1)) + 1 ) #define NULL_TERMINATED 0 /* val of cchKey if keys are null-term strings */ /* Useful operations we do to keys: compare them, copy them, free them */ #define KEY_CMP(ht, key1, key2) ( !STORES_PTR(ht) ? (key1) - (key2) : \ (key1) == (key2) ? 0 : \ HashKeySize(ht) == NULL_TERMINATED ? \ strcmp((char *)key1, (char *)key2) :\ memcmp((void *)key1, (void *)key2, \ HashKeySize(ht)) ) #define COPY_KEY(ht, keyTo, keyFrom) do \ if ( !STORES_PTR(ht) || !(ht)->fSaveKeys ) \ (keyTo) = (keyFrom); /* just copy pointer or info */\ else if ( (ht)->cchKey == NULL_TERMINATED ) /* copy 0-term.ed str */\ { \ (keyTo) = (ulong)HTsmalloc( WORD_ROUND(strlen((char *)(keyFrom))+1) ); \ strcpy((char *)(keyTo), (char *)(keyFrom)); \ } \ else \ { \ (keyTo) = (ulong) HTsmalloc( WORD_ROUND((ht)->cchKey) ); \ memcpy( (char *)(keyTo), (char *)(keyFrom), (ht)->cchKey); \ } \ while ( 0 ) #define FREE_KEY(ht, key) do \ if ( STORES_PTR(ht) && (ht)->fSaveKeys ) \ if ( (ht)->cchKey == NULL_TERMINATED ) \ HTfree((char *)(key), WORD_ROUND(strlen((char *)(key))+1)); \ else \ HTfree((char *)(key), WORD_ROUND((ht)->cchKey)); \ while ( 0 ) /* the following are useful for bitmaps */ /* Format is like this (if 1 word = 4 bits): 3210 7654 ba98 fedc ... */ typedef ulong HTBitmapPart; /* this has to be unsigned, for >> */ typedef HTBitmapPart HTBitmap[1<> LOG_WORD_SIZE) << (LOG_WORD_SIZE-3) ) #define MOD2(i, logmod) ( (i) & ((1<<(logmod))-1) ) #define DIV_NUM_ENTRIES(i) ( (i) >> LOG_WORD_SIZE ) #define MOD_NUM_ENTRIES(i) ( MOD2(i, LOG_WORD_SIZE) ) #define MODBIT(i) ( ((ulong)1) << MOD_NUM_ENTRIES(i) ) #define TEST_BITMAP(bm, i) ( (bm)[DIV_NUM_ENTRIES(i)] & MODBIT(i) ? 1 : 0 ) #define SET_BITMAP(bm, i) (bm)[DIV_NUM_ENTRIES(i)] |= MODBIT(i) #define CLEAR_BITMAP(bm, i) (bm)[DIV_NUM_ENTRIES(i)] &= ~MODBIT(i) /* the following are useful for reading and writing hashtables */ #define READ_UL(fp, data) \ do { \ long _ul; \ fread(&_ul, sizeof(_ul), 1, (fp)); \ data = ntohl(_ul); \ } while (0) #define WRITE_UL(fp, data) \ do { \ long _ul = htonl((long)(data)); \ fwrite(&_ul, sizeof(_ul), 1, (fp)); \ } while (0) /* Moves data from disk to memory if necessary. Note dataRead cannot be * * NULL, because then we might as well (and do) load the data into memory */ #define LOAD_AND_RETURN(ht, loadCommand) /* lC returns an HTItem * */ \ if ( !(ht)->fpData ) /* data is stored in memory */ \ return (loadCommand); \ else /* must read data off of disk */ \ {\ int cchData; \ HTItem *bck; \ if ( (ht)->bckData.data ) free((char *)(ht)->bckData.data); /* PIERRE: bug version 1.3: ce free genere une seg fault. FIXME */ \ ht->bckData.data = (ulong)NULL; /* needed if loadCommand fails */ \ bck = (loadCommand); \ if ( bck == NULL ) /* loadCommand failed: key not found */ \ return NULL; \ else \ (ht)->bckData = *bck; \ fseek(ht->fpData, (ht)->bckData.data, SEEK_SET); \ READ_UL((ht)->fpData, cchData); \ (ht)->bckData.data = (ulong)(ht)->dataRead((ht)->fpData, cchData); \ return &((ht)->bckData); \ } /* ======================================================================== */ /* UTILITY ROUTINES */ /* ---------------------- */ /* HTsmalloc() -- safe malloc * allocates memory, or crashes if the allocation fails. */ static void *HTsmalloc(unsigned long size) { void *retval; if ( size == 0 ) return NULL; retval = (void *)malloc(size); if ( !retval ) { fprintf(stderr, "HTsmalloc: Unable to allocate %lu bytes of memory\n", size); exit(1); } return retval; } /* HTscalloc() -- safe calloc * allocates memory and initializes it to 0, or crashes if * the allocation fails. */ static void *HTscalloc(unsigned long size) { void *retval; retval = (void *)calloc(size, 1); if ( !retval && size > 0 ) { fprintf(stderr, "HTscalloc: Unable to allocate %lu bytes of memory\n", size); exit(1); } return retval; } /* HTsrealloc() -- safe calloc * grows the amount of memory from a source, or crashes if * the allocation fails. */ static void *HTsrealloc(void *ptr, unsigned long new_size, long delta) { if ( ptr == NULL ) return HTsmalloc(new_size); ptr = realloc(ptr, new_size); if ( !ptr && new_size > 0 ) { fprintf(stderr, "HTsrealloc: Unable to reallocate %lu bytes of memory\n", new_size); exit(1); } return ptr; } /* HTfree() -- keep track of memory use * frees memory using free, but updates count of how much memory * is being used. */ static void HTfree(void *ptr, unsigned long size) { if ( size > 0 ) /* some systems seem to not like freeing NULL */ free(ptr); } /*************************************************************************\ | HTcopy() | | Sometimes we interpret data as a ulong. But ulongs must be | | aligned on some machines, so instead of casting we copy. | \*************************************************************************/ unsigned long HTcopy(char *ul) { unsigned long retval; memcpy(&retval, ul, sizeof(retval)); return retval; } /*************************************************************************\ | HTSetupKeyTrunc() | | If keys are stored directly but cchKey is less than | | sizeof(ulong), this cuts off the bits at the end. | \*************************************************************************/ static void HTSetupKeyTrunc(void) { int i, j; for ( i = 0; i < sizeof(unsigned long); i++ ) for ( j = 0; j < sizeof(unsigned long); j++ ) grgKeyTruncMask[i][j] = j < i ? 255 : 0; /* chars have 8 bits */ } /* ======================================================================== */ /* TABLE ROUTINES */ /* -------------------- */ /* The idea is that a hashtable with (logically) t buckets is divided * into t/M groups of M buckets each. (M is a constant set in * LOG_BM_WORDS for efficiency.) Each group is stored sparsely. * Thus, inserting into the table causes some array to grow, which is * slow but still constant time. Lookup involves doing a * logical-position-to-sparse-position lookup, which is also slow but * constant time. The larger M is, the slower these operations are * but the less overhead (slightly). * * To store the sparse array, we store a bitmap B, where B[i] = 1 iff * bucket i is non-empty. Then to look up bucket i we really look up * array[# of 1s before i in B]. This is constant time for fixed M. * * Terminology: the position of an item in the overall table (from * 1 .. t) is called its "location." The logical position in a group * (from 1 .. M ) is called its "position." The actual location in * the array (from 1 .. # of non-empty buckets in the group) is * called its "offset." * * The following operations are supported: * o Allocate an array with t buckets, all empty * o Free a array (but not whatever was stored in the buckets) * o Tell whether or not a bucket is empty * o Return a bucket with a given location * o Set the value of a bucket at a given location * o Iterate through all the buckets in the array * o Read and write an occupancy bitmap to disk * o Return how much memory is being allocated by the array structure */ #ifndef SparseBucket /* by default, each bucket holds an HTItem */ #define SparseBucket HTItem #endif typedef struct SparseBin { SparseBucket *binSparse; HTBitmap bmOccupied; /* bmOccupied[i] is 1 if bucket i has an item */ short cOccupied; /* size of binSparse; useful for iterators, eg */ } SparseBin; typedef struct SparseIterator { long posGroup; long posOffset; SparseBin *binSparse; /* state info, to avoid args for NextBucket() */ ulong cBuckets; } SparseIterator; #define LOG_LOW_BIN_SIZE ( LOG_BM_WORDS+LOG_WORD_SIZE ) #define SPARSE_GROUPS(cBuckets) ( (((cBuckets)-1) >> LOG_LOW_BIN_SIZE) + 1 ) /* we need a small function to figure out # of items set in the bm */ static HTOffset EntriesUpto(HTBitmapPart *bm, int i) { /* returns # of set bits in 0..i-1 */ HTOffset retval = 0; static HTOffset rgcBits[256] = /* # of bits set in one char */ {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; if ( i == 0 ) return 0; for ( ; i > sizeof(*bm)*8; i -= sizeof(*bm)*8, bm++ ) { /* think of it as loop unrolling */ #if LOG_WORD_SIZE >= 3 /* 1 byte per word, or more */ retval += rgcBits[*bm & 255]; /* get the low byte */ #if LOG_WORD_SIZE >= 4 /* at least 2 bytes */ retval += rgcBits[(*bm >> 8) & 255]; #if LOG_WORD_SIZE >= 5 /* at least 4 bytes */ retval += rgcBits[(*bm >> 16) & 255]; retval += rgcBits[(*bm >> 24) & 255]; #if LOG_WORD_SIZE >= 6 /* 8 bytes! */ retval += rgcBits[(*bm >> 32) & 255]; retval += rgcBits[(*bm >> 40) & 255]; retval += rgcBits[(*bm >> 48) & 255]; retval += rgcBits[(*bm >> 56) & 255]; #if LOG_WORD_SIZE >= 7 /* not a concern for a while... */ #error Need to rewrite EntriesUpto to support such big words #endif /* >8 bytes */ #endif /* 8 bytes */ #endif /* 4 bytes */ #endif /* 2 bytes */ #endif /* 1 byte */ } switch ( i ) { /* from 0 to 63 */ case 0: return retval; #if LOG_WORD_SIZE >= 3 /* 1 byte per word, or more */ case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: return (retval + rgcBits[*bm & ((1 << i)-1)]); #if LOG_WORD_SIZE >= 4 /* at least 2 bytes */ case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & ((1 << (i-8))-1)]); #if LOG_WORD_SIZE >= 5 /* at least 4 bytes */ case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + rgcBits[(*bm >> 16) & ((1 << (i-16))-1)]); case 25: case 26: case 27: case 28: case 29: case 30: case 31: case 32: return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + rgcBits[(*bm >> 16) & 255] + rgcBits[(*bm >> 24) & ((1 << (i-24))-1)]); #if LOG_WORD_SIZE >= 6 /* 8 bytes! */ case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + rgcBits[(*bm >> 16) & 255] + rgcBits[(*bm >> 24) & 255] + rgcBits[(*bm >> 32) & ((1 << (i-32))-1)]); case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + rgcBits[(*bm >> 16) & 255] + rgcBits[(*bm >> 24) & 255] + rgcBits[(*bm >> 32) & 255] + rgcBits[(*bm >> 40) & ((1 << (i-40))-1)]); case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + rgcBits[(*bm >> 16) & 255] + rgcBits[(*bm >> 24) & 255] + rgcBits[(*bm >> 32) & 255] + rgcBits[(*bm >> 40) & 255] + rgcBits[(*bm >> 48) & ((1 << (i-48))-1)]); case 57: case 58: case 59: case 60: case 61: case 62: case 63: case 64: return (retval + rgcBits[*bm & 255] + rgcBits[(*bm >> 8) & 255] + rgcBits[(*bm >> 16) & 255] + rgcBits[(*bm >> 24) & 255] + rgcBits[(*bm >> 32) & 255] + rgcBits[(*bm >> 40) & 255] + rgcBits[(*bm >> 48) & 255] + rgcBits[(*bm >> 56) & ((1 << (i-56))-1)]); #endif /* 8 bytes */ #endif /* 4 bytes */ #endif /* 2 bytes */ #endif /* 1 byte */ } assert("" == "word size is too big in EntriesUpto()"); return -1; } #define SPARSE_POS_TO_OFFSET(bm, i) ( EntriesUpto(&((bm)[0]), i) ) #define SPARSE_BUCKET(bin, location) \ ( (bin)[(location) >> LOG_LOW_BIN_SIZE].binSparse + \ SPARSE_POS_TO_OFFSET((bin)[(location)>>LOG_LOW_BIN_SIZE].bmOccupied, \ MOD2(location, LOG_LOW_BIN_SIZE)) ) /*************************************************************************\ | SparseAllocate() | | SparseFree() | | Allocates, sets-to-empty, and frees a sparse array. All you need | | to tell me is how many buckets you want. I return the number of | | buckets I actually allocated, setting the array as a parameter. | | Note that you have to set auxilliary parameters, like cOccupied. | \*************************************************************************/ static ulong SparseAllocate(SparseBin **pbinSparse, ulong cBuckets) { int cGroups = SPARSE_GROUPS(cBuckets); *pbinSparse = (SparseBin *) HTscalloc(sizeof(**pbinSparse) * cGroups); return cGroups << LOG_LOW_BIN_SIZE; } static SparseBin *SparseFree(SparseBin *binSparse, ulong cBuckets) { ulong iGroup, cGroups = SPARSE_GROUPS(cBuckets); for ( iGroup = 0; iGroup < cGroups; iGroup++ ) HTfree(binSparse[iGroup].binSparse, (sizeof(*binSparse[iGroup].binSparse) * binSparse[iGroup].cOccupied)); HTfree(binSparse, sizeof(*binSparse) * cGroups); return NULL; } /*************************************************************************\ | SparseIsEmpty() | | SparseFind() | | You give me a location (ie a number between 1 and t), and I | | return the bucket at that location, or NULL if the bucket is | | empty. It's OK to call Find() on an empty table. | \*************************************************************************/ static int SparseIsEmpty(SparseBin *binSparse, ulong location) { return !TEST_BITMAP(binSparse[location>>LOG_LOW_BIN_SIZE].bmOccupied, MOD2(location, LOG_LOW_BIN_SIZE)); } static SparseBucket *SparseFind(SparseBin *binSparse, ulong location) { if ( SparseIsEmpty(binSparse, location) ) return NULL; return SPARSE_BUCKET(binSparse, location); } /*************************************************************************\ | SparseInsert() | | You give me a location, and contents to put there, and I insert | | into that location and RETURN a pointer to the location. If | | bucket was already occupied, I write over the contents only if | | *pfOverwrite is 1. We set *pfOverwrite to 1 if there was someone | | there (whether or not we overwrote) and 0 else. | \*************************************************************************/ static SparseBucket *SparseInsert(SparseBin *binSparse, SparseBucket *bckInsert, ulong location, int *pfOverwrite) { SparseBucket *bckPlace; HTOffset offset; bckPlace = SparseFind(binSparse, location); if ( bckPlace ) /* means we replace old contents */ { if ( *pfOverwrite ) *bckPlace = *bckInsert; *pfOverwrite = 1; return bckPlace; } binSparse += (location >> LOG_LOW_BIN_SIZE); offset = SPARSE_POS_TO_OFFSET(binSparse->bmOccupied, MOD2(location, LOG_LOW_BIN_SIZE)); binSparse->binSparse = (SparseBucket *) HTsrealloc(binSparse->binSparse, sizeof(*binSparse->binSparse) * ++binSparse->cOccupied, sizeof(*binSparse->binSparse)); memmove(binSparse->binSparse + offset+1, binSparse->binSparse + offset, (binSparse->cOccupied-1 - offset) * sizeof(*binSparse->binSparse)); binSparse->binSparse[offset] = *bckInsert; SET_BITMAP(binSparse->bmOccupied, MOD2(location, LOG_LOW_BIN_SIZE)); *pfOverwrite = 0; return binSparse->binSparse + offset; } /*************************************************************************\ | SparseFirstBucket() | | SparseNextBucket() | | SparseCurrentBit() | | Iterate through the occupied buckets of a dense hashtable. You | | must, of course, have allocated space yourself for the iterator. | \*************************************************************************/ static SparseBucket *SparseNextBucket(SparseIterator *iter) { if ( iter->posOffset != -1 && /* not called from FirstBucket()? */ (++iter->posOffset < iter->binSparse[iter->posGroup].cOccupied) ) return iter->binSparse[iter->posGroup].binSparse + iter->posOffset; iter->posOffset = 0; /* start the next group */ for ( iter->posGroup++; iter->posGroup < SPARSE_GROUPS(iter->cBuckets); iter->posGroup++ ) if ( iter->binSparse[iter->posGroup].cOccupied > 0 ) return iter->binSparse[iter->posGroup].binSparse; /* + 0 */ return NULL; /* all remaining groups were empty */ } static SparseBucket *SparseFirstBucket(SparseIterator *iter, SparseBin *binSparse, ulong cBuckets) { iter->binSparse = binSparse; /* set it up for NextBucket() */ iter->cBuckets = cBuckets; iter->posOffset = -1; /* when we advance, we're at 0 */ iter->posGroup = -1; return SparseNextBucket(iter); } /*************************************************************************\ | SparseWrite() | | SparseRead() | | These are routines for storing a sparse hashtable onto disk. We | | store the number of buckets and a bitmap indicating which buckets | | are allocated (occupied). The actual contents of the buckets | | must be stored separately. | \*************************************************************************/ static void SparseWrite(FILE *fp, SparseBin *binSparse, ulong cBuckets) { ulong i, j; WRITE_UL(fp, cBuckets); for ( i = 0; i < SPARSE_GROUPS(cBuckets); i++ ) for ( j = 0; j < (1<rgBuckets, cBuckets); } static ulong DenseAllocate(DenseBin **pbin, ulong cBuckets) { *pbin = (DenseBin *) HTsmalloc(sizeof(*pbin)); (*pbin)->rgBuckets = (DenseBucket *) HTsmalloc(sizeof(*(*pbin)->rgBuckets) * cBuckets); DenseClear(*pbin, cBuckets); return cBuckets; } static DenseBin *DenseFree(DenseBin *bin, ulong cBuckets) { HTfree(bin->rgBuckets, sizeof(*bin->rgBuckets) * cBuckets); HTfree(bin, sizeof(*bin)); return NULL; } static int DenseIsEmpty(DenseBin *bin, ulong location) { return DENSE_IS_EMPTY(bin->rgBuckets, location); } static DenseBucket *DenseFind(DenseBin *bin, ulong location) { if ( DenseIsEmpty(bin, location) ) return NULL; return bin->rgBuckets + location; } static DenseBucket *DenseInsert(DenseBin *bin, DenseBucket *bckInsert, ulong location, int *pfOverwrite) { DenseBucket *bckPlace; bckPlace = DenseFind(bin, location); if ( bckPlace ) /* means something is already there */ { if ( *pfOverwrite ) *bckPlace = *bckInsert; *pfOverwrite = 1; /* set to 1 to indicate someone was there */ return bckPlace; } else { bin->rgBuckets[location] = *bckInsert; *pfOverwrite = 0; return bin->rgBuckets + location; } } static DenseBucket *DenseNextBucket(DenseIterator *iter) { for ( iter->pos++; iter->pos < iter->cBuckets; iter->pos++ ) if ( !DenseIsEmpty(iter->bin, iter->pos) ) return iter->bin->rgBuckets + iter->pos; return NULL; /* all remaining groups were empty */ } static DenseBucket *DenseFirstBucket(DenseIterator *iter, DenseBin *bin, ulong cBuckets) { iter->bin = bin; /* set it up for NextBucket() */ iter->cBuckets = cBuckets; iter->pos = -1; /* thus the next bucket will be 0 */ return DenseNextBucket(iter); } static void DenseWrite(FILE *fp, DenseBin *bin, ulong cBuckets) { ulong pos = 0, bit, bm; WRITE_UL(fp, cBuckets); while ( pos < cBuckets ) { bm = 0; for ( bit = 0; bit < 8*sizeof(ulong); bit++ ) { if ( !DenseIsEmpty(bin, pos) ) SET_BITMAP(&bm, bit); /* in fks-hash.h */ if ( ++pos == cBuckets ) break; } WRITE_UL(fp, bm); } } static ulong DenseRead(FILE *fp, DenseBin **pbin) { ulong pos = 0, bit, bm, cBuckets; READ_UL(fp, cBuckets); cBuckets = DenseAllocate(pbin, cBuckets); while ( pos < cBuckets ) { READ_UL(fp, bm); for ( bit = 0; bit < 8*sizeof(ulong); bit++ ) { if ( TEST_BITMAP(&bm, bit) ) /* in fks-hash.h */ DENSE_SET_OCCUPIED((*pbin)->rgBuckets, pos); else DENSE_SET_EMPTY((*pbin)->rgBuckets, pos); if ( ++pos == cBuckets ) break; } } return cBuckets; } static ulong DenseMemory(ulong cBuckets, ulong cOccupied) { return cBuckets * sizeof(DenseBucket); } /* ======================================================================== */ /* HASHING ROUTINES */ /* ---------------------- */ /* Implements a simple quadratic hashing scheme. We have a single hash * table of size t and a single hash function h(x). When inserting an * item, first we try h(x) % t. If it's occupied, we try h(x) + * i*(i-1)/2 % t for increasing values of i until we hit a not-occupied * space. To make this dynamic, we double the size of the hash table as * soon as more than half the cells are occupied. When deleting, we can * choose to shrink the hashtable when less than a quarter of the * cells are occupied, or we can choose never to shrink the hashtable. * For lookup, we check h(x) + i*(i-1)/2 % t (starting with i=0) until * we get a match or we hit an empty space. Note that as a result, * we can't make a cell empty on deletion, or lookups may end prematurely. * Instead we mark the cell as "deleted." We thus steal the value * DELETED as a possible "data" value. As long as data are pointers, * that's ok. * The hash increment we use, i(i-1)/2, is not the standard quadratic * hash increment, which is i^2. i(i-1)/2 covers the entire bucket space * when the hashtable size is a power of two, as it is for us. In fact, * the first n probes cover n distinct buckets; then it repeats. This * guarantees insertion will always succeed. * If you linear hashing, set JUMP in chash.h. You can also change * various other parameters there. */ /*************************************************************************\ | Hash() | | The hash function I use is due to Bob Jenkins (see | | http://burtleburtle.net/bob/hash/evahash.html | | According to http://burtleburtle.net/bob/c/lookup2.c, | | his implementation is public domain.) | | It takes 36 instructions, in 18 cycles if you're lucky. | | hashing depends on the fact the hashtable size is always a | | power of 2. cBuckets is probably ht->cBuckets. | \*************************************************************************/ #if LOG_WORD_SIZE == 5 /* 32 bit words */ #define mix(a,b,c) \ { \ a -= b; a -= c; a ^= (c>>13); \ b -= c; b -= a; b ^= (a<<8); \ c -= a; c -= b; c ^= (b>>13); \ a -= b; a -= c; a ^= (c>>12); \ b -= c; b -= a; b ^= (a<<16); \ c -= a; c -= b; c ^= (b>>5); \ a -= b; a -= c; a ^= (c>>3); \ b -= c; b -= a; b ^= (a<<10); \ c -= a; c -= b; c ^= (b>>15); \ } #ifdef WORD_HASH /* play with this on little-endian machines */ #define WORD_AT(ptr) ( *(ulong *)(ptr) ) #else #define WORD_AT(ptr) ( (ptr)[0] + ((ulong)(ptr)[1]<<8) + \ ((ulong)(ptr)[2]<<16) + ((ulong)(ptr)[3]<<24) ) #endif #elif LOG_WORD_SIZE == 6 /* 64 bit words */ #define mix(a,b,c) \ { \ a -= b; a -= c; a ^= (c>>43); \ b -= c; b -= a; b ^= (a<<9); \ c -= a; c -= b; c ^= (b>>8); \ a -= b; a -= c; a ^= (c>>38); \ b -= c; b -= a; b ^= (a<<23); \ c -= a; c -= b; c ^= (b>>5); \ a -= b; a -= c; a ^= (c>>35); \ b -= c; b -= a; b ^= (a<<49); \ c -= a; c -= b; c ^= (b>>11); \ a -= b; a -= c; a ^= (c>>12); \ b -= c; b -= a; b ^= (a<<18); \ c -= a; c -= b; c ^= (b>>22); \ } #ifdef WORD_HASH /* alpha is little-endian, btw */ #define WORD_AT(ptr) ( *(ulong *)(ptr) ) #else #define WORD_AT(ptr) ( (ptr)[0] + ((ulong)(ptr)[1]<<8) + \ ((ulong)(ptr)[2]<<16) + ((ulong)(ptr)[3]<<24) + \ ((ulong)(ptr)[4]<<32) + ((ulong)(ptr)[5]<<40) + \ ((ulong)(ptr)[6]<<48) + ((ulong)(ptr)[7]<<56) ) #endif #else /* neither 32 or 64 bit words */ #error This hash function can only hash 32 or 64 bit words. Sorry. #endif static ulong Hash(HashTable *ht, char *key, ulong cBuckets) { ulong a, b, c, cchKey, cchKeyOrig; cchKeyOrig = ht->cchKey == NULL_TERMINATED ? strlen(key) : ht->cchKey; a = b = c = 0x9e3779b9; /* the golden ratio; an arbitrary value */ for ( cchKey = cchKeyOrig; cchKey >= 3 * sizeof(ulong); cchKey -= 3 * sizeof(ulong), key += 3 * sizeof(ulong) ) { a += WORD_AT(key); b += WORD_AT(key + sizeof(ulong)); c += WORD_AT(key + sizeof(ulong)*2); mix(a,b,c); } c += cchKeyOrig; switch ( cchKey ) { /* deal with rest. Cases fall through */ #if LOG_WORD_SIZE == 5 case 11: c += (ulong)key[10]<<24; case 10: c += (ulong)key[9]<<16; case 9 : c += (ulong)key[8]<<8; /* the first byte of c is reserved for the length */ case 8 : b += WORD_AT(key+4); a+= WORD_AT(key); break; case 7 : b += (ulong)key[6]<<16; case 6 : b += (ulong)key[5]<<8; case 5 : b += key[4]; case 4 : a += WORD_AT(key); break; case 3 : a += (ulong)key[2]<<16; case 2 : a += (ulong)key[1]<<8; case 1 : a += key[0]; /* case 0 : nothing left to add */ #elif LOG_WORD_SIZE == 6 case 23: c += (ulong)key[22]<<56; case 22: c += (ulong)key[21]<<48; case 21: c += (ulong)key[20]<<40; case 20: c += (ulong)key[19]<<32; case 19: c += (ulong)key[18]<<24; case 18: c += (ulong)key[17]<<16; case 17: c += (ulong)key[16]<<8; /* the first byte of c is reserved for the length */ case 16: b += WORD_AT(key+8); a+= WORD_AT(key); break; case 15: b += (ulong)key[14]<<48; case 14: b += (ulong)key[13]<<40; case 13: b += (ulong)key[12]<<32; case 12: b += (ulong)key[11]<<24; case 11: b += (ulong)key[10]<<16; case 10: b += (ulong)key[ 9]<<8; case 9: b += (ulong)key[ 8]; case 8: a += WORD_AT(key); break; case 7: a += (ulong)key[ 6]<<48; case 6: a += (ulong)key[ 5]<<40; case 5: a += (ulong)key[ 4]<<32; case 4: a += (ulong)key[ 3]<<24; case 3: a += (ulong)key[ 2]<<16; case 2: a += (ulong)key[ 1]<<8; case 1: a += (ulong)key[ 0]; /* case 0: nothing left to add */ #endif } mix(a,b,c); return c & (cBuckets-1); } /*************************************************************************\ | Rehash() | | You give me a hashtable, a new size, and a bucket to follow, and | | I resize the hashtable's bin to be the new size, rehashing | | everything in it. I keep particular track of the bucket you pass | | in, and RETURN a pointer to where the item in the bucket got to. | | (If you pass in NULL, I return an arbitrary pointer.) | \*************************************************************************/ static HTItem *Rehash(HashTable *ht, ulong cNewBuckets, HTItem *bckWatch) { Table *tableNew; ulong iBucketFirst; HTItem *bck, *bckNew = NULL; ulong offset; /* the i in h(x) + i*(i-1)/2 */ int fOverwrite = 0; /* not an issue: there can be no collisions */ assert( ht->table ); cNewBuckets = Table(Allocate)(&tableNew, cNewBuckets); /* Since we RETURN the new position of bckWatch, we want * * to make sure it doesn't get moved due to some table * * rehashing that comes after it's inserted. Thus, we * * have to put it in last. This makes the loop weird. */ for ( bck = HashFirstBucket(ht); ; bck = HashNextBucket(ht) ) { if ( bck == NULL ) /* we're done iterating, so look at bckWatch */ { bck = bckWatch; if ( bck == NULL ) /* I guess bckWatch wasn't specified */ break; } else if ( bck == bckWatch ) continue; /* ignore if we see it during the iteration */ offset = 0; /* a new i for a new bucket */ for ( iBucketFirst = Hash(ht, KEY_PTR(ht, bck->key), cNewBuckets); !Table(IsEmpty)(tableNew, iBucketFirst); iBucketFirst = (iBucketFirst + JUMP(KEY_PTR(ht,bck->key), offset)) & (cNewBuckets-1) ) ; bckNew = Table(Insert)(tableNew, bck, iBucketFirst, &fOverwrite); if ( bck == bckWatch ) /* we're done with the last thing to do */ break; } Table(Free)(ht->table, ht->cBuckets); ht->table = tableNew; ht->cBuckets = cNewBuckets; ht->cDeletedItems = 0; return bckNew; /* new position of bckWatch, which was inserted last */ } /*************************************************************************\ | Find() | | Does the quadratic searching stuff. RETURNS NULL if we don't | | find an object with the given key, and a pointer to the Item | | holding the key, if we do. Also sets posLastFind. If piEmpty is | | non-NULL, we set it to the first open bucket we pass; helpful for | | doing a later insert if the search fails, for instance. | \*************************************************************************/ static HTItem *Find(HashTable *ht, ulong key, ulong *piEmpty) { ulong iBucketFirst; HTItem *item; ulong offset = 0; /* the i in h(x) + i*(i-1)/2 */ int fFoundEmpty = 0; /* set when we pass over an empty bucket */ ht->posLastFind = NULL; /* set up for failure: a new find starts */ if ( ht->table == NULL ) /* empty hash table: find is bound to fail */ return NULL; iBucketFirst = Hash(ht, KEY_PTR(ht, key), ht->cBuckets); while ( 1 ) /* now try all i > 0 */ { item = Table(Find)(ht->table, iBucketFirst); if ( item == NULL ) /* it's not in the table */ { if ( piEmpty && !fFoundEmpty ) *piEmpty = iBucketFirst; return NULL; } else { if ( IS_BCK_DELETED(item) ) /* always 0 ifdef INSERT_ONLY */ { if ( piEmpty && !fFoundEmpty ) { *piEmpty = iBucketFirst; fFoundEmpty = 1; } } else if ( !KEY_CMP(ht, key, item->key) ) /* must be occupied */ { ht->posLastFind = item; return item; /* we found it! */ } } iBucketFirst = ((iBucketFirst + JUMP(KEY_PTR(ht, key), offset)) & (ht->cBuckets-1)); } } /*************************************************************************\ | Insert() | | If an item with the key already exists in the hashtable, RETURNS | | a pointer to the item (replacing its data if fOverwrite is 1). | | If not, we find the first place-to-insert (which Find() is nice | | enough to set for us) and insert the item there, RETURNing a | | pointer to the item. We might grow the hashtable if it's getting | | full. Note we include buckets holding DELETED when determining | | fullness, because they slow down searching. | \*************************************************************************/ static ulong NextPow2(ulong x) /* returns next power of 2 > x, or 2^31 */ { if ( ((x << 1) >> 1) != x ) /* next power of 2 overflows */ x >>= 1; /* so we return highest power of 2 we can */ while ( (x & (x-1)) != 0 ) /* blacks out all but the top bit */ x &= (x-1); return x << 1; /* makes it the *next* power of 2 */ } static HTItem *Insert(HashTable *ht, ulong key, ulong data, int fOverwrite) { HTItem *item, bckInsert; ulong iEmpty; /* first empty bucket key probes */ if ( ht->table == NULL ) /* empty hash table: find is bound to fail */ return NULL; item = Find(ht, key, &iEmpty); ht->posLastFind = NULL; /* last operation is insert, not find */ if ( item ) { if ( fOverwrite ) item->data = data; /* key already matches */ return item; } COPY_KEY(ht, bckInsert.key, key); /* make our own copy of the key */ bckInsert.data = data; /* oh, and the data too */ item = Table(Insert)(ht->table, &bckInsert, iEmpty, &fOverwrite); if ( fOverwrite ) /* we overwrote a deleted bucket */ ht->cDeletedItems--; ht->cItems++; /* insert couldn't have overwritten */ if ( ht->cDeltaGoalSize > 0 ) /* closer to our goal size */ ht->cDeltaGoalSize--; if ( ht->cItems + ht->cDeletedItems >= ht->cBuckets * OCCUPANCY_PCT || ht->cDeltaGoalSize < 0 ) /* we must've overestimated # of deletes */ item = Rehash(ht, NextPow2((ulong)(((ht->cDeltaGoalSize > 0 ? ht->cDeltaGoalSize : 0) + ht->cItems) / OCCUPANCY_PCT)), item); return item; } /*************************************************************************\ | Delete() | | Removes the item from the hashtable, and if fShrink is 1, will | | shrink the hashtable if it's too small (ie even after halving, | | the ht would be less than half full, though in order to avoid | | oscillating table size, we insist that after halving the ht would | | be less than 40% full). RETURNS 1 if the item was found, 0 else. | | If fLastFindSet is true, then this function is basically | | DeleteLastFind. | \*************************************************************************/ static int Delete(HashTable *ht, ulong key, int fShrink, int fLastFindSet) { if ( !fLastFindSet && !Find(ht, key, NULL) ) return 0; SET_BCK_DELETED(ht, ht->posLastFind); /* find set this, how nice */ ht->cItems--; ht->cDeletedItems++; if ( ht->cDeltaGoalSize < 0 ) /* heading towards our goal of deletion */ ht->cDeltaGoalSize++; if ( fShrink && ht->cItems < ht->cBuckets * OCCUPANCY_PCT*0.4 && ht->cDeltaGoalSize >= 0 /* wait until we're done deleting */ && (ht->cBuckets >> 1) >= MIN_HASH_SIZE ) /* shrink */ Rehash(ht, NextPow2((ulong)((ht->cItems+ht->cDeltaGoalSize)/OCCUPANCY_PCT)), NULL); ht->posLastFind = NULL; /* last operation is delete, not find */ return 1; } /* ======================================================================== */ /* USER-VISIBLE API */ /* ---------------------- */ /*************************************************************************\ | AllocateHashTable() | | ClearHashTable() | | FreeHashTable() | | Allocate() allocates a hash table and sets up size parameters. | | Free() frees it. Clear() deletes all the items from the hash | | table, but frees not. | | cchKey is < 0 if the keys you send me are meant to be pointers | | to \0-terminated strings. Then -cchKey is the maximum key size. | | If cchKey < one word (ulong), the keys you send me are the keys | | themselves; else the keys you send me are pointers to the data. | | If fSaveKeys is 1, we copy any keys given to us to insert. We | | also free these keys when freeing the hash table. If it's 0, the | | user is responsible for key space management. | | AllocateHashTable() RETURNS a hash table; the others TAKE one. | \*************************************************************************/ HashTable *AllocateHashTable(int cchKey, int fSaveKeys) { HashTable *ht; ht = (HashTable *) HTsmalloc(sizeof(*ht)); /* set everything to 0 */ ht->cBuckets = Table(Allocate)(&ht->table, MIN_HASH_SIZE); ht->cchKey = cchKey <= 0 ? NULL_TERMINATED : cchKey; ht->cItems = 0; ht->cDeletedItems = 0; ht->fSaveKeys = fSaveKeys; ht->cDeltaGoalSize = 0; ht->iter = HTsmalloc( sizeof(TableIterator) ); ht->fpData = NULL; /* set by HashLoad, maybe */ ht->bckData.data = (ulong) NULL; /* this must be done */ HTSetupKeyTrunc(); /* in util.c */ return ht; } void ClearHashTable(HashTable *ht) { HTItem *bck; if ( STORES_PTR(ht) && ht->fSaveKeys ) /* need to free keys */ for ( bck = HashFirstBucket(ht); bck; bck = HashNextBucket(ht) ) { FREE_KEY(ht, bck->key); if ( ht->fSaveKeys == 2 ) /* this means key stored in one block */ break; /* ...so only free once */ } Table(Free)(ht->table, ht->cBuckets); ht->cBuckets = Table(Allocate)(&ht->table, MIN_HASH_SIZE); ht->cItems = 0; ht->cDeletedItems = 0; ht->cDeltaGoalSize = 0; ht->posLastFind = NULL; ht->fpData = NULL; /* no longer HashLoading */ if ( ht->bckData.data ) free( (char *)(ht)->bckData.data); ht->bckData.data = (ulong) NULL; } void FreeHashTable(HashTable *ht) { ClearHashTable(ht); if ( ht->iter ) HTfree(ht->iter, sizeof(TableIterator)); if ( ht->table ) Table(Free)(ht->table, ht->cBuckets); free(ht); } /*************************************************************************\ | HashFind() | | HashFindLast() | | HashFind(): looks in h(x) + i(i-1)/2 % t as i goes up from 0 | | until we either find the key or hit an empty bucket. RETURNS a | | pointer to the item in the hit bucket, if we find it, else | | RETURNS NULL. | | HashFindLast() returns the item returned by the last | | HashFind(), which may be NULL if the last HashFind() failed. | | LOAD_AND_RETURN reads the data from off disk, if necessary. | \*************************************************************************/ HTItem *HashFind(HashTable *ht, ulong key) { LOAD_AND_RETURN(ht, Find(ht, KEY_TRUNC(ht, key), NULL)); } HTItem *HashFindLast(HashTable *ht) { LOAD_AND_RETURN(ht, ht->posLastFind); } /*************************************************************************\ | HashFindOrInsert() | | HashFindOrInsertItem() | | HashInsert() | | HashInsertItem() | | HashDelete() | | HashDeleteLast() | | Pretty obvious what these guys do. Some take buckets (items), | | some take keys and data separately. All things RETURN the bucket | | (a pointer into the hashtable) if appropriate. | \*************************************************************************/ HTItem *HashFindOrInsert(HashTable *ht, ulong key, ulong dataInsert) { /* This is equivalent to Insert without samekey-overwrite */ return Insert(ht, KEY_TRUNC(ht, key), dataInsert, 0); } HTItem *HashFindOrInsertItem(HashTable *ht, HTItem *pItem) { return HashFindOrInsert(ht, pItem->key, pItem->data); } HTItem *HashInsert(HashTable *ht, ulong key, ulong data) { return Insert(ht, KEY_TRUNC(ht, key), data, SAMEKEY_OVERWRITE); } HTItem *HashInsertItem(HashTable *ht, HTItem *pItem) { return HashInsert(ht, pItem->key, pItem->data); } int HashDelete(HashTable *ht, ulong key) { return Delete(ht, KEY_TRUNC(ht, key), !FAST_DELETE, 0); } int HashDeleteLast(HashTable *ht) { if ( !ht->posLastFind ) /* last find failed */ return 0; return Delete(ht, 0, !FAST_DELETE, 1); /* no need to specify a key */ } /*************************************************************************\ | HashFirstBucket() | | HashNextBucket() | | Iterates through the items in the hashtable by iterating through | | the table. Since we know about deleted buckets and loading data | | off disk, and the table doesn't, our job is to take care of these | | things. RETURNS a bucket, or NULL after the last bucket. | \*************************************************************************/ HTItem *HashFirstBucket(HashTable *ht) { HTItem *retval; for ( retval = Table(FirstBucket)(ht->iter, ht->table, ht->cBuckets); retval; retval = Table(NextBucket)(ht->iter) ) if ( !IS_BCK_DELETED(retval) ) LOAD_AND_RETURN(ht, retval); return NULL; } HTItem *HashNextBucket(HashTable *ht) { HTItem *retval; while ( (retval=Table(NextBucket)(ht->iter)) ) if ( !IS_BCK_DELETED(retval) ) LOAD_AND_RETURN(ht, retval); return NULL; } /*************************************************************************\ | HashSetDeltaGoalSize() | | If we're going to insert 100 items, set the delta goal size to | | 100 and we take that into account when inserting. Likewise, if | | we're going to delete 10 items, set it to -100 and we won't | | rehash until all 100 have been done. It's ok to be wrong, but | | it's efficient to be right. Returns the delta value. | \*************************************************************************/ int HashSetDeltaGoalSize(HashTable *ht, int delta) { ht->cDeltaGoalSize = delta; #if FAST_DELETE == 1 || defined INSERT_ONLY if ( ht->cDeltaGoalSize < 0 ) /* for fast delete, we never */ ht->cDeltaGoalSize = 0; /* ...rehash after deletion */ #endif return ht->cDeltaGoalSize; } /*************************************************************************\ | HashSave() | | HashLoad() | | HashLoadKeys() | | Routines for saving and loading the hashtable from disk. We can | | then use the hashtable in two ways: loading it back into memory | | (HashLoad()) or loading only the keys into memory, in which case | | the data for a given key is loaded off disk when the key is | | retrieved. The data is freed when something new is retrieved in | | its place, so this is not a "lazy-load" scheme. | | The key is saved automatically and restored upon load, but the | | user needs to specify a routine for reading and writing the data. | | fSaveKeys is of course set to 1 when you read in a hashtable. | | HashLoad RETURNS a newly allocated hashtable. | | DATA_WRITE() takes an fp and a char * (representing the data | | field), and must perform two separate tasks. If fp is NULL, | | return the number of bytes written. If not, writes the data to | | disk at the place the fp points to. | | DATA_READ() takes an fp and the number of bytes in the data | | field, and returns a char * which points to wherever you've | | written the data. Thus, you must allocate memory for the data. | | Both dataRead and dataWrite may be NULL if you just wish to | | store the data field directly, as an integer. | \*************************************************************************/ void HashSave(FILE *fp, HashTable *ht, int (*dataWrite)(FILE *, char *)) { long cchData, posStart; HTItem *bck; /* File format: magic number (4 bytes) : cchKey (one word) : cItems (one word) : cDeletedItems (one word) : table info (buckets and a bitmap) : cchAllKeys (one word) Then the keys, in a block. If cchKey is NULL_TERMINATED, the keys are null-terminated too, otherwise this takes up cchKey*cItems bytes. Note that keys are not written for DELETED buckets. Then the data: : EITHER DELETED (one word) to indicate it's a deleted bucket, : OR number of bytes for this (non-empty) bucket's data (one word). This is not stored if dataWrite == NULL since the size is known to be sizeof(ul). Plus: : the data for this bucket (variable length) All words are in network byte order. */ fprintf(fp, "%s", MAGIC_KEY); WRITE_UL(fp, ht->cchKey); /* WRITE_UL, READ_UL, etc in fks-hash.h */ WRITE_UL(fp, ht->cItems); WRITE_UL(fp, ht->cDeletedItems); Table(Write)(fp, ht->table, ht->cBuckets); /* writes cBuckets too */ WRITE_UL(fp, 0); /* to be replaced with sizeof(key block) */ posStart = ftell(fp); for ( bck = HashFirstBucket(ht); bck; bck = HashNextBucket(ht) ) fwrite(KEY_PTR(ht, bck->key), 1, (ht->cchKey == NULL_TERMINATED ? strlen(KEY_PTR(ht, bck->key))+1 : ht->cchKey), fp); cchData = ftell(fp) - posStart; fseek(fp, posStart - sizeof(unsigned long), SEEK_SET); WRITE_UL(fp, cchData); fseek(fp, 0, SEEK_END); /* done with our sojourn at the header */ /* Unlike HashFirstBucket, TableFirstBucket iters through deleted bcks */ for ( bck = Table(FirstBucket)(ht->iter, ht->table, ht->cBuckets); bck; bck = Table(NextBucket)(ht->iter) ) if ( dataWrite == NULL || IS_BCK_DELETED(bck) ) WRITE_UL(fp, bck->data); else /* write cchData followed by the data */ { WRITE_UL(fp, (*dataWrite)(NULL, (char *)bck->data)); (*dataWrite)(fp, (char *)bck->data); } } static HashTable *HashDoLoad(FILE *fp, char * (*dataRead)(FILE *, int), HashTable *ht) { ulong cchKey; char szMagicKey[4], *rgchKeys; HTItem *bck; fread(szMagicKey, 1, 4, fp); if ( strncmp(szMagicKey, MAGIC_KEY, 4) ) { fprintf(stderr, "ERROR: not a hash table (magic key is %4.4s, not %s)\n", szMagicKey, MAGIC_KEY); exit(3); } Table(Free)(ht->table, ht->cBuckets); /* allocated in AllocateHashTable */ READ_UL(fp, ht->cchKey); READ_UL(fp, ht->cItems); READ_UL(fp, ht->cDeletedItems); ht->cBuckets = Table(Read)(fp, &ht->table); /* next is the table info */ READ_UL(fp, cchKey); rgchKeys = (char *) HTsmalloc( cchKey ); /* stores all the keys */ fread(rgchKeys, 1, cchKey, fp); /* We use the table iterator so we don't try to LOAD_AND_RETURN */ for ( bck = Table(FirstBucket)(ht->iter, ht->table, ht->cBuckets); bck; bck = Table(NextBucket)(ht->iter) ) { READ_UL(fp, bck->data); /* all we need if dataRead is NULL */ if ( IS_BCK_DELETED(bck) ) /* always 0 if defined(INSERT_ONLY) */ continue; /* this is why we read the data first */ if ( dataRead != NULL ) /* if it's null, we're done */ if ( !ht->fpData ) /* load data into memory */ bck->data = (ulong)dataRead(fp, bck->data); else /* store location of data on disk */ { fseek(fp, bck->data, SEEK_CUR); /* bck->data held size of data */ bck->data = ftell(fp) - bck->data - sizeof(unsigned long); } if ( ht->cchKey == NULL_TERMINATED ) /* now read the key */ { bck->key = (ulong) rgchKeys; rgchKeys = strchr(rgchKeys, '\0') + 1; /* read past the string */ } else { if ( STORES_PTR(ht) ) /* small keys stored directly */ bck->key = (ulong) rgchKeys; else memcpy(&bck->key, rgchKeys, ht->cchKey); rgchKeys += ht->cchKey; } } if ( !STORES_PTR(ht) ) /* keys are stored directly */ HTfree(rgchKeys - cchKey, cchKey); /* we've advanced rgchK to end */ return ht; } HashTable *HashLoad(FILE *fp, char * (*dataRead)(FILE *, int)) { HashTable *ht; ht = AllocateHashTable(0, 2); /* cchKey set later, fSaveKey should be 2! */ return HashDoLoad(fp, dataRead, ht); } HashTable *HashLoadKeys(FILE *fp, char * (*dataRead)(FILE *, int)) { HashTable *ht; if ( dataRead == NULL ) return HashLoad(fp, NULL); /* no reason not to load the data here */ ht = AllocateHashTable(0, 2); /* cchKey set later, fSaveKey should be 2! */ ht->fpData = fp; /* tells HashDoLoad() to only load keys */ ht->dataRead = dataRead; return HashDoLoad(fp, dataRead, ht); } /*************************************************************************\ | PrintHashTable() | | A debugging tool. Prints the entire contents of the hash table, | | like so: : key of the contents. Returns number of bytes | | allocated. If time is not -1, we print it as the time required | | for the hash. If iForm is 0, we just print the stats. If it's | | 1, we print the keys and data too, but the keys are printed as | | ulongs. If it's 2, we print the keys correctly (as long numbers | | or as strings). | \*************************************************************************/ ulong PrintHashTable(HashTable *ht, double time, int iForm) { ulong cbData = 0, cbBin = 0, cItems = 0, cOccupied = 0; HTItem *item; printf("HASH TABLE.\n"); if ( time > -1.0 ) { printf("----------\n"); printf("Time: %27.2f\n", time); } for ( item = Table(FirstBucket)(ht->iter, ht->table, ht->cBuckets); item; item = Table(NextBucket)(ht->iter) ) { cOccupied++; /* this includes deleted buckets */ if ( IS_BCK_DELETED(item) ) /* we don't need you for anything else */ continue; cItems++; /* this is for a sanity check */ if ( STORES_PTR(ht) ) cbData += ht->cchKey == NULL_TERMINATED ? WORD_ROUND(strlen((char *)item->key)+1) : ht->cchKey; else cbBin -= sizeof(item->key), cbData += sizeof(item->key); cbBin -= sizeof(item->data), cbData += sizeof(item->data); if ( iForm != 0 ) /* we want the actual contents */ { if ( iForm == 2 && ht->cchKey == NULL_TERMINATED ) printf("%s/%lu\n", (char *)item->key, item->data); else if ( iForm == 2 && STORES_PTR(ht) ) printf("%.*s/%lu\n", (int)ht->cchKey, (char *)item->key, item->data); else /* either key actually is a ulong, or iForm == 1 */ printf("%lu/%lu\n", item->key, item->data); } } assert( cItems == ht->cItems ); /* sanity check */ cbBin = Table(Memory)(ht->cBuckets, cOccupied); printf("----------\n"); printf("%lu buckets (%lu bytes). %lu empty. %lu hold deleted items.\n" "%lu items (%lu bytes).\n" "%lu bytes total. %lu bytes (%2.1f%%) of this is ht overhead.\n", ht->cBuckets, cbBin, ht->cBuckets - cOccupied, cOccupied - ht->cItems, ht->cItems, cbData, cbData + cbBin, cbBin, cbBin*100.0/(cbBin+cbData)); return cbData + cbBin; } discoSnp/kissreads/src/interface_libchash.c0000644000000000000000000003156712412737602020076 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * interface between libchash and the generic hash functions used in mapsembler */ #include #include #include #include /* for strdup */ #include /* for toupper */ #include /* for hash_add_int_to_list */ #include #include "commons.h" //#define debug_libchash_access /* * prepare the key for the hash table: * we only use uppercase keys */ /* * insert an element in the hash table * * hash_insert returns 0 on success * * in the case of mapsembler, hash_insert will only be used to insert pointers, so we dont need to reserve data space * this is a FIXME if we need to call hash_insert to copy data longer than a pointer. */ int hash_insert(hash_t map, const char *key, const void * data, size_t len){ HTItem *res; #ifdef debug_libchash_access printf("inserting key %s and data %d of length %d\n",key,*((int*)data),(int)len); #endif res=HashFindOrInsert( (struct HashTable*)map, PTR_KEY((struct HashTable*)map,key),(ulong) data); if (res!=NULL) return 0; return -1; } /* * create the hash table * * for now we dont care about nbuckets for hash_create */ hash_t hash_create(unsigned int nbuckets){ /** * arguments for AllocateHashTable(): * * cchKey: if it's a positive number, then each key is a * fixed-length record of that length. If it's 0, * the key is assumed to be a \0-terminated string. * fSaveKey: normally, you are responsible for allocating * space for the key. If this is 1, we make a * copy of the key for you. */ return (hash_t)AllocateHashTable(0,1); } hash_t hash_create_binarykey(unsigned int nbuckets){ /** * arguments for AllocateHashTable(): * * cchKey: if it's a positive number, then each key is a * fixed-length record of that length. If it's 0, * the key is assumed to be a \0-terminated string. * fSaveKey: normally, you are responsible for allocating * space for the key. If this is 1, we make a * copy of the key for you. */ return (hash_t)AllocateHashTable(sizeof(kmer_type),1); } void hash_clear(hash_t map, void (*specific_free)(const void *)){ hash_iter iterator=hash_iterator_init(map); /* is the hash table empty? */ if (iterator < 0) return; char *key; void *data; /* * free all lists */ while (!hash_iterator_is_end(map,iterator)) { hash_iterator_return_entry(map,iterator,&key,(void **)&data); specific_free((void **)&data); iterator=hash_iterator_next(map,iterator); } /* * free hash table */ ClearHashTable((struct HashTable*)map); } /* * fully delete and free the hash table * * in hashmap, hash_delete recursively deletes while calling specific free function at each element, * so we do this too * */ int hash_delete(hash_t map, void (*specific_free)(const void *)){ hash_iter iterator=hash_iterator_init(map); /* is the hash table empty? */ if (iterator < 0) return 0; char *key; void *data; /* * free all lists */ while (!hash_iterator_is_end(map,iterator)) { hash_iterator_return_entry(map,iterator,&key,(void **)&data); specific_free((void **)&data); iterator=hash_iterator_next(map,iterator); } /* * free hash table */ FreeHashTable((struct HashTable*)map); return 0; } /* * retrieve an element from the hash table * */ ssize_t hash_entry_by_key(hash_t map, const char *key, void **data){ HTItem *res; res=HashFind((struct HashTable*)map, PTR_KEY((struct HashTable*)map,key)); if (res!=NULL) { *data=(void **)(res->data); #ifdef debug_libchash_access printf("accessing key %s yielding data %X\n",key,*(unsigned int*)data); #endif return sizeof(ulong); } #ifdef debug_libchash_access printf("accessing key %s -- not found\n",key); #endif return 0;// TODO: maybe make it return the length of the data, as specified in the interface, // but for now we don't need it apparently } /* * iterator functions * */ hash_iter hash_iterator_init(hash_t map){ hash_iter iter; iter=(hash_iter) HashFirstBucket((struct HashTable*)map); if (iter==NULL || iter == (hash_iter)-1) return (hash_iter)-1; return iter; } hash_iter hash_iterator_next(hash_t map, hash_iter iter){ hash_iter next_iter; next_iter=(hash_iter) HashNextBucket((struct HashTable*)map); return next_iter; } hash_iter hash_iterator_is_end(hash_t map, hash_iter iter){ //return (hash_iter)(iter==NULL || (int) iter == -1); if (iter==NULL || iter == (hash_iter)-1) return (hash_iter)1; else return (hash_iter)0; } ssize_t hash_iterator_return_entry(hash_t map, hash_iter iter, char **key, void **data){ assert(map != NULL); assert(iter >= 0); assert(key != NULL); assert(data != NULL); //if ((int)iter != -1 && !hash_iterator_is_end(map, iter)) if (iter != NULL && iter != (hash_iter)-1 &&!hash_iterator_is_end(map, iter)) { HTItem *my_iterator=(HTItem*)iter; *key=KEY_PTR((struct HashTable*)map,my_iterator->key); /*// that actually may happen if (*key==NULL) { printf("null key in hash at iterator %X\n",(int)iter);exit(1); }*/ *data=(void **)(my_iterator->data); #ifdef debug_libchash_access printf("returning data key: %s data: %X\n",*key,(int)*(int **)data); #endif return sizeof(ulong); } else { #ifdef debug_libchash_access printf("returning data key: %s -- not found\n",*key); #endif } return 0; // TODO: maybe make it return the length of the data, as specified in the interface, // but for now we don't need it in mapsembler apparently } /* * advanced functions */ ssize_t hash_search_key_int_value(hash_t map, const char *key, const int value_to_search){ HTItem *res; res=HashFind( (struct HashTable*)map, PTR_KEY((struct HashTable*)map,key)); if (res != NULL) { #ifdef debug_libchash_access printf("searching for key: %s value: %d whereas data is: %X\n",key,value_to_search,*(int*)(res->data) ); #endif if((*(int *) (res->data)) == value_to_search) return 1; } return 0; } void hash_set_int_to_key(hash_t map, char * key, int value){ int * p_value; if(hash_entry_by_key(map, key, (void **) (&p_value)) == 0){ // first time a value is added to this key #ifdef debug_libchash_access printf("first time a value is set to this key %s\n", key); // DEB #endif p_value= (int *)malloc(sizeof(int)); *p_value = value; hash_insert(map, key, p_value, sizeof(int *)); } else { #ifdef debug_libchash_access printf("new time a value is set to this key %s\n", key); // DEB #endif *p_value=value; } } int* hash_get_int_value(hash_t map, char * key){ int * p_value; if(hash_entry_by_key(map, key, (void **) (&p_value)) != 0){ return p_value; } return NULL; } void hash_increase_int_value_if_exists(hash_t map, char * key){ int * p_value; if(hash_entry_by_key(map, key, (void **) (&p_value)) != 0){ *p_value=(*p_value)+1; } } /* * requirement: the hash table cells are lists * these functions add elements to the lists * not sure whether it really belongs to this file.. more like to a hash_common.c file */ void hash_add_int_to_list(hash_t map, char * key, int value){ int * p_value = (int *)malloc(sizeof(int)); *p_value = value; hash_add_something_to_list(map, key, p_value); } inline void get_offset_and_nb_from_sinfo(hash_val sinfo, uint64_t * offset_seed,uint64_t * nb_seeds ) { *nb_seeds = sinfo & mask_nbseed; *offset_seed = (sinfo >> nbits_nbseeds) & mask_offset_seed ; } inline void set_offset_and_nb_into_sinfo(hash_val * sinfo, uint64_t offset_seed,uint64_t nb_seeds ) { hash_val new_val = 0 ; new_val = (offset_seed << nbits_nbseeds ) + nb_seeds ; *sinfo = new_val; } void iterate_and_fill_offsets(hash_t map){ uint64_t offset_courant=0; // seedinfo sinfo; hash_val sinfo; uint64_t offset_seed; uint64_t nb_seeds; //iterate over hash table uint64_t nbdiffseeds= 0; HTItem *bck; for ( bck = HashFirstBucket((struct HashTable*)map); bck; bck = HashNextBucket((struct HashTable*)map) ) { sinfo = (hash_val) (bck->data); get_offset_and_nb_from_sinfo(sinfo, &offset_seed, &nb_seeds); set_offset_and_nb_into_sinfo(&sinfo, offset_courant, 0); offset_courant += nb_seeds ; bck->data = sinfo; nbdiffseeds ++; } } void hash_fill_kmer_index(hash_t map, const kmer_type * key, couple * seed_table, const int fragment_id, const int position_on_fragment){ HTItem *res; hash_val sinfo; uint64_t offset_seed; uint64_t nb_seeds; uint64_t indexseed; couple new_couple; res=HashFind((struct HashTable*)map, *key); assert(res!=NULL); //key should be present sinfo = (hash_val) (res->data); get_offset_and_nb_from_sinfo(sinfo, &offset_seed, &nb_seeds); indexseed = offset_seed + nb_seeds ; new_couple.a = fragment_id; new_couple.b = position_on_fragment; seed_table[indexseed]=new_couple; Sinc24(nb_seeds) ; set_offset_and_nb_into_sinfo(&sinfo, offset_seed, nb_seeds); res->data = sinfo; } int get_seed_info(hash_t map, const kmer_type * key, uint64_t * offset_seed, uint64_t * nb_seeds){ HTItem *res; hash_val sinfo; res=HashFind((struct HashTable*)map, *key); if(res!=NULL) { sinfo = (hash_val) (res->data); get_offset_and_nb_from_sinfo(sinfo, offset_seed, nb_seeds); return 1; } return 0; } //int get_seed_info(hash_t map, const char * key, uint64_t * offset_seed, uint64_t * nb_seeds){ // // HTItem *res; // hash_val sinfo; // // kmer_type graine; // graine = codeSeed(key); // // res=HashFind((struct HashTable*)map, graine); // // if(res!=NULL) // { // sinfo = (hash_val) (res->data); // get_offset_and_nb_from_sinfo(sinfo, offset_seed, nb_seeds); // // return 1; // } // return 0; // //} void hash_incr_kmer_count(hash_t map, const kmer_type * key){ HTItem *res; uint64_t offset_seed; uint64_t nb_seeds; hash_val sinfo; res=HashFindOrInsert( (struct HashTable*)map, *key,(ulong) 0); // find or insert 0 sinfo = (hash_val) (res->data); get_offset_and_nb_from_sinfo(sinfo, &offset_seed, &nb_seeds); Sinc24(nb_seeds) ; // saturated inc to 24 bit set_offset_and_nb_into_sinfo(&sinfo, offset_seed, nb_seeds); res->data = sinfo; } void hash_add_something_to_list(hash_t map, const char * key, void * something){ list * somethings; if(hash_entry_by_key(map, key, (void **) (&somethings)) == 0){ // first time a value is added to this key #ifdef debug_libchash_access printf("first time a value is added to this key %s\n", key); // DEB #endif somethings = list_create(); list_add(somethings, something); hash_insert(map, key, somethings, sizeof(list *)); } else {// we add the current couple (read, position) to the list of the well mapped read for this fragment list_add(somethings, something); #ifdef debug_libchash_access printf("new time a value is added to this key %s\n", key); // DEB #endif } } discoSnp/kissreads/src/outputs.c0000644000000000000000000011142412424174356016017 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * outputs.c * * Created on: 27 oct. 2010 * Author: ppeterlo */ #include #include #include #include //#include #include #include #include #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define ABS(a) (((a) < 0) ? -(a) : (a)) //#define DEBUG_QUALITY #if !HAVE_LOG2F #define log2f log #endif // Operation made on each data set (read_set_id) //#define op() MIN(corrected_avg_lo[read_set_id],corrected_avg_up[read_set_id]) / (corrected_avg_lo[read_set_id]+corrected_avg_up[read_set_id]); #define op() corrected_avg_up[read_set_id] / (corrected_avg_lo[read_set_id]+corrected_avg_up[read_set_id]); float rank_max(const float * corrected_avg_up, const float * corrected_avg_lo, const int number_of_read_sets){ int read_set_id; float rank=0; float temp; // float sum=0; for(read_set_id=0;read_set_id rank) rank = temp; } } return rank; } float rank_min(const float * corrected_avg_up, const float * corrected_avg_lo, const int number_of_read_sets){ int read_set_id; float rank=INT_MAX; float temp; for(read_set_id=0;read_set_id %f\n", entropy); return entropy; } /*Calculates the phi coefficient of 2*2 contingency table. Value close to 1 indicates an association between the alleles and the conditions.*/ /*Note that this value is valid if at least 3 out of the 4 values are non 0, or if the .Otherwise it output -1*/ float phi(int a,int b, int c,int d) { // int denom=(a+b)*(c+d)*(a+c)*(b+d); // if (denom==0) // return 0; // float Phi = (a*d-b*c)/sqrt(denom); // return Phi; if((a+b)==0) return 0; if((c+d)==0) return 0; if((a+c)==0) return 0; if((b+d)==0) return 0; // avoid the computation of denom, possibly bigger than an int or an unsigned long long int... return (a*d-b*c)/(sqrt((float)(a+b))*sqrt((float)(c+d))*sqrt((float)(a+c))*sqrt((float)(b+d))); } /*Computes the chi2 value of the matrix 2*number_of_read_sets */ float rank_phi_N (const int *sum_up, const int *sum_lo, const int number_of_read_sets) { if (number_of_read_sets==1) return 0; int i; float n=0; for (i=0;inb_reads_overlapping_AS[read_set_id] + results_against_set[cycle_id]->nb_reads_overlapping_SB[read_set_id] + results_against_set[cycle_id]->nb_reads_fully_in_S[read_set_id] - results_against_set[cycle_id]->nb_reads_overlapping_both_AS_and_SB[read_set_id]; sum_lo[read_set_id]=results_against_set[cycle_id + 1]->nb_reads_overlapping_both_AS_and_SB[read_set_id]; } float rank = rank_phi_N(sum_up,sum_lo,number_of_read_sets); if (!standard_fasta) { // UPPER PATH fprintf(out, "%2f >%s%s|", rank, comment,results_against_set[cycle_id]->comment); if (countingOption == 0) { for(read_set_id=0;read_set_idnb_reads_overlapping_AS[read_set_id]); fprintf(out, "SB%d_%d|",read_set_id+1,results_against_set[cycle_id]->nb_reads_overlapping_SB[read_set_id]); fprintf(out, "ASSB%d_%d|",read_set_id+1,results_against_set[cycle_id]->nb_reads_overlapping_both_AS_and_SB[read_set_id]); } } else if (countingOption == 2) {//all counts for(read_set_id=0;read_set_idnb_reads_overlapping_AS[read_set_id]); fprintf(out, "SB%d_%d|",read_set_id+1,results_against_set[cycle_id]->nb_reads_overlapping_SB[read_set_id]); fprintf(out, "S%d_%d|",read_set_id+1,results_against_set[cycle_id]->nb_reads_fully_in_S[read_set_id]); fprintf(out, "ASSB%d_%d|",read_set_id+1,results_against_set[cycle_id]->nb_reads_overlapping_both_AS_and_SB[read_set_id]); }} fprintf(out, "rank_%.5f",rank); fprintf(out, ";%s%s%s;", results_against_set[cycle_id]->left_extension, results_against_set[cycle_id]->w, results_against_set[cycle_id]->right_extension); // LOWER PATH fprintf(out, ">%s%s|", comment, results_against_set[cycle_id+1]->comment); char * optionsCounts = ( countingOption == 0) ? "C" : "AB" ; for(read_set_id=0;read_set_idleft_extension, results_against_set[cycle_id+1]->w, results_against_set[cycle_id+1]->right_extension); } else // standard fasta, only one output possible { // UPPER PATH fprintf(out, ">%s%s|", comment,results_against_set[cycle_id]->comment); for(read_set_id=0;read_set_idnb_reads_overlapping_AS[read_set_id]); fprintf(out, "SB%d_%d|",read_set_id+1,results_against_set[cycle_id]->nb_reads_overlapping_SB[read_set_id]); fprintf(out, "S%d_%d|",read_set_id+1,results_against_set[cycle_id]->nb_reads_fully_in_S[read_set_id]); fprintf(out, "ASSB%d_%d|",read_set_id+1,results_against_set[cycle_id]->nb_reads_overlapping_both_AS_and_SB[read_set_id]); } fprintf(out, "rank_%.5f",rank); fprintf(out, "\n%s%s%s\n", results_against_set[cycle_id]->left_extension, results_against_set[cycle_id]->w, results_against_set[cycle_id]->right_extension); // LOWER PATH fprintf(out, ">%s%s|", comment, results_against_set[cycle_id+1]->comment); for(read_set_id=0;read_set_idnb_reads_overlapping_both_AS_and_SB[read_set_id]); fprintf(out, "rank_%.5f",rank); fprintf(out, "\n%s%s%s\n", results_against_set[cycle_id+1]->left_extension, results_against_set[cycle_id+1]->w, results_against_set[cycle_id+1]->right_extension); } } #else // INPUT_FROM_KISSPLICE /** * prints a couple using the reads starting position instead of coverage per position */ void print_couple_i(char * comment, FILE* out, const p_fragment_info * results_against_set, int cycle_id, int number_of_read_sets, int qual, const char map_snps){ // on upper path int sum_up[number_of_read_sets]; int avg_up[number_of_read_sets]; // on lower path int sum_lo[number_of_read_sets]; int avg_lo[number_of_read_sets]; int read_set_id; if( qual ){ // we are providing results for generic dataset // if(!map_snps){ // TODO: UNTESTED CODE. // for(read_set_id=0;read_set_idw)-kmer_size;j++){ // if(results_against_set[cycle_id]->read_coherent_positions[read_set_id][j]) //#ifdef CHARQUAL // FIXME: IT SHOULKD BE THE OPOSIT NO ? (PIERRE APRL 2013) // avg_up[read_set_id] = avg_up[read_set_id] + results_against_set[cycle_id]->sum_quality_per_position[read_set_id][j]; //#else // avg_up[read_set_id] = avg_up[read_set_id] + (results_against_set[cycle_id]->sum_quality_per_position[read_set_id][j] / results_against_set[cycle_id]->read_coherent_positions[read_set_id][j]); //#endif // } // } // for(read_set_id=0;read_set_idw)-kmer_size;j++){ // if(results_against_set[cycle_id+1]->read_coherent_positions[read_set_id][j]) //#ifdef CHARQUAL // FIXME: IT SHOULKD BE THE OPOSIT NO ? (PIERRE APRL 2013) // avg_lo[read_set_id] = avg_lo[read_set_id] + results_against_set[cycle_id+1]->sum_quality_per_position[read_set_id][j]; //#else // avg_lo[read_set_id] = avg_lo[read_set_id] + (results_against_set[cycle_id+1]->sum_quality_per_position[read_set_id][j] / results_against_set[cycle_id+1]->read_coherent_positions[read_set_id][j]); //#endif // } // } // } // END TODO. // else{ // we are providing results for a SNP or a splicing..., we give outputs only for the central position //compute average quality for the variant (position quality if SNP) for(read_set_id=0;read_set_idw)/2; if(results_against_set[cycle_id]->read_coherent_positions[read_set_id][snp_pos]) #ifdef CHARQUAL // FIXME: IT SHOULKD BE THE OPOSIT NO ? (PIERRE APRL 2013) avg_up[read_set_id] = avg_up[read_set_id] + results_against_set[cycle_id]->sum_quality_per_position[read_set_id][snp_pos]; #else avg_up[read_set_id] = avg_up[read_set_id] + (results_against_set[cycle_id]->sum_quality_per_position[read_set_id][snp_pos] / results_against_set[cycle_id]->read_coherent_positions[read_set_id][snp_pos]); #endif // avg_up[read_set_id] = avg_up[read_set_id] / (strlen(results_against_set[cycle_id]->w) - 2*kmer_size + 2); } //compute average quality for the variant (position quality if SNP) for(read_set_id=0;read_set_idw)/2; if(results_against_set[cycle_id+1]->read_coherent_positions[read_set_id][snp_pos]) #ifdef CHARQUAL // FIXME: IT SHOULD BE THE OPOSIT NO ? (PIERRE APRL 2013) avg_lo[read_set_id] = avg_lo[read_set_id] + results_against_set[cycle_id+1]->sum_quality_per_position[read_set_id][snp_pos]; #else avg_lo[read_set_id] = avg_lo[read_set_id] + (results_against_set[cycle_id+1]->sum_quality_per_position[read_set_id][snp_pos] / results_against_set[cycle_id+1]->read_coherent_positions[read_set_id][snp_pos]); #endif // avg_lo[read_set_id] = avg_lo[read_set_id] / (strlen(results_against_set[cycle_id+1]->w) - 2*kmer_size + 2); } // } } // float sum=0; for(read_set_id=0;read_set_idnumber_mapped_reads[read_set_id]; // compute_min_max_sum_starting_reads(results_against_set[read_set_id][cycle_id], &min_up[read_set_id], &max_up[read_set_id], &sum_up[read_set_id]); /// LOWER sum_lo[read_set_id]=results_against_set[cycle_id+1]->number_mapped_reads[read_set_id]; //compute_min_max_sum_starting_reads(results_against_set[read_set_id][cycle_id+1], &min_lo[read_set_id], &max_lo[read_set_id], &sum_lo[read_set_id]); } if (!standard_fasta) { float rank = rank_phi_N(sum_up,sum_lo,number_of_read_sets); // UPPER PATH //fprintf(out, ">%s%s|", comment,results_against_set[cycle_id]->comment); fprintf(out, "%2f >%s%s|", rank, comment,results_against_set[cycle_id]->comment); for(read_set_id=0;read_set_idleft_extension, results_against_set[cycle_id]->w, results_against_set[cycle_id]->right_extension); //#else else fprintf(out, ";%s", results_against_set[cycle_id]->w); //#endif fprintf(out, ";"); // LOWER PATH fprintf(out, ">%s%s|", comment, results_against_set[cycle_id+1]->comment); for(read_set_id=0;read_set_idleft_extension, results_against_set[cycle_id+1]->w, results_against_set[cycle_id+1]->right_extension); //#else else fprintf(out, ";%s", results_against_set[cycle_id+1]->w); //#endif fprintf(out, "\n"); } else { // UPPER PATH fprintf(out, ">%s%s|", comment,results_against_set[cycle_id]->comment); for(read_set_id=0;read_set_idleft_extension, results_against_set[cycle_id]->w, results_against_set[cycle_id]->right_extension); //#else else fprintf(out, "\n%s\n", results_against_set[cycle_id]->w); //#endif // LOWER PATH fprintf(out, ">%s%s|", comment, results_against_set[cycle_id+1]->comment); for(read_set_id=0;read_set_idleft_extension, results_against_set[cycle_id+1]->w, results_against_set[cycle_id+1]->right_extension); //#else else fprintf(out, "\n%s\n", results_against_set[cycle_id+1]->w); //#endif } } #endif // INPUT_FROM_KISSPLICE /** * prints a couple using the reads starting position instead of coverage per position */ void print_quadruplet_i(FILE* out, const p_fragment_info * results_against_set, int cycle_id, int number_of_read_sets, int qual){ int j; int cov_1[number_of_read_sets] ; // coverage path 1 au int cov_2[number_of_read_sets] ; // coverage path 2 vb int cov_3[number_of_read_sets] ; // coverage path 3 av' int cov_4[number_of_read_sets] ; // coverage path 4 u'b int qual_1[number_of_read_sets]; // quality path 1 int qual_2[number_of_read_sets]; // quality path 2 int qual_3[number_of_read_sets]; // quality path 3 int qual_4[number_of_read_sets]; // quality path 4 int read_set_id; if( qual ){// TODO: UNTESTED CODE - APRIL 2013 // we are providing results for generic dataset for(read_set_id=0;read_set_idw)-kmer_size;j++){ #ifdef CHARQUAL // FIXME: IT SHOULKD BE THE OPOSIT NO ? (PIERRE APRL 2013) if(results_against_set[cycle_id]->read_coherent_positions[read_set_id][j]) qual_1[read_set_id] = qual_1[read_set_id] + results_against_set[cycle_id]->sum_quality_per_position[read_set_id][j]; if(results_against_set[cycle_id+1]->read_coherent_positions[read_set_id][j]) qual_2[read_set_id] = qual_2[read_set_id] + results_against_set[cycle_id+1]->sum_quality_per_position[read_set_id][j]; if(results_against_set[cycle_id+2]->read_coherent_positions[read_set_id][j]) qual_3[read_set_id] = qual_3[read_set_id] + results_against_set[cycle_id+2]->sum_quality_per_position[read_set_id][j]; if(results_against_set[cycle_id+3]->read_coherent_positions[read_set_id][j]) qual_4[read_set_id] = qual_4[read_set_id] + results_against_set[cycle_id+3]->sum_quality_per_position[read_set_id][j]; #else if(results_against_set[cycle_id]->read_coherent_positions[read_set_id][j]) qual_1[read_set_id] = qual_1[read_set_id] + (results_against_set[cycle_id]->sum_quality_per_position[read_set_id][j] / results_against_set[cycle_id]->read_coherent_positions[read_set_id][j]); if(results_against_set[cycle_id+1]->read_coherent_positions[read_set_id][j]) qual_2[read_set_id] = qual_2[read_set_id] + (results_against_set[cycle_id+1]->sum_quality_per_position[read_set_id][j] / results_against_set[cycle_id+1]->read_coherent_positions[read_set_id][j]); if(results_against_set[cycle_id+2]->read_coherent_positions[read_set_id][j]) qual_3[read_set_id] = qual_3[read_set_id] + (results_against_set[cycle_id+2]->sum_quality_per_position[read_set_id][j] / results_against_set[cycle_id+2]->read_coherent_positions[read_set_id][j]); if(results_against_set[cycle_id+3]->read_coherent_positions[read_set_id][j]) qual_4[read_set_id] = qual_4[read_set_id] + (results_against_set[cycle_id+3]->sum_quality_per_position[read_set_id][j] / results_against_set[cycle_id+3]->read_coherent_positions[read_set_id][j]); #endif } } } // END UNTESTED CODE // on upper path int sum_up[number_of_read_sets]; // on lower path int sum_lo[number_of_read_sets]; // // considering the uncoherent as covered by 0 reads // for(read_set_id=0;read_set_idread_coherent[read_set_id]?results_against_set[cycle_id]->number_mapped_reads[read_set_id]:0; // cov_2[read_set_id]=results_against_set[cycle_id+1]->read_coherent[read_set_id]?results_against_set[cycle_id+1]->number_mapped_reads[read_set_id]:0; // sum_up[read_set_id]=cov_1[read_set_id]+cov_2[read_set_id]; // cov_3[read_set_id]=results_against_set[cycle_id+2]->read_coherent[read_set_id]?results_against_set[cycle_id+2]->number_mapped_reads[read_set_id]:0; // cov_4[read_set_id]=results_against_set[cycle_id+3]->read_coherent[read_set_id]?results_against_set[cycle_id+3]->number_mapped_reads[read_set_id]:0; // sum_lo[read_set_id]=cov_3[read_set_id]+cov_4[read_set_id]; // } // not changing the uncoherent for(read_set_id=0;read_set_idnumber_mapped_reads[read_set_id]; cov_2[read_set_id]=results_against_set[cycle_id+1]->number_mapped_reads[read_set_id]; sum_up[read_set_id]=cov_1[read_set_id]+cov_2[read_set_id]; cov_3[read_set_id]=results_against_set[cycle_id+2]->number_mapped_reads[read_set_id]; cov_4[read_set_id]=results_against_set[cycle_id+3]->number_mapped_reads[read_set_id]; sum_lo[read_set_id]=cov_3[read_set_id]+cov_4[read_set_id]; } float rank = rank_phi_N(sum_up,sum_lo,number_of_read_sets); if (!standard_fasta) { // PATH1 fprintf(out, ">%s|",results_against_set[cycle_id]->comment); for(read_set_id=0;read_set_idw); fprintf(out, ";"); // PATH2 fprintf(out, ">%s|",results_against_set[cycle_id+1]->comment); for(read_set_id=0;read_set_idw); fprintf(out, ";"); // PATH3 fprintf(out, ">%s|",results_against_set[cycle_id+2]->comment); for(read_set_id=0;read_set_idw); fprintf(out, ";"); // PATH4 fprintf(out, ">%s|",results_against_set[cycle_id+3]->comment); for(read_set_id=0;read_set_idw); fprintf(out, "\n"); } else { // PATH1 fprintf(out, ">%s|", results_against_set[cycle_id]->comment); for(read_set_id=0;read_set_idw); // PATH2 fprintf(out, ">%s|", results_against_set[cycle_id+1]->comment); for(read_set_id=0;read_set_idw); // PATH3 fprintf(out, ">%s|", results_against_set[cycle_id+2]->comment); for(read_set_id=0;read_set_idw); // PATH4 fprintf(out, ">%s|", results_against_set[cycle_id+3]->comment); for(read_set_id=0;read_set_idw); } } /** * checks if at least one read set provide read coherency for a path. */ inline int one_coherent(const p_fragment_info * results_against_set, int cycle_id, int number_of_read_sets){ int i; for(i=0;iread_coherent[i]) return 1; } return 0; } void print_results_2_paths_per_event(FILE * coherent_out, FILE * uncoherent_out, const p_fragment_info * results_against_set, const int number_of_read_sets, int nb_events_per_set, int qual){ int i; int nb_read_coherent=0; int nb_unread_coherent=0; //printf("number ofread sets = %d\n", number_of_read_sets); // // C1 C2 C3 .... // path1 (i) [0/1] [0/1] [0/1]... // path2 (i+1) [0/1] [0/1] [0/1]... // // event is kept only if each line has at least one "1" per line: // for(i=0;iread_coherent[0] && results_against_set[i+1]->read_coherent[0] && //au and vb coherent in C1 (!results_against_set[i+2]->read_coherent[0] || !results_against_set[i+3]->read_coherent[0]) && //av' or u'b uncoherent in C1 (!results_against_set[i]->read_coherent[1] || !results_against_set[i+1]->read_coherent[1]) && //au or vb uncoherent in C2 results_against_set[i+2]->read_coherent[1] && results_against_set[i+3]->read_coherent[1]) //av' and u'b coherent in C2 coherent = 1; if(results_against_set[i]->read_coherent[1] && results_against_set[i+1]->read_coherent[1] && //au and vb coherent in C2 (!results_against_set[i+2]->read_coherent[1] || !results_against_set[i+3]->read_coherent[1]) && //av' or u'b uncoherent in C2 (!results_against_set[i]->read_coherent[0] || !results_against_set[i+1]->read_coherent[0]) && //au or vb uncoherent in C1 results_against_set[i+2]->read_coherent[0] && results_against_set[i+3]->read_coherent[0]) //av' and u'b coherent in C1 coherent=1; if(coherent){ nb_read_coherent++; print_quadruplet_i(coherent_out, results_against_set, i, number_of_read_sets, qual); } else{ nb_unread_coherent++; print_quadruplet_i(uncoherent_out, results_against_set, i, number_of_read_sets, qual); } } if (!silent) printf("Among %d inversions:\n\t%d read coherent and\n\t%d not read coherent\n", nb_events_per_set, nb_read_coherent, nb_unread_coherent); } #else // !READ2INV void print_results_invs(FILE * coherent_out, FILE * uncoherent_out, const p_fragment_info * results_against_set, const int number_of_read_sets, int nb_events_per_set, int qual){ int i; int nb_read_coherent=0; int nb_unread_coherent=0; //printf("number ofread sets = %d\n", number_of_read_sets); // // C1 C2 C3 .... // path1 (i) [0/1] [0/1] [0/1]... // path2 (i+1) [0/1] [0/1] [0/1]... // path2 (i+2) [0/1] [0/1] [0/1]... // path2 (i+3) [0/1] [0/1] [0/1]... // // event is kept only if each line has at least one "1" per line: // for(i=0;iw)-kmer_size;j++){ if(results_against_set[cycle_id]->read_coherent_positions[read_set_id][j]){ #ifdef CHARQUAL avg[read_set_id] = avg[read_set_id] + results_against_set[cycle_id]->sum_quality_per_position[read_set_id][j]; #else avg[read_set_id] = avg_up[read_set_id] + (results_against_set[cycle_id]->sum_quality_per_position[read_set_id][j] / results_against_set[cycle_id]->read_coherent_positions[read_set_id][j]); #endif } } } } for(read_set_id=0;read_set_idnumber_mapped_reads[read_set_id]; } fprintf(out, ">%s|", results_against_set[cycle_id]->comment); for(read_set_id=0;read_set_idw); } void print_generic_results(FILE * coherent_out, FILE * uncoherent_out, const p_fragment_info * results_against_set, const int number_of_read_sets, int nb_events_per_set, int qual){ int i; int nb_read_coherent=0; int nb_unread_coherent=0; for(i=0;i #include #include #include #include p_couple create_couple(int a,int b){ p_couple cpl = malloc(sizeof(couple)); test_alloc(cpl); cpl->a=a; cpl->b=b; return cpl; } void free_couple (const void * v_c){ couple * c = (couple *) v_c; if(c != NULL){ free(c); } } p_charint_couple create_charint_couple(char* a,int b){ p_charint_couple cpl = malloc(sizeof(charint_couple)); test_alloc(cpl); cpl->a=a; cpl->b=b; return cpl; } void free_charint_couple (const void * v_c){ charint_couple * c = (charint_couple *) v_c; if(c != NULL){ free(c); } } p_pointers_couple create_pointers_couple(void* a, void * b){ p_pointers_couple cpl = malloc(sizeof(pointers_couple)); test_alloc(cpl); cpl->a=a; cpl->b=b; return cpl; } void free_pointers_couple (const void * v_c){ pointers_couple * c = (pointers_couple *) v_c; if(c != NULL){ free(c); } } // //p_node_couple create_node_couple(p_node t, int pos){//, int fragment_id){ // p_node_couple pnc = (p_node_couple) malloc(sizeof(node_couple)); test_alloc(pnc); // pnc->t=t; // pnc->b=pos; //// pnc->fragment_id=fragment_id; // return pnc; //} // //void free_node_couple( const void * v_nc){ // node_couple * nc = (node_couple *) v_nc; // if(nc != NULL) { // free(nc); // } //} discoSnp/kissreads/src/list.c0000644000000000000000000001107212424137006015234 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * list.c * * Created on: 16 sept. 2010 * Author: ppeterlo */ #include "list.h" int numberInList (list *l) { return l->size; } list* list_create(void){ list * l = (list *)malloc(sizeof(list)); test_alloc(l); l->size=0; l->first=NULL; return l; } void list_add(list *l, void * val) { cell * new = (cell *)malloc(sizeof(cell)); test_alloc(new); new->val = val; l->size++; new->prox = l->first; l->first=new; } /** * free a list and its generic content: free all cells, and specifically free their val using a function given as argument. */ void list_free(const void *v_list, void (*specific_free)(void *)) { list * p_list = (list *) v_list; cell *aux; cell *l = p_list->first; while (l != NULL) { aux = l; l = l->prox; specific_free(aux->val); free(aux); } free(p_list); } /** * empty a list and its generic content: free all cells, and free their val using free(). */ void list_of_generic_empty(const void * v_list) { list * p_list = (list *) v_list; cell *aux; if(!p_list) return; cell * l = p_list->first; while (l != NULL) { // printf("freeing value %d\n", *(int*)l->val); //DEB if(l->val != NULL) free(l->val); aux = l; l = l->prox; free(aux); } p_list->size=0; p_list->first=NULL; } /** * free a list and its generic content: free all cells, and free their val using free(). */ void list_of_generic_free(const void * v_list) { list_of_generic_empty(v_list); free((list *) v_list); } /* * for debugging purposes.. */ void list_print(list *l) { cell *c=l->first; while (c != NULL) { c=c->prox; } } char list_of_int_contains(list *l, int val){ cell *c=l->first; while (c != NULL) { if ((*(int*)c->val)==val) return 1; c=c->prox; } return 0; } ///////////////////////////////////////////////////////////////////////////////// ///////// For speed purpose, here is a list dedicated to int only /////////////// ///////////////////////////////////////////////////////////////////////////////// listint *listint_create(void){ listint * l = (listint *)malloc(sizeof(listint)); test_alloc(l); l->size=0; l->first=NULL; return l; } void listint_add(listint *l, int val) { cellint * new = (cellint *)malloc(sizeof(cellint)); test_alloc(new); new->val = val; l->size++; new->prox = l->first; l->first=new; } char listint_contains(listint *l, int val){ cellint *c=l->first; while (c != NULL) { if ((c->val)==val) return 1; c=c->prox; } return 0; } void listint_empty(const void *v_list){ listint * p_list = (listint *) v_list; cellint *aux; if(!p_list) return; cellint * l = p_list->first; while (l != NULL) { aux = l; l = l->prox; free(aux); } p_list->size=0; p_list->first=NULL; } void listint_free(const void * v_list) { listint_empty(v_list); free((listint *) v_list); } int numberInListint (listint *l){ return l->size; } discoSnp/kissreads/src/fragment_index.c0000644000000000000000000003335512424174356017274 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * fragment_index.c * * Created on: 16 sept. 2010 * Author: ppeterlo */ #include #include #include #include #include #include #include #include #include #include //#define DEBUG_INDEXING int line_num(FILE * f) { rewind(f); char c; int lines = 0; while((c = fgetc(f)) != EOF) if(c == '\n') lines++; if(c != '\n') lines++; rewind(f); return lines; } void index_one_seed(const char * seed, const int fragment_id, const int position_on_fragment){ hash_add_something_to_list(seeds,(char *)seed,create_couple(fragment_id,position_on_fragment)); } ////void index_one_seed_using_nodes(const char * seed, const p_node fragment_node, const int fragment_id, const int position_on_fragment){ //void index_one_seed_using_nodes(const char * seed, const p_node fragment_node, const int position_on_fragment){ // node_couple * seed_info = create_node_couple(fragment_node, position_on_fragment); // hash_add_something_to_list(seeds,(char *)seed,seed_info); //} char * strdup_upper_case(char * in){ // count number of upper case letters in "in" int count =0; int i; for(i=0;i='A' && in[i]<='Z') count++; char * temp = (char *) malloc(sizeof(char)*(count+1)); test_alloc(temp); int j=0; for(i=0;i='A' && in[i]<='Z') temp[j++]=in[i]; temp[j]='\0'; return temp; } char * strdup_first_lower(char * in){ // count number of first lower case letters in "in" int count =0; int i; for(i=0;i='a' && in[i]<='z') count++; else break; char * temp = (char *) malloc(sizeof(char)*(count+1)); test_alloc(temp); int j=0; for(i=0;i='a' && in[i]<='z') temp[j++]=in[i]; else break; temp[j]='\0'; return temp; } #include char * strdup_last_lower(char * in){ // count number of first lower case letters in "in" int count =0; int i; for(i=strlen(in)-1;i>=0;i--) if(in[i]>='a' && in[i]<='z') { count++; } else break; char * temp = (char *) malloc(sizeof(char)*(count+1)); test_alloc(temp); int j=count-1; for(i=strlen(in)-1;i>=0;i--) if(in[i]>='a' && in[i]<='z'){ temp[j--]=in[i]; } else break; temp[count]='\0'; return temp; } // read and store all fragments presents in the pointed file. // index by seeds of length k all these fragments. // each fragment is stored twice: one direct, one reverse complement. p_fragment_info * index_starters_from_input_file (const int k, int nb_events_per_set, const int nb_fragment_per_event, const char input_only_upper, const int index_stride){ char * temp_fragment = (char *) calloc (sizeof(char)*1048576,1); // fragment used for reading line by line test_alloc(temp_fragment); char * temp_fragment2 = (char *) malloc (sizeof(char)*131072); // fragment used for reading line by line test_alloc(temp_fragment2); int witness; // is a fragment was read ? kmer_type coded_seed; int i,j,z,stop; char validSeed; char * line = malloc(sizeof(char)*1048576); uint64_t total_seeds = 0 ; seeds = hash_create(100000); test_alloc(seeds); seeds_count = hash_create_binarykey(100000); // todo change to binary key (hash_t)AllocateHashTable(kmersize,1); // p_fragment_info * all_starters; // all existing starters are stored in this array. // this way any starter is accessed by its offset in this array = its id // allocate space for the main array of fragments all_starters = (p_fragment_info *) malloc(sizeof(p_fragment_info)*(nb_events_per_set*nb_fragment_per_event)); // fragment_index.h ( test_alloc(all_starters); #ifdef DEBUG_INDEXING printf("indexing %d*%d sequences, allocating memory for storing info about %d read sets\n", nb_fragment_per_event, nb_events_per_set, number_of_read_sets); #endif // each fragment has an id. each seed pobints to couples (id, position). and the fragment is then found thanks to all_fragment[id]; int fragment_id=0; do{ // if(fragment_id%1000==0) printf("\r%d fragments stored", fragment_id); if ( fragment_id+1 > nb_events_per_set*nb_fragment_per_event ) break; // we read the starters we needed to read witness=get_next_sequence_and_comments_for_starters(temp_fragment, temp_fragment2, input_only_upper,line); if(witness<1) break; // we have read all the file. // create the corresponding direct fragment all_starters[fragment_id] = (p_fragment_info) malloc(sizeof(fragment_info)); test_alloc(all_starters[fragment_id]); //#ifdef GET_ONLY_UPPER_CHARS if(input_only_upper){ all_starters[fragment_id]->left_extension = strdup_first_lower(temp_fragment); // printf("left ext = %s\n", all_starters[fragment_id]->left_extension); // DEB all_starters[fragment_id]->w = strdup_upper_case(temp_fragment); // printf("center = %s\n", all_starters[fragment_id]->w); // DEB all_starters[fragment_id]->right_extension = strdup_last_lower(temp_fragment); // printf("right ext = %s\n", all_starters[fragment_id]->right_extension); // DEB } else { //#else all_starters[fragment_id]->w = strdup(temp_fragment); // the fragment is stored // printf("center = %s\n", all_starters[fragment_id]->w); // DEB } //#endif all_starters[fragment_id]->mapped_with_current_read = (char *)malloc(sizeof(char)*number_of_read_sets);test_alloc(all_starters[fragment_id]->mapped_with_current_read); all_starters[fragment_id]->tested_pwis_with_current_read = (listint **)malloc(sizeof(listint *)*number_of_read_sets); test_alloc(all_starters[fragment_id]->tested_pwis_with_current_read); all_starters[fragment_id]->read_coherent = (char*) malloc(sizeof(char)*number_of_read_sets);test_alloc(all_starters[fragment_id]->read_coherent); all_starters[fragment_id]->number_mapped_reads = (int*) malloc(sizeof(int)*number_of_read_sets);test_alloc(all_starters[fragment_id]->number_mapped_reads); all_starters[fragment_id]->read_coherent_positions = (unsigned char**) malloc(sizeof(unsigned char*)*number_of_read_sets);test_alloc(all_starters[fragment_id]->read_coherent_positions); #ifdef CHARQUAL all_starters[fragment_id]->sum_quality_per_position = (unsigned char**) malloc(sizeof(unsigned char*)*number_of_read_sets);test_alloc(all_starters[fragment_id]->sum_quality_per_position); #else all_starters[fragment_id]->sum_quality_per_position = (int **) malloc(sizeof(int*)*number_of_read_sets); test_alloc(all_starters[fragment_id]->sum_quality_per_position); #endif all_starters[fragment_id]->comment = format_comment(temp_fragment2); for (i=0; imapped_with_current_read[i] = 0; all_starters[fragment_id]->tested_pwis_with_current_read[i] = listint_create(); all_starters[fragment_id]->read_coherent_positions[i] = (unsigned char *) malloc (strlen(all_starters[fragment_id]->w)*sizeof(unsigned char)); test_alloc(all_starters[fragment_id]->read_coherent_positions[i]); #ifdef CHARQUAL all_starters[fragment_id]->sum_quality_per_position[i] = (unsigned char *) malloc (strlen(all_starters[fragment_id]->w)*sizeof(unsigned char)); test_alloc(all_starters[fragment_id]->sum_quality_per_position[i]); #else all_starters[fragment_id]->sum_quality_per_position[i] = (int *) malloc (strlen(all_starters[fragment_id]->w)*sizeof(int)); test_alloc(all_starters[fragment_id]->sum_quality_per_position[i]); #endif for(z=0;zw); z++) all_starters[fragment_id]->read_coherent_positions[i][z]=0; for(z=0;zw); z++) all_starters[fragment_id]->read_coherent_positions[i][z]=0; for(z=0;zw); z++) all_starters[fragment_id]->sum_quality_per_position[i][z]=0; all_starters[fragment_id]->number_mapped_reads[i]=0; } #ifdef INPUT_FROM_KISSPLICE if(strstr(all_starters[fragment_id]->comment,"upper")) all_starters[fragment_id]->upperpath=1; // even numbers are upper. else all_starters[fragment_id]->upperpath=0; if(all_starters[fragment_id]->upperpath){ all_starters[fragment_id]->nb_reads_fully_in_S = (int *) malloc(sizeof(int)*number_of_read_sets); test_alloc(all_starters[fragment_id]->nb_reads_fully_in_S); all_starters[fragment_id]->nb_reads_overlapping_AS = (int *) malloc(sizeof(int)*number_of_read_sets); test_alloc(all_starters[fragment_id]->nb_reads_overlapping_AS); all_starters[fragment_id]->nb_reads_overlapping_SB = (int *) malloc(sizeof(int)*number_of_read_sets); test_alloc(all_starters[fragment_id]->nb_reads_overlapping_SB); } all_starters[fragment_id]->nb_reads_overlapping_both_AS_and_SB = (int *) malloc(sizeof(int)*number_of_read_sets); test_alloc(all_starters[fragment_id]->nb_reads_overlapping_both_AS_and_SB); for (i=0; iupperpath){ all_starters[fragment_id]->nb_reads_fully_in_S[i] = 0; all_starters[fragment_id]->nb_reads_overlapping_AS[i] = 0; all_starters[fragment_id]->nb_reads_overlapping_SB[i] = 0; } all_starters[fragment_id]->nb_reads_overlapping_both_AS_and_SB[i] = 0; } #endif #ifdef DEBUG_INDEXING printf("counting in %s\n", all_starters[fragment_id]->w); #endif // read all the seeds present on the fragment stop=strlen(all_starters[fragment_id]->w)-k+1; // char validSeed; for (i=0;iw[j+i])){ // if i+j character is not valid // i+=j; // don't test the next j+1 next positions (+1 will come from the 'for' loop) // validSeed=0; // } // if(validSeed){ coded_seed=codeSeed(all_starters[fragment_id]->w+i); // init the seed (as seeds are not consecutives hash_incr_kmer_count(seeds_count,&coded_seed); total_seeds++; // } } fragment_id++; }while (1); #ifdef DEBUG_INDEXING printf("%d seeds\n", total_seeds); #endif // printf("\r%d fragments stored\n", fragment_id); seed_table = calloc(total_seeds,sizeof(couple)); iterate_and_fill_offsets(seeds_count); ///second loop over fragments : create the index fragment_id=0; do{ if ( fragment_id+1 > nb_events_per_set*nb_fragment_per_event ) break; // we read the starters we needed to read #ifdef DEBUG_INDEXING printf("indexing in %s\n", all_starters[fragment_id]->w); #endif // read all the seeds present on the fragment stop=strlen(all_starters[fragment_id]->w)-k+1; // char validSeed=1; for (i=0;iw[j+i])){ // if i+j character is not valid // validSeed=0; // i+=j; // don't test the next j+1 next positions (+1 will come from the 'for' loop) // continue; // } // if(validSeed){ coded_seed=codeSeed(all_starters[fragment_id]->w+i); // init the seed hash_fill_kmer_index(seeds_count,&coded_seed,seed_table, fragment_id, i); // } } fragment_id++; }while (1); free(temp_fragment); free(line); return all_starters; } void free_seeds_index (){ hash_delete(seeds, list_of_generic_free); } discoSnp/kissreads/src/coherent_algorithm.c0000644000000000000000000001244412410743430020141 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * coherent_algorithm.c * * Created on: 16 sept. 2010 * Author: pierre peterlongo */ #include #include #include #include /** * | pwi (may be negative) * -------------- fragment * ************* read * * Tests if the overlapping part between read and fragment do not have more than subst_allowed substitions * returns 1 if true between read and fragment, 0 else */ char read_coherent_generic(const int pwi, const char * fragment, const char * read, const int subst_allowed){ // printf("read coherent, subst_allowed = %d\n", subst_allowed); int substitution_seen=0; // number of seen substitutions for now int pos_on_read, pos_on_fragment; // where to start /* * | pwi (negative) * -------------- fragment * ************* read * | we start here */ if(pwi<0) { pos_on_fragment=0; pos_on_read=-pwi; } /* * | pwi (positive) * -------------- fragment * ************* read * | we start here */ else{ pos_on_fragment=pwi; pos_on_read=0; } // walk the read and the fragment together, detecting substitutions. // stop if the number of substitution is too high while(fragment[pos_on_fragment]!='\0' && read[pos_on_read]!='\0'){ //if(fragment[pos_on_fragment]!=read[pos_on_read]) && fragment[pos_on_fragment]!='*') {// one subsitution if(fragment[pos_on_fragment]!=read[pos_on_read] && fragment[pos_on_fragment]!='*' && fragment[pos_on_fragment]!='?' && fragment[pos_on_fragment]!='N'){ // one subsitution substitution_seen++; if(substitution_seen>subst_allowed) break; // too much subsitutions } pos_on_fragment++; pos_on_read++; } // printf("%d subst seen\n", substitution_seen); if(substitution_seen<=subst_allowed) return 1; return 0; } /** * | pwi (may be negative) * -------------- fragment * ************* read * * Tests if the overlapping part between read and fragment do not have more than subst_allowed substitions * In case of SNPs, we need to avoid any substitution on the central fragment position (the one containing the SNP) * Thus in this function, we return 0 if any substitution occurs on this central position, whatever the number of substitution_seen * returns 1 if true between read and fragment, 0 else */ char read_coherent_SNP(const int pwi, const char * fragment, const char * read, const int subst_allowed){ int substitution_seen=0; // number of seen substitutions for now int pos_on_read, pos_on_fragment; // where to start /* * | pwi (negative) * -------------- fragment * ************* read * | we start here */ if(pwi<0) { pos_on_fragment=0; pos_on_read=-pwi; } /* * | pwi (positive) * -------------- fragment * ************* read * | we start here */ else{ pos_on_fragment=pwi; pos_on_read=0; } const int snp_pos = strlen(fragment)/2; // walk the read and the fragment together, detecting substitutions. // stop if the number of substitution is too high while(fragment[pos_on_fragment]!='\0' && read[pos_on_read]!='\0'){ if(fragment[pos_on_fragment]!=read[pos_on_read] && fragment[pos_on_fragment]!='*' && fragment[pos_on_fragment]!='?' && fragment[pos_on_fragment]!='N'){ // one subsitution substitution_seen++; if(substitution_seen>subst_allowed) return 0; // too much subsitutions if(pos_on_fragment==snp_pos) return 0; // substition should not be on the snp } pos_on_fragment++; pos_on_read++; } return 1; } discoSnp/kissreads/src/extension_algorithm.c0000644000000000000000000005443312424174356020364 0ustar rootroot/** * Copyright INRIA , contributors Peterlongo * pierre.peterlongo@inria.fr * * * This software is a computer program whose purpose is to detect the * presence of a sequence in a set of NGS reads, and to compute its average quality and coverage * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ /* * extension_algorithm.c * * Created on: 16 sept. 2010 * Author: ppeterlo */ #include #include #include #include #include #include #include #include #include #include #include #include //#define DEBUG_MAPPING //#define DEBUG_QUALITY #define min(a, b) ((a) < (b) ? (a) : (b)) int number_of_reads; // //// checks if, for a fragment, a tuple read/position mapped already (return 1) or none (return 0) //int exists_tuple_read_position(const hash_t map, const char * starter, const int pos){ // list * read_coherent_positions; //for one couple (read/fragment) : list of coherent mapped positions (usually, one position) // if(hash_entry_by_key(map, starter, (void **) (&read_coherent_positions)) !=0){ // cell *c = ((list *)read_coherent_positions)->first; // while(c != NULL){ // if((*(int *) (c->val))== pos){ // return 1;} // c = c->prox; // } // } // return 0; //} void print_mapping(const int pos_on_fragment, const char * fragment, const char *read){ int i; printf("pos: %d\n", pos_on_fragment); for(i=0;i<60;i++) printf(" "); printf("%s\n", fragment); for(i=0;i<60+pos_on_fragment;i++) printf(" "); printf("%s\n", read); } void feed_coherent_positions(p_fragment_info the_starter, const int start, const int length_read, const int qual, char *quality, int start_on_read, int read_file){ int i, start_on_starter, stop_on_starter; if(start<0) start_on_starter=0; else start_on_starter=start; if(start+length_readw)) stop_on_starter=start+length_read; else stop_on_starter=strlen(the_starter->w); // FEED THE STARTING POSITIONS: // ---------------[]------------************************** // before fragment | starter // size_before_reads_starting | strlen(starter) // // starter[i] corresponds to the_starter->reads_starting[i+size_before_reads_starting] // TOO HEAVY, //the_starter->reads_starting[start+size_before_reads_starting]++; // REPLACED BY: the_starter->number_mapped_reads[read_file]++; #ifdef INPUT_FROM_KISSPLICE if (the_starter->upperpath){ // ************************* // alice 2/10/13 : new kissplice output, 1 nt of context added // <-k--><----?----><-k-> // A S B // overlap on junctions : need one more char overlap_AS=0; char overlap_SB=0; if(start_on_starter<=size_seeds-min_overlap && stop_on_starter>=size_seeds+min_overlap) overlap_AS=1; const int pos_SB = strlen(the_starter->w)-(size_seeds); if(start_on_starter<=pos_SB-min_overlap && stop_on_starter>=pos_SB+min_overlap) overlap_SB=1; if(overlap_AS) the_starter->nb_reads_overlapping_AS[read_file]++; if(overlap_SB) the_starter->nb_reads_overlapping_SB[read_file]++; if(overlap_AS && overlap_SB) the_starter->nb_reads_overlapping_both_AS_and_SB[read_file]++; if(start_on_starter>size_seeds-min_overlap && stop_on_starternb_reads_fully_in_S[read_file]++; } else{// lower path if(stop_on_starter-start_on_starter>size_seeds+min_overlap) the_starter->nb_reads_overlapping_both_AS_and_SB[read_file]++; } #endif #ifdef CHARQUAL if ( qual ) { //GR 06/11/2012 : cumulative moving average, allow quals to be stored in uchar //but average is computed only over 255 first read mappeds, because read_coherent_positions also changed to uchar unsigned char nbreads; float new_val; for(i=start_on_starter;iread_coherent_positions[read_file][i]; if (nbreads == 0) //first read mapped the_starter->sum_quality_per_position[read_file][i] = quality[start_on_read + i - start_on_starter]; else //at least 1 read mapped already { new_val = ((float)the_starter->sum_quality_per_position[read_file][i]) *(nbreads-1) +quality[start_on_read + i - start_on_starter] ; new_val = new_val / nbreads; the_starter->sum_quality_per_position[read_file][i] = (unsigned char) new_val ; } } } #else if ( qual ) for(i=start_on_starter;iread_coherent_positions[read_file][i] == 0) //first read mapped the_starter->sum_quality_per_position[read_file][i] = quality[start_on_read + i - start_on_starter]; else //at least 1 read mapped already the_starter->sum_quality_per_position[read_file][i] += (int) quality[start_on_read + i - start_on_starter]; #endif #ifdef KMER_SPANNING // the position i is contained into a kmer fully contained into only 1 mapped read, return 1 // for doing this we stored on each position of the fragment the number of k-mers starting at this position that fully belong to a read that was mapped // -------------------------------------------------------------- starter // ************************ // <-----k-----> // 00000000001111111111110000000000000000000000000000000000000000 the_starter->read_coherent_positions[read_file] if(start+length_read-minimal_read_overlapw)) stop_on_starter=start+length_read-minimal_read_overlap; else stop_on_starter=strlen(the_starter->w); #endif for(i=start_on_starter;iread_coherent_positions[read_file][i]); } // For each position in the starter: // find the kmer supported by the smallest number of reads, e.g.: // i // ------------------------------X------------------------------- starter // a ************************ // b ************************** // c ******************* // d ************************* // <-----k-----> : 2 reads (a and b) // <-----k-----> : 3 reads (a,b and b) // <-----k-----> : 2 reads (b and c) // <-----k-----> : 1 reads (c) // <-----k-----> : 2 reads (c and d) // ... // the position i is contained into a kmer fully contained into only 1 mapped read, return 1 // for doing this we stored on each position of the fragment the number of k-mers starting at this position that fully belong to a read that was mapped. int minimal_kmer_coverage(p_fragment_info the_starter, int read_file){ int i, val_min=INT_MAX; const int stopi=strlen(the_starter->w); for(i=0;iread_coherent_positions[read_file][i]); } return val_min; } void set_read_coherent(p_fragment_info the_starter, const int min_coverage, int read_file){ int i; // V1: the whole fragment has to be k_read coherent or V2 where the last k positions have no influence on the coherency of the fragment. // V2 is appropriate for the cases where the fragment is the end of a sequence (transcript, chromosome) and thus, no read are "longer" than the sequence: // ----------------- fragment // °°°°°°°°°°°° read // °°°°°°°°°°°° read // °°°°°°°°°°°° read // °°°°°°°°°°°° read #ifdef KMER_SPANNING const int stop=strlen(the_starter->w)-minimal_read_overlap; #else const int stop=strlen(the_starter->w); #endif for(i=0;iread_coherent_positions[read_file][i]read_coherent[read_file]=0; return;} the_starter->read_coherent[read_file]=1; } /////////////////////////////////////////////////////////////////////////////////////////////// ///// we use a boolean vector to know if a read was alread mapped on a fragment // OCTOBER 2014: THIS SOLUTION IS NOT GOOD: some read maps several position of a fragment // (more and more true with long reads) // The new way of checking if a triplet (fragment/read/pwi) is already tested uses the fragment_info structure. // Each fragment info houses a listint where tested pwi values are stored for a read. // Each of these lists is emptied after each read mapping. /////////////////////////////////////////////////////////////////////////////////////////////// //char mask [8]; // //char * new_boleanVector (long size){ // char* boolean_vector = (char*)malloc(size/8+1); // test_alloc(boolean_vector); // memset(boolean_vector, 0, size/8+1); // mask[0]=1; //00000001 // mask[1]=2; //00000010 // mask[2]=4; //00000100 // mask[3]=8; //00001000 // mask[4]=16; //00010000 // mask[5]=32; //00100000 // mask[6]=64; //01000000 // mask[7]=128;//10000000 // return boolean_vector; //} // // //char is_boolean_vector_visited (const char * boolean_vector, long i){ // return (boolean_vector[i/8]&mask[i%8])==0?0:1; //} // //void set_boolean_vector_visited(char * boolean_vector, long i){ // boolean_vector[i/8]|=mask[i%8]; //} // //void free_boolean_vector(char * boolean_vector){ // free(boolean_vector); //} // //void reinit_boolean_vector(char * boolean_vector, long size){ // memset(boolean_vector, 0, size/8+1); //} /** * Performs the first extension of the algorithm: * For each starter: * - verify which reads maps on it with at most subst_allowed substitutions * - for fragments that are fully covered by reads (each position is covered at least once): * 1) add their id in a list (that is returned by the function) * 2) detect the extending reads (at least "min_extension_coverage_depth" reads) that enable to extend right the starter * 3) store this extending reads in the structure of the fragments (fragment_info) * returns the average read length */ float read_coherence (gzFile reads_file, char * reads_file_name, const int k, const int min_coverage, p_fragment_info * all_starters, const int number_starters, int read_file, int qual, int nb_events_per_set, int nb_fragment_per_event, FILE * sam_out, int subst_allowed, const char no_subsutitution_on_central_position, const int minimal_read_overlap ){ ////////////////////////////////////////////////////////////////////////// /////////////// read all reads - storing those coherent with reads /////// ////////////////////////////////////////////////////////////////////////// char * starter; uint64_t offset_seed; uint64_t nb_seeds; // working variables int read_len, i, ii, j, starter_id, pwi, stop, read_coherence; long int read_number=0; // map of starter -> position (for each read and direction, stores the starter and position already tested.) // char * boolean_vector = new_boleanVector(number_starters); // book space for the read that going to be read. char * line = (char *)malloc(sizeof(char)*1048576); // 1048576 char * read = (char *)malloc(sizeof(char)*16384); // char * quality = (char *)malloc(sizeof(char)*16384);// test_alloc(read); test_alloc(quality); listint * tested_starters = listint_create(); // given a read, stores all starter ids on which a seed was seen. Enables to free quickly list of tested pwis of each tested starters. char is_fastq=0; if ( qual || strstr(reads_file_name,"fastq") || strstr(reads_file_name,"fq") || strstr(reads_file_name,"txt") ) is_fastq=1; // read all the reads do{ if(!silent) if((++read_number)%(100000) == 0) printf("\r %ld reads treated", read_number); // print progress if ( is_fastq ) read_len = get_next_sequence_for_fastq(reads_file, read, quality,line); else read_len = get_next_fasta_sequence(reads_file, read,line); if(read_len<0) break; // we have read all the file. const int minimal_pwi = minimal_read_overlap - read_len; // The read must overlap the fragment with at least minimal_read_overlap positions. // here is the first position on which the read may map : // ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; starter // ********** read (10) // <-----> minimal_read_overlap (7) // <-> -pwi (-3) // -pwi+minimal_read_overlap <= |read| // -pwi <= |read|-minimal_read_overlap // pwi >= minimal_read_overlap-|read| // pwi >= 7-10 = -3 // minimal_pwi = minimal_read_overlap-|read| stop = read_len-k+1; #ifdef DEBUG_MAPPING printf("new read = %s-\n", read); #endif // read all seeds present on the read: int direction; kmer_type coded_seed; char toinit=1; // char validSeed; for(direction=0;direction<2;direction++){ // try the two possible directions of the read toinit=1; // we have to init a new seed for (i=0;ia = %d\n", value->a); //DEB starter = all_starters[value->a]->w; if(all_starters[value->a]->mapped_with_current_read[read_file]==1) { // printf("already mapped %d with this read\n", value->a); //DEB continue; // a mach was already found with this starter, we consider only one match per couple (starter/read) } // sprintf(starter_key, "%d", value->a); pwi = value->b-i; // starting position of the read on the starter. // printf("a=%d pwi = %d\n", value->a,pwi); // DEB if (listint_contains(all_starters[value->a]->tested_pwis_with_current_read[read_file],pwi)) { // printf("already tested %d position %d with this read\n", value->a, pwi); //DEB continue; // this reads was already (unsuccessfuly) tested with this starter at this position. No need to try it again. } if (numberInListint (all_starters[value->a]->tested_pwis_with_current_read[read_file])==0){ // this is the first time we meet this starter with this read, we add it in the list of met starters (in order to free the pwis lists of each encounted starters for this read) listint_add(tested_starters,value->a); // printf("adding %d in the list of tested starters with this read \n", *p_valuea); //DEB } listint_add(all_starters[value->a]->tested_pwis_with_current_read[read_file],pwi); // We store the fact that this read was already tested at this position on this starter. // overview general situation: // ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; starter // <---------> b // [--------] seed // ****************************** read // <----> i // <---> pwi if (pwi maximal_pwi) { continue; // this read to not overlap enough with the starter. } // ;;;;;;;;;;; starter (11) // ****************************** read // <----> minimal_read_overlap (6) // <---> pwi (5) // |starter| <= pwi+minimal_read_overlap read_coherence=0; if(no_subsutitution_on_central_position) read_coherence = read_coherent_SNP(pwi, starter, read, subst_allowed); else read_coherence = read_coherent_generic(pwi, starter, read, subst_allowed); if(read_coherence == 1){ // tuple read starter position is read coherent all_starters[value->a]->mapped_with_current_read[read_file]=1; #ifdef DEBUG_MAPPING printf("SUCCESS %d %d \n", pwi, value->a); print_mapping(pwi,all_starters[value->a]->w ,read); //DEB #endif feed_coherent_positions(all_starters[value->a], pwi, (int)strlen(read), qual, quality, i, read_file); if( sam_out ) fprintf(sam_out,"%d %d %s\t%s\tC%d\t%d\n", value->a, value->b, all_starters[value->a]->comment, read, read_file+1, pwi); #ifdef DEBUG_QUALITY if ( qual ) { int l; printf("\nstarter %d pwi=%d\n",value->a,pwi); for(l=0;l<70;l++)printf(" "); printf("%s\n",all_starters[value->a]->w); for(l=0;l<70+pwi;l++)printf(" "); printf("%s\n", read); for(l=0;l<70+pwi;l++)printf(" "); printf("%s\n", quality); } #endif } // end tuple read starter position is read coherent // hash_add_int_to_list(already_tested_direct, starter_key, pwi); //c=c->prox; } } // end all infos for the current seed } // end all seeds of the read revcomp(read,read_len); if ( qual ) rev (quality,read_len); // free the lists of tested positions: cellint * tested_starter=tested_starters->first; while (tested_starter != NULL) { listint_empty(all_starters[tested_starter->val]->tested_pwis_with_current_read[read_file]); all_starters[tested_starter->val]->mapped_with_current_read[read_file] = 0; // printf("freeing starter %d\n", *(int *)tested_starter->val); //DEB tested_starter=tested_starter->prox; } listint_empty(tested_starters); } // end both directions }while(1); // end all reads of the file if(!silent) printf("\r %ld reads treated\n", read_number); // print progress /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////// for each starter: check those fully coherent and store left and right reads covering them /////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// for (starter_id=0;starter_id < nb_events_per_set*nb_fragment_per_event;starter_id++){ if(!silent && (starter_id%(1+(nb_events_per_set/50)) == 0)) printf("."); // print progress set_read_coherent(all_starters[starter_id], min_coverage, read_file); } // end all fragments free(read); free(quality); free(line); listint_free(tested_starters); return 0; } discoSnp/kissreads/Makefile0000644000000000000000000000522412424174356015001 0ustar rootroot###################################################################################################### # kissreads # # January 2012 # ###################################################################################################### # Developper: # # Pierre PETERLONGO pierre.peterlongo@inria.fr # ###################################################################################################### # POSSIBILITIES: # * make: compiled for generic usage. By default: kmer_spanning (a position is considered as covered if the kmer starting at this position is fully covered by a read) # * make MYFLAGS=-DREAD2INV : output only motifs where au-vb is specific to one datasets and av'-u'b is specific to the other # * make MYFLAGS=-DCLASSICAL_SPANNING : compiled without kmer (a position is considered as covered as soon as a read maps this position) # * make MYFLAGS=-DINPUT_FROM_KISSPLICE : compiled for dealing with kissplice output and to count separately junctions and central portions # Note that this is compatible: make CFLAGS="-DCLASSICAL_SPANNING -DINPUT_FROM_KISSPLICE" is possible ALL = kissreads CC =gcc # optimized flags #CFLAGS=-Wall -O3 -lz -fopenmp -DOMP #openmp is incompatiblre with clang #@!§ CFLAGS= -O3 -lz -fopenmp -DOMP #openmp is incompatiblre with clang #@! CFLAGS+=$(MYFLAGS) #LDFLAGS+=-Wall -lm -O3 -lz -DOMP -fopenmp#-fopenmp LDFLAGS+= -lm -O3 -lz -DOMP -fopenmp#-fopenmp ## debug flags #CFLAGS +=-Wall -g -lz -fopenmp #LDFLAGS +=-Wall -lm -g -lz -fopenmp SRCDIR = ./src/ INCLDIR = ./include/ IFLAGS = -I$(INCLDIR) SRC = $(SRCDIR)coherent_algorithm.c $(SRCDIR)commons.c $(SRCDIR)couple.c $(SRCDIR)extension_algorithm.c $(SRCDIR)fragment_index.c $(SRCDIR)kissReads.c $(SRCDIR)list.c $(SRCDIR)outputs.c $(SRCDIR)interface_libchash.c $(SRCDIR)libchash.c OBJ = $(SRC:.c=.o) all: $(ALL) @echo "#################" @echo "# Compilation OK#" @echo "#################" kissreads: $(OBJ) $(CC) -o $@ $^ $(LDFLAGS) kissReads.o: $(INCLDIR)coherence_algorithm.h $(INCLDIR)couple.h $(INCLDIR)extension_algorithm.h $(INCLDIR)fragment_info.h $(INCLDIR)libchash.h $(INCLDIR)outputs.h $(INCLDIR)commons.h $(INCLDIR)extending_fragment.h $(INCLDIR)fragment_index.h $(INCLDIR)hash.h $(INCLDIR)list.h %.o: %.c $(CC) -o $@ -c $< $(CFLAGS) $(IFLAGS) .PHONY: clean mrproper clean: rm -rf $(SRCDIR)*.o $(ALL) mrproper: clean rm -rf $(ALL) discoSnp/LICENSE0000644000000000000000000005115312227036606012354 0ustar rootroot CeCILL FREE SOFTWARE LICENSE AGREEMENT Notice This Agreement is a Free Software license agreement that is the result of discussions between its authors in order to ensure compliance with the two main principles guiding its drafting: * firstly, compliance with the principles governing the distribution of Free Software: access to source code, broad rights granted to users, * secondly, the election of a governing law, French law, with which it is conformant, both as regards the law of torts and intellectual property law, and the protection that it offers to both authors and holders of the economic rights over software. The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) license are: Commissariat a l'Energie Atomique - CEA, a public scientific, technical and industrial research establishment, having its principal place of business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. Centre National de la Recherche Scientifique - CNRS, a public scientific and technological establishment, having its principal place of business at 3 rue Michel-Ange, 75794 Paris cedex 16, France. Institut National de Recherche en Informatique et en Automatique - INRIA, a public scientific and technological establishment, having its principal place of business at Domaine de Voluceau, Rocquencourt, BP 105, 78153 Le Chesnay cedex, France. Preamble The purpose of this Free Software license agreement is to grant users the right to modify and redistribute the software governed by this license within the framework of an open source distribution model. The exercising of these rights is conditional upon certain obligations for users so as to preserve this status for all subsequent redistributions. In consideration of access to the source code and the rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the successive licensors only have limited liability. In this respect, the risks associated with loading, using, modifying and/or developing or reproducing the software by the user are brought to the user's attention, given its Free Software status, which may make it complicated to use, with the result that its use is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the suitability of the software as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions of security. This Agreement may be freely reproduced and published, provided it is not altered, and that no provisions are either added or removed herefrom. This Agreement may apply to any or all software for which the holder of the economic rights decides to submit the use thereof to its provisions. Article 1 - DEFINITIONS For the purpose of this Agreement, when the following expressions commence with a capital letter, they shall have the following meaning: Agreement: means this license agreement, and its possible subsequent versions and annexes. Software: means the software in its Object Code and/or Source Code form and, where applicable, its documentation, "as is" when the Licensee accepts the Agreement. Initial Software: means the Software in its Source Code and possibly its Object Code form and, where applicable, its documentation, "as is" when it is first distributed under the terms and conditions of the Agreement. Modified Software: means the Software modified by at least one Contribution. Source Code: means all the Software's instructions and program lines to which access is required so as to modify the Software. Object Code: means the binary files originating from the compilation of the Source Code. Holder: means the holder(s) of the economic rights over the Initial Software. Licensee: means the Software user(s) having accepted the Agreement. Contributor: means a Licensee having made at least one Contribution. Licensor: means the Holder, or any other individual or legal entity, who distributes the Software under the Agreement. Contribution: means any or all modifications, corrections, translations, adaptations and/or new functions integrated into the Software by any or all Contributors, as well as any or all Internal Modules. Module: means a set of sources files including their documentation that enables supplementary functions or services in addition to those offered by the Software. External Module: means any or all Modules, not derived from the Software, so that this Module and the Software run in separate address spaces, with one calling the other when they are run. Internal Module: means any or all Module, connected to the Software so that they both execute in the same address space. GNU GPL: means the GNU General Public License version 2 or any subsequent version, as published by the Free Software Foundation Inc. Parties: mean both the Licensee and the Licensor. These expressions may be used both in singular and plural form. Article 2 - PURPOSE The purpose of the Agreement is the grant by the Licensor to the Licensee of a non-exclusive, transferable and worldwide license for the Software as set forth in Article 5 hereinafter for the whole term of the protection granted by the rights over said Software. Article 3 - ACCEPTANCE 3.1 The Licensee shall be deemed as having accepted the terms and conditions of this Agreement upon the occurrence of the first of the following events: * (i) loading the Software by any or all means, notably, by downloading from a remote server, or by loading from a physical medium; * (ii) the first time the Licensee exercises any of the rights granted hereunder. 3.2 One copy of the Agreement, containing a notice relating to the characteristics of the Software, to the limited warranty, and to the fact that its use is restricted to experienced users has been provided to the Licensee prior to its acceptance as set forth in Article 3.1 hereinabove, and the Licensee hereby acknowledges that it has read and understood it. Article 4 - EFFECTIVE DATE AND TERM 4.1 EFFECTIVE DATE The Agreement shall become effective on the date when it is accepted by the Licensee as set forth in Article 3.1. 4.2 TERM The Agreement shall remain in force for the entire legal term of protection of the economic rights over the Software. Article 5 - SCOPE OF RIGHTS GRANTED The Licensor hereby grants to the Licensee, who accepts, the following rights over the Software for any or all use, and for the term of the Agreement, on the basis of the terms and conditions set forth hereinafter. Besides, if the Licensor owns or comes to own one or more patents protecting all or part of the functions of the Software or of its components, the Licensor undertakes not to enforce the rights granted by these patents against successive Licensees using, exploiting or modifying the Software. If these patents are transferred, the Licensor undertakes to have the transferees subscribe to the obligations set forth in this paragraph. 5.1 RIGHT OF USE The Licensee is authorized to use the Software, without any limitation as to its fields of application, with it being hereinafter specified that this comprises: 1. permanent or temporary reproduction of all or part of the Software by any or all means and in any or all form. 2. loading, displaying, running, or storing the Software on any or all medium. 3. entitlement to observe, study or test its operation so as to determine the ideas and principles behind any or all constituent elements of said Software. This shall apply when the Licensee carries out any or all loading, displaying, running, transmission or storage operation as regards the Software, that it is entitled to carry out hereunder. 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS The right to make Contributions includes the right to translate, adapt, arrange, or make any or all modifications to the Software, and the right to reproduce the resulting software. The Licensee is authorized to make any or all Contributions to the Software provided that it includes an explicit notice that it is the author of said Contribution and indicates the date of the creation thereof. 5.3 RIGHT OF DISTRIBUTION In particular, the right of distribution includes the right to publish, transmit and communicate the Software to the general public on any or all medium, and by any or all means, and the right to market, either in consideration of a fee, or free of charge, one or more copies of the Software by any means. The Licensee is further authorized to distribute copies of the modified or unmodified Software to third parties according to the terms and conditions set forth hereinafter. 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION The Licensee is authorized to distribute true copies of the Software in Source Code or Object Code form, provided that said distribution complies with all the provisions of the Agreement and is accompanied by: 1. a copy of the Agreement, 2. a notice relating to the limitation of both the Licensor's warranty and liability as set forth in Articles 8 and 9, and that, in the event that only the Object Code of the Software is redistributed, the Licensee allows future Licensees unhindered access to the full Source Code of the Software by indicating how to access it, it being understood that the additional cost of acquiring the Source Code shall not exceed the cost of transferring the data. 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE When the Licensee makes a Contribution to the Software, the terms and conditions for the distribution of the resulting Modified Software become subject to all the provisions of this Agreement. The Licensee is authorized to distribute the Modified Software, in source code or object code form, provided that said distribution complies with all the provisions of the Agreement and is accompanied by: 1. a copy of the Agreement, 2. a notice relating to the limitation of both the Licensor's warranty and liability as set forth in Articles 8 and 9, and that, in the event that only the object code of the Modified Software is redistributed, the Licensee allows future Licensees unhindered access to the full source code of the Modified Software by indicating how to access it, it being understood that the additional cost of acquiring the source code shall not exceed the cost of transferring the data. 5.3.3 DISTRIBUTION OF EXTERNAL MODULES When the Licensee has developed an External Module, the terms and conditions of this Agreement do not apply to said External Module, that may be distributed under a separate license agreement. 5.3.4 COMPATIBILITY WITH THE GNU GPL The Licensee can include a code that is subject to the provisions of one of the versions of the GNU GPL in the Modified or unmodified Software, and distribute that entire code under the terms of the same version of the GNU GPL. The Licensee can include the Modified or unmodified Software in a code that is subject to the provisions of one of the versions of the GNU GPL, and distribute that entire code under the terms of the same version of the GNU GPL. Article 6 - INTELLECTUAL PROPERTY 6.1 OVER THE INITIAL SOFTWARE The Holder owns the economic rights over the Initial Software. Any or all use of the Initial Software is subject to compliance with the terms and conditions under which the Holder has elected to distribute its work and no one shall be entitled to modify the terms and conditions for the distribution of said Initial Software. The Holder undertakes that the Initial Software will remain ruled at least by this Agreement, for the duration set forth in Article 4.2. 6.2 OVER THE CONTRIBUTIONS The Licensee who develops a Contribution is the owner of the intellectual property rights over this Contribution as defined by applicable law. 6.3 OVER THE EXTERNAL MODULES The Licensee who develops an External Module is the owner of the intellectual property rights over this External Module as defined by applicable law and is free to choose the type of agreement that shall govern its distribution. 6.4 JOINT PROVISIONS The Licensee expressly undertakes: 1. not to remove, or modify, in any manner, the intellectual property notices attached to the Software; 2. to reproduce said notices, in an identical manner, in the copies of the Software modified or not. The Licensee undertakes not to directly or indirectly infringe the intellectual property rights of the Holder and/or Contributors on the Software and to take, where applicable, vis-à-vis its staff, any and all measures required to ensure respect of said intellectual property rights of the Holder and/or Contributors. Article 7 - RELATED SERVICES 7.1 Under no circumstances shall the Agreement oblige the Licensor to provide technical assistance or maintenance services for the Software. However, the Licensor is entitled to offer this type of services. The terms and conditions of such technical assistance, and/or such maintenance, shall be set forth in a separate instrument. Only the Licensor offering said maintenance and/or technical assistance services shall incur liability therefor. 7.2 Similarly, any Licensor is entitled to offer to its licensees, under its sole responsibility, a warranty, that shall only be binding upon itself, for the redistribution of the Software and/or the Modified Software, under terms and conditions that it is free to decide. Said warranty, and the financial terms and conditions of its application, shall be subject of a separate instrument executed between the Licensor and the Licensee. Article 8 - LIABILITY 8.1 Subject to the provisions of Article 8.2, the Licensee shall be entitled to claim compensation for any direct loss it may have suffered from the Software as a result of a fault on the part of the relevant Licensor, subject to providing evidence thereof. 8.2 The Licensor's liability is limited to the commitments made under this Agreement and shall not be incurred as a result of in particular: (i) loss due the Licensee's total or partial failure to fulfill its obligations, (ii) direct or consequential loss that is suffered by the Licensee due to the use or performance of the Software, and (iii) more generally, any consequential loss. In particular the Parties expressly agree that any or all pecuniary or business loss (i.e. loss of data, loss of profits, operating loss, loss of customers or orders, opportunity cost, any disturbance to business activities) or any or all legal proceedings instituted against the Licensee by a third party, shall constitute consequential loss and shall not provide entitlement to any or all compensation from the Licensor. Article 9 - WARRANTY 9.1 The Licensee acknowledges that the scientific and technical state-of-the-art when the Software was distributed did not enable all possible uses to be tested and verified, nor for the presence of possible defects to be detected. In this respect, the Licensee's attention has been drawn to the risks associated with loading, using, modifying and/or developing and reproducing the Software which are reserved for experienced users. The Licensee shall be responsible for verifying, by any or all means, the suitability of the product for its requirements, its good working order, and for ensuring that it shall not cause damage to either persons or properties. 9.2 The Licensor hereby represents, in good faith, that it is entitled to grant all the rights over the Software (including in particular the rights set forth in Article 5). 9.3 The Licensee acknowledges that the Software is supplied "as is" by the Licensor without any other express or tacit warranty, other than that provided for in Article 9.2 and, in particular, without any warranty as to its commercial value, its secured, safe, innovative or relevant nature. Specifically, the Licensor does not warrant that the Software is free from any error, that it will operate without interruption, that it will be compatible with the Licensee's own equipment and software configuration, nor that it will meet the Licensee's requirements. 9.4 The Licensor does not either expressly or tacitly warrant that the Software does not infringe any third party intellectual property right relating to a patent, software or any other property right. Therefore, the Licensor disclaims any and all liability towards the Licensee arising out of any or all proceedings for infringement that may be instituted in respect of the use, modification and redistribution of the Software. Nevertheless, should such proceedings be instituted against the Licensee, the Licensor shall provide it with technical and legal assistance for its defense. Such technical and legal assistance shall be decided on a case-by-case basis between the relevant Licensor and the Licensee pursuant to a memorandum of understanding. The Licensor disclaims any and all liability as regards the Licensee's use of the name of the Software. No warranty is given as regards the existence of prior rights over the name of the Software or as regards the existence of a trademark. Article 10 - TERMINATION 10.1 In the event of a breach by the Licensee of its obligations hereunder, the Licensor may automatically terminate this Agreement thirty (30) days after notice has been sent to the Licensee and has remained ineffective. 10.2 A Licensee whose Agreement is terminated shall no longer be authorized to use, modify or distribute the Software. However, any licenses that it may have granted prior to termination of the Agreement shall remain valid subject to their having been granted in compliance with the terms and conditions hereof. Article 11 - MISCELLANEOUS 11.1 EXCUSABLE EVENTS Neither Party shall be liable for any or all delay, or failure to perform the Agreement, that may be attributable to an event of force majeure, an act of God or an outside cause, such as defective functioning or interruptions of the electricity or telecommunications networks, network paralysis following a virus attack, intervention by government authorities, natural disasters, water damage, earthquakes, fire, explosions, strikes and labor unrest, war, etc. 11.2 Any failure by either Party, on one or more occasions, to invoke one or more of the provisions hereof, shall under no circumstances be interpreted as being a waiver by the interested Party of its right to invoke said provision(s) subsequently. 11.3 The Agreement cancels and replaces any or all previous agreements, whether written or oral, between the Parties and having the same purpose, and constitutes the entirety of the agreement between said Parties concerning said purpose. No supplement or modification to the terms and conditions hereof shall be effective as between the Parties unless it is made in writing and signed by their duly authorized representatives. 11.4 In the event that one or more of the provisions hereof were to conflict with a current or future applicable act or legislative text, said act or legislative text shall prevail, and the Parties shall make the necessary amendments so as to comply with said act or legislative text. All other provisions shall remain effective. Similarly, invalidity of a provision of the Agreement, for any reason whatsoever, shall not cause the Agreement as a whole to be invalid. 11.5 LANGUAGE The Agreement is drafted in both French and English and both versions are deemed authentic. Article 12 - NEW VERSIONS OF THE AGREEMENT 12.1 Any person is authorized to duplicate and distribute copies of this Agreement. 12.2 So as to ensure coherence, the wording of this Agreement is protected and may only be modified by the authors of the License, who reserve the right to periodically publish updates or new versions of the Agreement, each with a separate number. These subsequent versions may address new issues encountered by Free Software. 12.3 Any Software distributed under a given version of the Agreement may only be subsequently distributed under the same version of the Agreement or a subsequent version, subject to the provisions of Article 5.3.4. Article 13 - GOVERNING LAW AND JURISDICTION 13.1 The Agreement is governed by French law. The Parties agree to endeavor to seek an amicable solution to any disagreements or disputes that may arise during the performance of the Agreement. 13.2 Failing an amicable solution within two (2) months as from their occurrence, and unless emergency proceedings are necessary, the disagreements or disputes shall be referred to the Paris Courts having jurisdiction, by the more diligent Party. Version 2.0 dated 2006-09-05. discoSnp/output_analyses/0000755000000000000000000000000012232437324014577 5ustar rootrootdiscoSnp/output_analyses/discoSnp_to_genotypes.py0000755000000000000000000000406312227047666021552 0ustar rootroot#!/usr/bin/env python import sys def get_central_nuc(s1,s2): s_maj="" for l in s1: if l.isupper(): s_maj=s_maj+l central1=s_maj[len(s_maj)/2] s_maj="" for l in s2: if l.isupper(): s_maj=s_maj+l central2=s_maj[len(s_maj)/2] return s_maj[0:len(s_maj)/2]+central1+"/"+central2+s_maj[(len(s_maj)/2)+1:] if len(sys.argv) !=3: print "Mandatory: python discoSnp_to_genotypes.py prefix_coherent_k_kval_c_cval.fa threshold_value" print "This program extracts the \genotypes\" of each SNP:" print "\t for each SNP and each input data set it indicates if the SNP is:" print "\t\t -homozygous ALT1 path (coverage ALT1 >= threshold and ALT2 < threshold): 1" print "\t\t -homozygous ALT2 path (coverage ALT1 < threshold and ALT2 >= threshold): -1" print "\t\t -heterozygous (coverage ALT1 >= threshold and ALT2 >= threshold): 2" print "\t\t -absent (coverage ALT1 < threshold and ALT2 < threshold): 0" print "\t then it outputs the central sequence of length 2k-1 replacing the central position by ALT1/ALT2" sys.exit(1) f=open(sys.argv[1], "r") t=int(sys.argv[2]) while 1: com1_1=f.readline() if not com1_1: break data1_1=f.readline() if not data1_1: break com1_2=f.readline() if not com1_2: break data1_2=f.readline() if not data1_2: break sequence=get_central_nuc(data1_1, data1_2) com1_tab=com1_1.split("|") com2_tab=com1_2.split("|") # get coverages for computing genotypings sys.stdout.write("GENOTYPES_SNP_") print com1_tab[0].split("_")[-1], sys.stdout.write("_THRESHOLD_") print t, i=4 while com1_tab[i][0:1]!="C" and i=t and lo=t: print -1, if up=t and lo>=t: print 2, i+=1 print sequence discoSnp/output_analyses/discoSnp_to_csv.py0000755000000000000000000000311412227041676020317 0ustar rootroot#!/usr/bin/env python import sys if len(sys.argv) !=2: print "Mandatory: python discoSnp_to_csv.py prefix_coherent_k_kval_c_cval.fa" print "This program formats the .fa to .csv format by puting each couple of .fa sequence (4 lines = 2 comments + 2 nucleotide sequences) into one line, replacing the '|' character by spaces and removing the CX_ formating" sys.exit(1) f=open(sys.argv[1], "r") while 1: com1_1=f.readline() if not com1_1: break data1_1=f.readline() if not data1_1: break com1_2=f.readline() if not com1_2: break data1_2=f.readline() if not data1_2: break com1_tab=com1_1.split("|") # prints all before coverages for i in range(0,4): print com1_tab[i], # prints coverages i=4 while com1_tab[i][0:1]!="C" and i