/********************************************************** This software is part of J.-S. Caux's ABACUS library. Copyright (c). ----------------------------------------------------------- File: Scan_Thread_Set.cc Purpose: defines all functions for Scan_Thread_Set class. ***********************************************************/ #include "JSC.h" using namespace std; using namespace JSC; namespace JSC { Scan_Thread_Set::Scan_Thread_Set() { dim = Vect (nlists); nthreads_tot = Vect (nlists); nthreads_done = Vect (nlists); label = Vect > (nlists); type = Vect > (nlists); isdone = Vect > (nlists); // Give starting values to all: for (int il = 0; il < nlists; ++il) { dim[il] = 100; nthreads_tot[il] = 0; nthreads_done[il] = 0; label[il] = Vect (dim[il]); type[il] = Vect (dim[il]); isdone[il] = Vect (false, dim[il]); } } bool Scan_Thread_Set::Increase_Size (int il, int nr_to_add) // resizes the vectors to accommodate up to nr_to_add additional entries { if (il < 0 || il > nlists) JSCerror("ilist out of bounds in Scan_Thread_Set::Increase_Size"); dim[il] += nr_to_add; try { label[il].Increase_Size (nr_to_add, ""); type[il].Increase_Size (nr_to_add); isdone[il].Increase_Size (nr_to_add, false); } catch (bad_alloc) { cout << "dim[il] " << dim[il] << "\tnr_to_add " << nr_to_add << endl; JSCerror("Memory allocation failed in Scan_Thread_Set::Increase_Size."); } return(true); } void Scan_Thread_Set::Include_Thread (DP abs_data_value_ref, string label_ref, int type_ref) { // Determine which ilist index is to be used: int il = int(-log(abs_data_value_ref)/logscale); if (il < 0) il = 0; if (il >= nlists) il = nlists - 1; if (nthreads_tot[il] > dim[il] - 10) { // Resize the Scan_Thread_Set list, by doubling its size //cout << "Resizing threads list" << endl; (*this).Increase_Size (il, dim[il]); //cout << "Done resizing" << endl; } //cout << "Including thread for label " << label_ref << " and type " << type_ref << endl; label[il][nthreads_tot[il] ] = label_ref; type[il][nthreads_tot[il] ] = type_ref; isdone[il][nthreads_tot[il] ] = false; nthreads_tot[il]++; } void Scan_Thread_Set::Merge (const Scan_Thread_Set& refset) { if (nlists != refset.nlists) JSCerror("nlists don't match in Scan_Thread_Set::Merge"); for (int il = 0; il < nlists; ++il) { if (nthreads_tot[il] + refset.nthreads_tot[il] >= dim[il]) (*this).Increase_Size (il, nthreads_tot[il]/10 + refset.nthreads_tot[il]); for (int i = 0; i < refset.nthreads_tot[il]; ++i) { label[il][nthreads_tot[il] ] = refset.label[il][i]; type[il][nthreads_tot[il] ] = refset.type[il][i]; isdone[il][nthreads_tot[il] ] = refset.isdone[il][i]; nthreads_tot[il]++; } } } void Scan_Thread_Set::Remove_Done_Threads (int il) { // If isdone[ithread] == true, remove from list int nr_removed = 0; for (int i = 0; i < nthreads_tot[il]; ++i) { if (!isdone[il][i]) { label[il][i - nr_removed] = label[il][i]; type[il][i - nr_removed] = type[il][i]; isdone[il][i - nr_removed] = isdone[il][i]; } else nr_removed++; } // Zero other entries: for (int i = nthreads_tot[il] - nr_removed; i < nthreads_tot[il]; ++i) { label[il][i] = ""; type[il][i] = 0; isdone[il][i] = false; } nthreads_tot[il] -= nr_removed; if (nthreads_done[il] != nr_removed) { cout << nthreads_done[il] << "\t" << nr_removed << endl; JSCerror("Miscount in removing threads during Scan_Thread_Set::Remove_Done_Threads."); } nthreads_done[il] = 0; return; } void Scan_Thread_Set::Remove_Done_Threads () { // If isdone[ithread] == true, remove from list for (int il = 0; il < nlists; ++il) (*this).Remove_Done_Threads(il); return; } void Scan_Thread_Set::Clear () { for (int il = 0; il < nlists; ++il) { nthreads_tot[il] = 0; nthreads_done[il] = 0; label[il] = Vect (dim[il]); type[il] = Vect (dim[il]); isdone[il] = Vect (false, dim[il]); } } void Scan_Thread_Set::Save(const char* outfile_Cstr) { // We save only the undone threads, so after cleanup. (*this).Remove_Done_Threads(); ofstream outfile; outfile.open(outfile_Cstr); if (outfile.fail()) JSCerror("Could not open outfile... "); outfile.precision(3); //cout << "Saving threads: nthreads_tot vector is" << endl; //for (int il = 0; il < nlists; ++il) //if (nthreads_tot[il] > 0) cout << il << "\t" << nthreads_tot[il] << "\t"; //cout << endl; bool started = false; for (int il = 0; il < nlists; ++il) { if (nthreads_tot[il] > 0) { if (started) outfile << endl; outfile << il << "\t" << label[il][0] << "\t" << type[il][0]; started = true; for (int i = 1; i < nthreads_tot[il]; ++i) { outfile << endl << il << "\t" << label[il][i] << "\t" << type[il][i]; } } } outfile.close(); return; } void Scan_Thread_Set::Load (const char* thrfile_Cstr) { ifstream infile; infile.open(thrfile_Cstr); if(infile.fail()) { cout << "Could not open file " << thrfile_Cstr << " in Scan_Thread_Set::Load." << endl; JSCerror("Terminating."); } (*this).Clear(); // First count the number of elements in each list: Vect nthreads_read(0, nlists); int il_read; string label_read; int type_read; while (infile.peek() != EOF) { infile >> il_read; infile >> label_read; infile >> type_read; nthreads_read[il_read]++; } infile.close(); //cout << "nthreads_read vector: " << endl; //for (int il = 0; il < nlists; ++il) //if (nthreads_read[il] > 0) cout << il << "\t" << nthreads_read[il] << "\t"; //cout << endl; // Now allocate the proper sizes: for (int il = 0; il < nlists; ++il) { (*this).Increase_Size (il, JSC::max(0, nthreads_read[il] - dim[il] + 10)); nthreads_read[il] = 0; } // Read threads data in: ifstream infile2; infile2.open(thrfile_Cstr); infile.seekg(0); while (infile2.peek() != EOF) { infile2 >> il_read; infile2 >> label[il_read][nthreads_read[il_read] ]; infile2 >> type[il_read][nthreads_read[il_read] ]; //isdone[il_read][nthreads_read[il_read] ] = false; // no need nthreads_tot[il_read]++; nthreads_read[il_read]++; } infile2.close(); //cout << "Loading threads: nthreads_tot vector is" << endl; //for (int il = 0; il < nlists; ++il) //if (nthreads_tot[il] > 0) cout << il << "\t" << nthreads_tot[il] << "\t"; //cout << endl; return; } } // namespace JSC