| | 1 | | #pragma rtGlobals=3 |
| | 2 | | #pragma TextEncoding="UTF-8" |
| | 3 | | #pragma rtFunctionErrors=1 |
| | 4 | | #pragma version=1.10 |
| | 5 | | #pragma ModuleName=IUTF_Utils_Vector |
| | 6 | |
|
| | 7 | | // Vector is a special concept that is similar to Vec<> in Rust or List<T> in C#. It represents a |
| | 8 | | // dynamically sized array of elements. All operation should be done using these methods. The wave |
| | 9 | | // that is returned here is the internal buffer and can contain more elements then it's length. |
| | 10 | |
|
| | 11 | | static StrConstant LENGTH_KEY = "NOTE_LENGTH" |
| | 12 | |
|
| 1029 | 13 | | static Function SetNumberInWaveNote(wv, key, value) |
| | 14 | | WAVE wv |
| | 15 | | string key |
| | 16 | | variable value |
| | 17 | |
|
| 1029 | 18 | | Note/K wv, ReplaceNumberByKey(key, note(wv), value) |
| 1029 | 19 | | End |
| | 20 | |
|
| | 21 | | /// @brief Set the length of the vector. This doesn't change the capacity or size of any dimension. |
| 1029 | 22 | | static Function SetLength(wv, value) |
| | 23 | | WAVE wv |
| | 24 | | variable value |
| | 25 | |
|
| 1029 | 26 | | SetNumberInWaveNote(wv, LENGTH_KEY, value) |
| 1029 | 27 | | End |
| | 28 | |
|
| | 29 | | /// @brief Returns the length of the vector. This doesn't output the capacity or the real size of |
| | 30 | | /// any dimension. |
| 1016 | 31 | | static Function GetLength(wv) |
| | 32 | | WAVE wv |
| | 33 | |
|
| 1016 | 34 | | return NumberByKey(LENGTH_KEY, note(wv)) |
| 1016 | 35 | | End |
| | 36 | |
|
| | 37 | | /// @brief Automatically increase the wave row size if required to fit the specified index. |
| | 38 | | /// The actual (filled) wave size is not tracked, the caller has to do that. |
| | 39 | | /// Returns 1 if the wave was resized, 0 if it was not resized |
| | 40 | | /// |
| | 41 | | /// Known Limitations: Igor 32 bit has a limit of 2 GB and 64bit a limit of 200 GB a wave can be. |
| 412 | 42 | | static Function EnsureCapacity(wv, indexShouldExist) |
| | 43 | |
|
| | 44 | | WAVE wv |
| | 45 | | variable indexShouldExist |
| | 46 | |
|
| 412 | 47 | | variable size = DimSize(wv, UTF_ROW) |
| 412 | 48 | | variable targetSize |
| | 49 | |
|
| 412 | 50 | | if(indexShouldExist < size) |
| 406 | 51 | | return 0 |
| 6 | 52 | | endif |
| | 53 | |
|
| 6 | 54 | | // the wave is smaller than any usable chunk |
| 6 | 55 | | if(size < IUTF_WAVECHUNK_SIZE && indexShouldExist < IUTF_WAVECHUNK_SIZE) |
| 6 | 56 | | targetSize = IUTF_WAVECHUNK_SIZE |
| 6 | 57 | | // exponential sizing for smaller waves as this behave asymptotic better |
| 0 | 58 | | elseif(indexShouldExist < IUTF_BIGWAVECHUNK_SIZE) |
| 0 | 59 | | // Calculate the target size. This is a shortcut because we need most times to increase the |
| 0 | 60 | | // size only for a small amount and a single multiplication is faster then the complex |
| 0 | 61 | | // operation below. |
| 0 | 62 | | targetSize = size * 2 |
| 0 | 63 | | if(targetSize <= indexShouldExist) |
| 0 | 64 | | // target size: n |
| 0 | 65 | | // indexShouldExist: m |
| 0 | 66 | | // chunk size: c |
| 0 | 67 | | // exponent: e |
| 0 | 68 | | // |
| 0 | 69 | | // n = c * 2 ^ e >= m + 1 |
| 0 | 70 | | // => 2 ^ e >= (m + 1)/c |
| 0 | 71 | | // => e >= log_2((m + 1) / c) |
| 0 | 72 | | // => e = ceil(log_2((m + 1) / c)) |
| 0 | 73 | | // => n = c * 2 ^ ceil(log_2((m + 1) / c)) = c * 2 ^ ceil(ln((m + 1) / c) / ln(2)) |
| 0 | 74 | | targetSize = IUTF_WAVECHUNK_SIZE * 2^ceil(ln((indexShouldExist + 1) / IUTF_WAVECHUNK_SIZE) / ln(2)) |
| 0 | 75 | | endif |
| 0 | 76 | | // linear sizing for really large waves with high system memory impact. This is to reduce system |
| 0 | 77 | | // memory stress. |
| 0 | 78 | | else |
| 0 | 79 | | // target size: n |
| 0 | 80 | | // indexShouldExist: m |
| 0 | 81 | | // big chunk size: c |
| 0 | 82 | | // multiplicator: a |
| 0 | 83 | | // |
| 0 | 84 | | // n = c * a >= m + 1 |
| 0 | 85 | | // => a >= (m + 1) / c |
| 0 | 86 | | // => a = ceil((m + 1) / c) |
| 0 | 87 | | // => n = c * ceil((m + 1) / c) |
| 0 | 88 | | targetSize = IUTF_BIGWAVECHUNK_SIZE * ceil((indexShouldExist + 1) / IUTF_BIGWAVECHUNK_SIZE) |
| 6 | 89 | | endif |
| | 90 | |
|
| 6 | 91 | | Redimension/N=(targetSize, -1, -1, -1) wv |
| | 92 | |
|
| 6 | 93 | | return 1 |
| 412 | 94 | | End |
| | 95 | |
|
| | 96 | | /// @brief Add a new row to the end of the vector and ensures if the wave has enough capacity for it. |
| | 97 | | /// This also updates the dimension label "CURRENT" to the new added row. |
| | 98 | | /// @param wv The wave for which a new row should be added |
| | 99 | | /// @returns The row index of the added row. |
| 323 | 100 | | static Function AddRow(wv) |
| | 101 | | WAVE wv |
| | 102 | |
|
| 323 | 103 | | return AddRows(wv, 1) |
| 323 | 104 | | End |
| | 105 | |
|
| | 106 | | /// @brief Add count new rows at the end of the vector and ensures if the wave has enough capacity |
| | 107 | | /// for it. This also updates the dimension label "CURRENT" to the last added row. |
| | 108 | | /// @param wv The wave for which new rows should be added. |
| | 109 | | /// @param count The number of new rows to add. If this parameter is less or equal than 0 the wave |
| | 110 | | /// remains unchanged. |
| | 111 | | /// @returns The row index of the last added row or -1 if the list is kept unchanged. |
| 328 | 112 | | static Function AddRows(wv, count) |
| | 113 | | WAVE wv |
| | 114 | | variable count |
| | 115 | |
|
| 328 | 116 | | variable oldLength, newLength |
| | 117 | |
|
| 328 | 118 | | if(count <= 0) |
| 0 | 119 | | return -1 |
| 328 | 120 | | endif |
| | 121 | |
|
| 328 | 122 | | oldLength = GetLength(wv) |
| 328 | 123 | | newLength = oldLength + count |
| 328 | 124 | | EnsureCapacity(wv, newLength - 1) |
| 328 | 125 | | SetLength(wv, newLength) |
| | 126 | |
|
| 328 | 127 | | IUTF_Utils_Waves#RemoveDimLabel(wv, UTF_ROW, "CURRENT") |
| 328 | 128 | | SetDimLabel UTF_ROW, newLength - 1, CURRENT, wv |
| | 129 | |
|
| 328 | 130 | | return newLength - 1 |
| 328 | 131 | | End |
| | 132 | |
|
| | 133 | | /// @brief Find the requested string inside the text wave. The full string has to match. If the |
| | 134 | | /// requested text is found multiple times in the wave it will return one of them. |
| | 135 | | /// |
| | 136 | | /// @param wv The text vector to search in |
| | 137 | | /// @param text The string to search |
| | 138 | | /// |
| | 139 | | /// @returns The index if found or -1 if not. |
| 322 | 140 | | static Function FindText(wv, text) |
| | 141 | | WAVE/T wv |
| | 142 | | string text |
| | 143 | |
|
| 322 | 144 | | variable length |
| | 145 | |
|
| | 146 | | #if (IgorVersion() >= 8.00) |
| 322 | 147 | | length = GetLength(wv) |
| 322 | 148 | | FindValue/Z/TEXT=(text)/TXOP=5/RMD=[0, length - 1] wv |
| | 149 | | #else |
| 0 | 150 | | FindValue/Z/TEXT=(text)/TXOP=5 wv |
| | 151 | | #endif |
| | 152 | |
|
| 322 | 153 | | return V_value |
| 322 | 154 | | End |