00001 00002 // File: hash.cpp // 00003 // Description: source file for classes hash_element and hash_cones // 00004 // This file is part of the SISCone project. // 00005 // For more details, see http://projects.hepforge.org/siscone // 00006 // // 00007 // Copyright (c) 2006 Gavin Salam and Gregory Soyez // 00008 // // 00009 // This program is free software; you can redistribute it and/or modify // 00010 // it under the terms of the GNU General Public License as published by // 00011 // the Free Software Foundation; either version 2 of the License, or // 00012 // (at your option) any later version. // 00013 // // 00014 // This program is distributed in the hope that it will be useful, // 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 00017 // GNU General Public License for more details. // 00018 // // 00019 // You should have received a copy of the GNU General Public License // 00020 // along with this program; if not, write to the Free Software // 00021 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA // 00022 // // 00023 // $Revision:: 123 $// 00024 // $Date:: 2007-02-28 20:52:16 -0500 (Wed, 28 Feb 2007) $// 00026 00027 #include <math.h> 00028 #include <stdio.h> 00029 #include "hash.h" 00030 #include <iostream> 00031 00032 namespace siscone{ 00033 00034 using namespace std; 00035 00036 /************************************************************** 00037 * implementation of hash_cones * 00038 * list of cones candidates. * 00039 * We store in this class all the hash_elements and give * 00040 * functions to manipulate them. * 00041 **************************************************************/ 00042 00043 // constructor with initialisation 00044 // - _Np number of particles 00045 // - _R2 cone radius (squared) 00046 //----------------------------------- 00047 hash_cones::hash_cones(int _Np, double _R2){ 00048 int i; 00049 00050 n_cones = 0; 00051 00052 // determine hash size 00053 mask = 1 << (int) (2*log(double(_Np))/log(2.0)); 00054 if (mask<=1) mask=2; 00055 00056 // create hash 00057 hash_array = new hash_element*[mask]; 00058 mask--; 00059 00060 // set the array to 0 00061 //? needed ? 00062 for (i=0;i<mask+1;i++) 00063 hash_array[i] = NULL; 00064 00065 R2 = _R2; 00066 } 00067 00068 // destructor 00069 //------------ 00070 hash_cones::~hash_cones(){ 00071 int i; 00072 hash_element *elm; 00073 00074 for (i=0;i<mask+1;i++){ 00075 while (hash_array[i]!=NULL){ 00076 elm = hash_array[i]; 00077 hash_array[i] = hash_array[i]->next; 00078 delete elm; 00079 } 00080 } 00081 00082 delete[] hash_array; 00083 } 00084 00085 00086 /* 00087 * insert a new candidate into the hash. 00088 * - v 4-momentum of the cone to add 00089 * - parent parent particle defining the cone 00090 * - child child particle defining the cone 00091 * - p_io whether the parent has to belong to the cone or not 00092 * - c_io whether the child has to belong to the cone or not 00093 * return 0 on success, 1 on error 00094 ***********************************************************************/ 00095 int hash_cones::insert(Cmomentum *v, Cmomentum *parent, Cmomentum *child, bool p_io, bool c_io){ 00096 hash_element *elm; 00097 int index = (v->ref.ref[0]) & mask; 00098 00099 // check the array cell corresponding to our reference 00100 elm = hash_array[index]; 00101 do{ 00102 // if it is not present, add it 00103 if (elm==NULL){ 00104 // create element 00105 elm = new hash_element; 00106 00107 // set its varibles 00108 // Note: at this level, eta and phi have already been computed 00109 // through Cmomentum::build_etaphi. 00110 elm->ref = v->ref; 00111 00112 //compute vectors centre 00113 v->build_etaphi(); 00114 elm->eta = v->eta; 00115 elm->phi = v->phi; 00116 // if at least one of the two is_inside tests gives a result != from the expected, 00117 // the || will be true hence !(...) false as wanted 00118 elm->is_stable = !((is_inside(v, parent)^p_io)||(is_inside(v, child)^c_io)); 00119 //cout << "-- new status of " << v->ref[0] << ":" << elm->is_stable << endl; 00120 00121 // update hash 00122 elm->next = hash_array[index]; 00123 hash_array[index] = elm; 00124 00125 n_cones++; 00126 return 0; 00127 } 00128 00129 // if the cone is already there, simply update stability status 00130 if (v->ref == elm->ref){ 00131 // there is only an update to perform to see if the cone is still stable 00132 if (elm->is_stable){ 00133 v->build_etaphi(); 00134 elm->is_stable = !((is_inside(v, parent)^p_io)||(is_inside(v, child)^c_io)); 00135 //cout << " parent/child: " 00136 // << parent->ref[0] << ":" << is_inside(v, parent) << ":" << p_io << " " 00137 // << child->ref[0] << ":" << is_inside(v, child) << ":" << c_io << endl; 00138 //cout << "-- rep status of " << v->ref[0] << ":" << elm->is_stable << endl; 00139 //cout << v->eta << " " << v->phi << endl; 00140 //cout << (child->eta) << " " << child->phi << endl; 00141 } 00142 return 0; 00143 } 00144 00145 elm = elm->next; 00146 } while (1); 00147 00148 return 1; 00149 } 00150 00151 /* 00152 * insert a new candidate into the hash. 00153 * - v 4-momentum of te cone to add 00154 * Note, in this case, we assume stability. We also assume 00155 * that eta and phi are computed for v 00156 * return 0 on success, 1 on error 00157 ***********************************************************************/ 00158 int hash_cones::insert(Cmomentum *v){ 00159 hash_element *elm; 00160 int index = (v->ref.ref[0]) & mask; 00161 //cout << "-- stable candidate: " << v->ref[0] << ":" << endl; 00162 00163 // check the array cell corresponding to our reference 00164 elm = hash_array[index]; 00165 do{ 00166 // if it is not present, add it 00167 if (elm==NULL){ 00168 // create element 00169 elm = new hash_element; 00170 00171 // set its varibles 00172 // Note: at this level, eta and phi have already been computed 00173 // through Cmomentum::build_etaphi. 00174 elm->ref = v->ref; 00175 elm->eta = v->eta; 00176 elm->phi = v->phi; 00177 elm->is_stable = true; 00178 00179 // update hash 00180 elm->next = hash_array[index]; 00181 hash_array[index] = elm; 00182 00183 n_cones++; 00184 return 0; 00185 } 00186 00187 // if the cone is already there, we have nothing to do 00188 if (v->ref == elm->ref){ 00189 return 0; 00190 } 00191 00192 elm = elm->next; 00193 } while (1); 00194 00195 return 1; 00196 } 00197 00198 /* 00199 * test if a particle is inside a cone of given centre. 00200 * check if the particle of coordinates 'v' is inside the circle of radius R 00201 * centered at 'centre'. 00202 * - centre centre of the circle 00203 * - v particle to test 00204 * return true if inside, false if outside 00205 ******************************************************************************/ 00206 inline bool hash_cones::is_inside(Cmomentum *centre, Cmomentum *v){ 00207 double dx, dy; 00208 00209 dx = centre->eta - v->eta; 00210 dy = fabs(centre->phi - v->phi); 00211 if (dy>M_PI) 00212 dy -= 2.0*M_PI; 00213 00214 return dx*dx+dy*dy<R2; 00215 } 00216 00217 }