Commit ac8208884b848fbe81a683effe5f07c54883a0e7
1 parent
3c121781
Use bisection for row search in GMatrixSparse::row() and GMatrixSparse::get_index() methods.
Bisection is substantially faster then the previous looping over all elements in a column.
Showing
1 changed file
with
53 additions
and
29 deletions
src/linalg/GMatrixSparse.cpp
| ... | ... | @@ -804,18 +804,26 @@ GVector GMatrixSparse::row(const int& row) const |
| 804 | 804 | int i_start = m_colstart[col]; |
| 805 | 805 | int i_stop = m_colstart[col+1]; |
| 806 | 806 | |
| 807 | - // Search requested row in elements | |
| 808 | - int i; | |
| 809 | - for (i = i_start; i < i_stop; ++i) { | |
| 810 | - if (m_rowinx[i] == row) { | |
| 811 | - break; | |
| 807 | + // If column is not empty then search requested row by bisection | |
| 808 | + if (i_stop > i_start) { | |
| 809 | + | |
| 810 | + // Find row by bisection | |
| 811 | + while ((i_stop - i_start) > 1) { | |
| 812 | + int mid = (i_start+i_stop) / 2; | |
| 813 | + if (m_rowinx[mid] > row) { | |
| 814 | + i_stop = mid; | |
| 815 | + } | |
| 816 | + else { | |
| 817 | + i_start = mid; | |
| 818 | + } | |
| 812 | 819 | } |
| 813 | - } | |
| 814 | 820 | |
| 815 | - // Copy element if we found one | |
| 816 | - if (i < i_stop) { | |
| 817 | - result[col] = m_data[i]; | |
| 818 | - } | |
| 821 | + // Copy element if we found the row | |
| 822 | + if (m_rowinx[i_start] == row) { | |
| 823 | + result[col] = m_data[i_start]; | |
| 824 | + } | |
| 825 | + | |
| 826 | + } // endif: column was not empty | |
| 819 | 827 | |
| 820 | 828 | } // endfor: looped over all columns |
| 821 | 829 | |
| ... | ... | @@ -2786,40 +2794,56 @@ void GMatrixSparse::free_stack_members(void) |
| 2786 | 2794 | * |
| 2787 | 2795 | * @param[in] row Row index. |
| 2788 | 2796 | * @param[in] column Column index. |
| 2797 | + * @return Element index. | |
| 2789 | 2798 | * |
| 2790 | 2799 | * Returns the index in the compressed array for (row,col). The following |
| 2791 | 2800 | * special results exist: |
| 2792 | - * -1: Requested index does not exist in the matrix. | |
| 2793 | - * m_elements: Requested index is the pending element. | |
| 2801 | + * | |
| 2802 | + * -1: Requested index does not exist in the matrix. | |
| 2803 | + * m_elements: Requested index is the pending element. | |
| 2794 | 2804 | ***************************************************************************/ |
| 2795 | 2805 | int GMatrixSparse::get_index(const int& row, const int& column) const |
| 2796 | 2806 | { |
| 2797 | 2807 | // Initialise element to 'not found' |
| 2798 | 2808 | int index = -1; |
| 2799 | 2809 | |
| 2800 | - // If we have a pending element then check if this element is requested | |
| 2801 | - if (m_fill_val != 0.0) { | |
| 2802 | - if (row == m_fill_row && column == m_fill_col) { | |
| 2803 | - return m_elements; | |
| 2804 | - } | |
| 2810 | + // If we have a pending element and the pending element is requested | |
| 2811 | + // then return m_elements as index | |
| 2812 | + if ((m_fill_val != 0.0) && (row == m_fill_row && column == m_fill_col)) { | |
| 2813 | + index = m_elements; | |
| 2805 | 2814 | } |
| 2815 | + | |
| 2816 | + // ... otherwise if there are elements in the matrix then search for | |
| 2817 | + // the requested row and column. | |
| 2818 | + else if (m_elements > 0) { | |
| 2806 | 2819 | |
| 2807 | - // If requested element is not the pending element then check if it exists | |
| 2808 | - // in the matrix. Only if it is found its index is returned. Otherwise | |
| 2809 | - // the default index is -1, signalling that the element is absent. | |
| 2810 | - if (m_elements > 0) { | |
| 2820 | + // Get the start and stop of the elements | |
| 2811 | 2821 | int* ptr_colstart = m_colstart + column; |
| 2812 | 2822 | int i_start = *ptr_colstart++; |
| 2813 | 2823 | int i_stop = *ptr_colstart; |
| 2814 | - int* ptr_rowinx = m_rowinx + i_start; | |
| 2815 | - for (int i = i_start; i < i_stop; ++i) { | |
| 2816 | - int row_test = *ptr_rowinx++; | |
| 2817 | - if (row_test == row) { | |
| 2818 | - index = i; | |
| 2819 | - break; | |
| 2824 | + | |
| 2825 | + // If column is not empty then search requested row by bisection | |
| 2826 | + if (i_stop > i_start) { | |
| 2827 | + | |
| 2828 | + // Find row by bisection | |
| 2829 | + while ((i_stop - i_start) > 1) { | |
| 2830 | + int mid = (i_start+i_stop) / 2; | |
| 2831 | + if (m_rowinx[mid] > row) { | |
| 2832 | + i_stop = mid; | |
| 2833 | + } | |
| 2834 | + else { | |
| 2835 | + i_start = mid; | |
| 2836 | + } | |
| 2820 | 2837 | } |
| 2821 | - } | |
| 2822 | - } | |
| 2838 | + | |
| 2839 | + // If we found the row then store the index | |
| 2840 | + if (m_rowinx[i_start] == row) { | |
| 2841 | + index = i_start; | |
| 2842 | + } | |
| 2843 | + | |
| 2844 | + } // endif: column was not empty | |
| 2845 | + | |
| 2846 | + } // endif: matrix contained elements | |
| 2823 | 2847 | |
| 2824 | 2848 | // Return index |
| 2825 | 2849 | return index; | ... | ... |