Commit e1acd30a2f8ff5cebcebc822642171c8ec730fff
1 parent
c30f34a4
implement bisection for non-equidistant nodes
Showing
2 changed files
with
46 additions
and
15 deletions
include/GNodeArray.hpp
src/GNodeArray.cpp
| ... | ... | @@ -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 | 20 | /* __ Includes ___________________________________________________________ */ |
| 16 | 21 | #include <iostream> |
| ... | ... | @@ -192,10 +197,16 @@ void GNodeArray::nodes(const GVector& vector) |
| 192 | 197 | * @brief Set indices and weighting factors for interpolation |
| 193 | 198 | * |
| 194 | 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 | 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 | 210 | if (m_is_linear) { |
| 200 | 211 | |
| 201 | 212 | // Set left index |
| ... | ... | @@ -205,20 +216,41 @@ void GNodeArray::set_value(const double& value) |
| 205 | 216 | if (m_inx_left < 0) m_inx_left = 0; |
| 206 | 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 | 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 | 254 | // Return |
| 223 | 255 | return; |
| 224 | 256 | } |
| ... | ... | @@ -297,7 +329,7 @@ void GNodeArray::free_members(void) |
| 297 | 329 | ***************************************************************************/ |
| 298 | 330 | void GNodeArray::setup(void) |
| 299 | 331 | { |
| 300 | - // Setup distance array | |
| 332 | + // Setup distance array between subsequent nodes | |
| 301 | 333 | for (int i = 0; i < m_nodes-1; ++i) |
| 302 | 334 | m_step[i] = m_node[i+1] - m_node[i]; |
| 303 | 335 | |
| ... | ... | @@ -310,9 +342,8 @@ void GNodeArray::setup(void) |
| 310 | 342 | for (int i = 0; i < m_nodes-1; ++i) { |
| 311 | 343 | double eps = m_linear_slope * m_node[i] + m_linear_offset - double(i); |
| 312 | 344 | if (fabs(eps) > 1.0e-6) { |
| 313 | - cout << "WARNING: Node " << i | |
| 314 | - << "indexing is invalid (eps=" << eps << ")" << endl; | |
| 315 | 345 | m_is_linear = 0; |
| 346 | + break; | |
| 316 | 347 | } |
| 317 | 348 | } |
| 318 | 349 | ... | ... |