| 132 | } |
| 133 | |
| 134 | bool llama_kv_cache_recurrent::seq_rm(llama_seq_id seq_id, llama_pos p0, llama_pos p1) { |
| 135 | uint32_t new_head = size; |
| 136 | |
| 137 | if (p0 < 0) { |
| 138 | p0 = 0; |
| 139 | } |
| 140 | |
| 141 | if (p1 < 0) { |
| 142 | p1 = std::numeric_limits<llama_pos>::max(); |
| 143 | } |
| 144 | |
| 145 | // models like Mamba or RWKV can't have a state partially erased |
| 146 | if (seq_id >= (int64_t) size) { |
| 147 | // could be fatal |
| 148 | return false; |
| 149 | } |
| 150 | if (0 <= seq_id) { |
| 151 | int32_t & tail_id = cells[seq_id].tail; |
| 152 | if (tail_id >= 0) { |
| 153 | const kv_cell & cell = cells[tail_id]; |
| 154 | // partial intersection is invalid |
| 155 | if ((0 < p0 && p0 <= cell.pos) || (0 < p1 && p1 <= cell.pos)) { |
| 156 | return false; |
| 157 | } |
| 158 | // invalidate tails which will be cleared |
| 159 | if (p0 <= cell.pos && cell.pos < p1) { |
| 160 | tail_id = -1; |
| 161 | } |
| 162 | } |
| 163 | } else { |
| 164 | // seq_id is negative, then the range should include everything or nothing |
| 165 | if (p0 != p1 && (p0 != 0 || p1 != std::numeric_limits<llama_pos>::max())) { |
| 166 | return false; |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | for (uint32_t i = 0; i < size; ++i) { |
| 171 | if (cells[i].pos >= p0 && cells[i].pos < p1) { |
| 172 | if (seq_id < 0) { |
| 173 | cells[i].seq_id.clear(); |
| 174 | } else if (cells[i].has_seq_id(seq_id)) { |
| 175 | cells[i].seq_id.erase(seq_id); |
| 176 | } else { |
| 177 | continue; |
| 178 | } |
| 179 | if (cells[i].is_empty()) { |
| 180 | // keep count of the number of used cells |
| 181 | if (cells[i].pos >= 0) { |
| 182 | used--; |
| 183 | } |
| 184 | cells[i].pos = -1; |
| 185 | cells[i].src = -1; |
| 186 | if (new_head == size) { |
| 187 | new_head = i; |
| 188 | } |
| 189 | } |
| 190 | } |
| 191 | } |
nothing calls this directly
no test coverage detected