Commit e1acd30a2f8ff5cebcebc822642171c8ec730fff

Authored by knodlseder
1 parent c30f34a4

implement bisection for non-equidistant nodes

include/GNodeArray.hpp
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 ***************************************************************************/ 12 ***************************************************************************/
13 /** 13 /**
14 * @file GNodeArray.hpp 14 * @file GNodeArray.hpp
15 - * @brief GNodeArray class definition. 15 + * @brief GNodeArray class interface definition.
16 * @author J. Knodlseder 16 * @author J. Knodlseder
17 */ 17 */
18 18
src/GNodeArray.cpp
@@ -11,6 +11,11 @@ @@ -11,6 +11,11 @@
11 * * 11 * *
12 * ----------------------------------------------------------------------- * 12 * ----------------------------------------------------------------------- *
13 ***************************************************************************/ 13 ***************************************************************************/
  14 +/**
  15 + * @file GNodeArray.cpp
  16 + * @brief GNodeArray class implementation.
  17 + * @author J. Knodlseder
  18 + */
14 19
15 /* __ Includes ___________________________________________________________ */ 20 /* __ Includes ___________________________________________________________ */
16 #include <iostream> 21 #include <iostream>
@@ -192,10 +197,16 @@ void GNodeArray::nodes(const GVector&amp; vector) @@ -192,10 +197,16 @@ void GNodeArray::nodes(const GVector&amp; vector)
192 * @brief Set indices and weighting factors for interpolation 197 * @brief Set indices and weighting factors for interpolation
193 * 198 *
194 * @param[in] value Value for which the interpolation should be done. 199 * @param[in] value Value for which the interpolation should be done.
  200 + *
  201 + * Set the indices that bound the specified value and the corresponding
  202 + * weighting factors for linear interpolation. If the array has a linear
  203 + * form (i.e. the nodes are equidistant), an analytic formula is used to
  204 + * determine the boundary indices. If the nodes are not equidistant the
  205 + * boundary indices are searched by bisection.
195 ***************************************************************************/ 206 ***************************************************************************/
196 void GNodeArray::set_value(const double& value) 207 void GNodeArray::set_value(const double& value)
197 { 208 {
198 - // If array is linear 209 + // If array is linear then get left index from analytic formula
199 if (m_is_linear) { 210 if (m_is_linear) {
200 211
201 // Set left index 212 // Set left index
@@ -205,20 +216,41 @@ void GNodeArray::set_value(const double&amp; value) @@ -205,20 +216,41 @@ void GNodeArray::set_value(const double&amp; value)
205 if (m_inx_left < 0) m_inx_left = 0; 216 if (m_inx_left < 0) m_inx_left = 0;
206 else if (m_inx_left >= m_nodes-1) m_inx_left = m_nodes - 2; 217 else if (m_inx_left >= m_nodes-1) m_inx_left = m_nodes - 2;
207 218
208 - // Set right index  
209 - m_inx_right = m_inx_left + 1;  
210 -  
211 - // Set weighting factors  
212 - m_wgt_right = (value - m_node[m_inx_left]) / m_step[m_inx_left];  
213 - m_wgt_left = 1.0 - m_wgt_right;  
214 -  
215 } // endif: array is linear 219 } // endif: array is linear
216 220
217 - // ... otherwise search the relevant bin  
218 - {  
219 - // TBD 221 + // ... otherwise search the relevant indices by bisection
  222 + else {
  223 + // Set left index if value is before first node
  224 + if (value < m_node[0])
  225 + m_inx_left = 0;
  226 +
  227 + // Set left index if value is after last node
  228 + else if (value > m_node[m_nodes-1])
  229 + m_inx_left = m_nodes - 2;
  230 +
  231 + // Set left index by bisection
  232 + else {
  233 + int low = 0;
  234 + int high = m_nodes - 1;
  235 + int mid = 0;
  236 + while ((high - low) > 1) {
  237 + int mid = (low+high) / 2;
  238 + if (m_node[mid] > value)
  239 + high = mid;
  240 + else if (m_node[mid] <= value)
  241 + low = mid;
  242 + }
  243 + m_inx_left = low;
  244 + } // endelse: did bisection
220 } 245 }
221 246
  247 + // Set right index
  248 + m_inx_right = m_inx_left + 1;
  249 +
  250 + // Set weighting factors
  251 + m_wgt_right = (value - m_node[m_inx_left]) / m_step[m_inx_left];
  252 + m_wgt_left = 1.0 - m_wgt_right;
  253 +
222 // Return 254 // Return
223 return; 255 return;
224 } 256 }
@@ -297,7 +329,7 @@ void GNodeArray::free_members(void) @@ -297,7 +329,7 @@ void GNodeArray::free_members(void)
297 ***************************************************************************/ 329 ***************************************************************************/
298 void GNodeArray::setup(void) 330 void GNodeArray::setup(void)
299 { 331 {
300 - // Setup distance array 332 + // Setup distance array between subsequent nodes
301 for (int i = 0; i < m_nodes-1; ++i) 333 for (int i = 0; i < m_nodes-1; ++i)
302 m_step[i] = m_node[i+1] - m_node[i]; 334 m_step[i] = m_node[i+1] - m_node[i];
303 335
@@ -310,9 +342,8 @@ void GNodeArray::setup(void) @@ -310,9 +342,8 @@ void GNodeArray::setup(void)
310 for (int i = 0; i < m_nodes-1; ++i) { 342 for (int i = 0; i < m_nodes-1; ++i) {
311 double eps = m_linear_slope * m_node[i] + m_linear_offset - double(i); 343 double eps = m_linear_slope * m_node[i] + m_linear_offset - double(i);
312 if (fabs(eps) > 1.0e-6) { 344 if (fabs(eps) > 1.0e-6) {
313 - cout << "WARNING: Node " << i  
314 - << "indexing is invalid (eps=" << eps << ")" << endl;  
315 m_is_linear = 0; 345 m_is_linear = 0;
  346 + break;
316 } 347 }
317 } 348 }
318 349