Commit e1acd30a2f8ff5cebcebc822642171c8ec730fff
1 parent
c30f34a4
implement bisection for non-equidistant nodes
Showing
2 changed files
with
46 additions
and
15 deletions
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& vector) | @@ -192,10 +197,16 @@ void GNodeArray::nodes(const GVector& 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& value) | @@ -205,20 +216,41 @@ void GNodeArray::set_value(const double& 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 |