@@ -236,12 +236,6 @@ class row_iterator_T {
236
236
237
237
inline VALUE rb_i () const { return LONG2NUM (i ()); }
238
238
239
- row_stored_nd_iterator_T<D,RefType,YaleRef> ndfind (size_t j) {
240
- if (j == 0 ) return ndbegin ();
241
- size_t p = y.real_find_left_boundary_pos (p_first, p_last, j + y.offset (1 ));
242
- return row_stored_nd_iterator_T<D,RefType,YaleRef>(*this , p);
243
- }
244
-
245
239
row_stored_iterator_T<D,RefType,YaleRef> begin () { return row_stored_iterator_T<D,RefType,YaleRef>(*this , p_first); }
246
240
row_stored_nd_iterator_T<D,RefType,YaleRef> ndbegin () { return row_stored_nd_iterator_T<D,RefType,YaleRef>(*this , p_first); }
247
241
row_stored_iterator_T<D,RefType,YaleRef> end () { return row_stored_iterator_T<D,RefType,YaleRef>(*this , p_last+1 , true ); }
@@ -257,6 +251,21 @@ class row_iterator_T {
257
251
row_stored_nd_iterator_T<D,RefType,YaleRef>(*this , y.real_find_left_boundary_pos (p_first, p_last, y.offset (1 )));
258
252
}
259
253
254
+ row_stored_nd_iterator_T<D,RefType,YaleRef> ndfind (size_t j) {
255
+ if (j == 0 ) return ndbegin ();
256
+ std::cerr << " ndfind: p_first = " << p_first << " " << p_last << std::endl;
257
+ size_t p = p_first > p_last ? p_first : y.real_find_left_boundary_pos (p_first, p_last, j + y.offset (1 ));
258
+ std::cerr << " ndfind(" << j << " )" << " = " << p << " \t (max_p = " << y.ija (y.real_shape (0 )) << " )" << std::endl;
259
+ row_stored_nd_iterator iter = row_stored_nd_iterator_T<D,RefType,YaleRef>(*this , p);
260
+ std::cerr << " iter.end = " << std::boolalpha << iter.end () << " , p = " << iter.p () << std::endl;
261
+ return iter;
262
+ }
263
+
264
+ row_stored_iterator_T<D,RefType,YaleRef> find (size_t j) {
265
+ if (j == 0 ) return begin (); // may or may not be on the diagonal
266
+ else return row_stored_iterator_T<D,RefType,YaleRef>(*this , ndfind (j).p (), false ); // is on the diagonal, definitely
267
+ }
268
+
260
269
/*
261
270
* Remove an entry from an already found non-diagonal position. Adjust this row appropriately so we can continue to
262
271
* use it.
@@ -265,9 +274,10 @@ class row_iterator_T {
265
274
row_stored_nd_iterator erase (row_stored_nd_iterator position) {
266
275
size_t sz = y.size ();
267
276
if (y.capacity () / nm::yale_storage::GROWTH_CONSTANT <= sz - 1 ) {
268
- y.update_resize_move (position, i () + offset ( 0 ), -1 );
277
+ y.update_resize_move (position, real_i ( ), -1 );
269
278
} else {
270
279
y.move_left (position, 1 );
280
+ y.update_real_row_sizes_from (real_i (), -1 );
271
281
}
272
282
adjust_length (-1 );
273
283
return row_stored_nd_iterator (*this , position.p ()-1 );
@@ -287,41 +297,20 @@ class row_iterator_T {
287
297
}
288
298
}
289
299
290
- // template <typename = typename std::enable_if<!std::is_const<RefType>::value>::type>
291
- template <typename T = typename std::conditional<std::is_const<RefType>::value,void ,row_stored_nd_iterator>::type>
292
- row_stored_nd_iterator insert (row_stored_iterator position, size_t jj, const D& val) {
293
- if (position.diag ()) {
294
- *position = val; // simply replace existing, regardless of whether it's 0 or not
295
- ++position;
296
- return row_stored_nd_iterator (*this , position.p ());
297
- } else {
298
- row_stored_nd_iterator jt (*this , position.p ());
299
- return insert (jt, jj, val);
300
- }
301
- }
302
300
303
- /*
304
- * Insert an element in column j, using position's p() as the location to insert the new column. i and j will be the
305
- * coordinates. This also does a replace if column j is already present.
306
- *
307
- * Returns true if a new entry was added and false if an entry was replaced.
308
- *
309
- * Pre-conditions:
310
- * - position.p() must be between ija(real_i) and ija(real_i+1), inclusive, where real_i = i + offset(0)
311
- * - real_i and real_j must not be equal
312
- */
301
+
313
302
// template <typename = typename std::enable_if<!std::is_const<RefType>::value>::type>
314
303
row_stored_nd_iterator insert (row_stored_nd_iterator position, size_t jj, const D& val) {
315
304
size_t sz = y.size ();
305
+ while (!position.end () && position.j () < jj) ++position; // position is just a hint. (This loop ideally only has to happen once.)
306
+
316
307
if (!position.end () && position.j () == jj) {
317
- std::cerr << " insert: *position = val at " << i_ << " ," << jj << " \t p=" << position.p () << std::endl;
318
308
*position = val; // replace existing
319
309
} else {
310
+
320
311
if (sz + 1 > y.capacity ()) {
321
- std::cerr << " insert: update_resize_move " << i_ << " ," << jj << " \t p=" << position.p () << std::endl;
322
312
y.update_resize_move (position, real_i (), 1 );
323
313
} else {
324
- std::cerr << " insert: move_right at " << i_ << " ," << jj << " \t p=" << position.p () << std::endl;
325
314
y.move_right (position, 1 );
326
315
y.update_real_row_sizes_from (real_i (), 1 );
327
316
}
@@ -333,26 +322,44 @@ class row_iterator_T {
333
322
return position++;
334
323
}
335
324
325
+
326
+ /*
327
+ * This version of insert doesn't return anything. Why, when the others do?
328
+ *
329
+ * Well, mainly because j here can be a diagonal entry. Most of the inserters return the *next* element following
330
+ * the insertion, but to do that, we have to create a row_stored_nd_iterator, which requires at least one binary
331
+ * search for the location following the diagonal (and as of the writing of this, two binary searches). There's no
332
+ * reason to do that when we never actually *use* the return value. So instead we just have void.
333
+ */
336
334
// template <typename = typename std::enable_if<!std::is_const<RefType>::value>::type>
337
- row_stored_nd_iterator insert (size_t j, const D& val) {
338
- return insert (ndfind (j), j, val);
335
+ void insert (size_t j, const D& val) {
336
+ if (j + y.offset (1 ) == real_i ()) a (real_i ()) = val;
337
+ else {
338
+ row_stored_nd_iterator jt = ndfind (j);
339
+ if (!jt.end () && jt.j () == j) {
340
+ if (val == y.const_default_obj ()) erase (jt); // erase
341
+ else insert (jt, j, val); // replace
342
+ } else { // only insert if it's not the default
343
+ if (val != y.const_default_obj ()) insert (jt, j, val);
344
+ }
345
+ }
339
346
}
340
347
341
348
342
349
/*
343
350
* Determines a plan for inserting a single row. Returns an integer giving the amount of the row change.
344
351
*/
345
- int single_row_insertion_plan (row_stored_nd_iterator position, size_t jj, size_t length, D const * v, size_t v_size, const size_t & v_offset) {
352
+ int single_row_insertion_plan (row_stored_nd_iterator position, size_t jj, size_t length, D const * v, size_t v_size, size_t v_offset) {
346
353
int nd_change;
347
- size_t m = v_offset;
348
- for (size_t jc = jj; jc < jj + length; ++jc, ++m ) {
349
- if (m >= v_size) m %= v_size; // reset v position.
354
+
355
+ for (size_t jc = jj; jc < jj + length; ++jc, ++v_offset ) {
356
+ if (v_offset >= v_size) v_offset %= v_size; // reset v position.
350
357
351
358
if (jc + y.offset (1 ) != real_i ()) { // diagonal -- no nd_change here
352
359
if (position.j () != jc) { // not present -- do we need to add it?
353
- if (v[m ] != y.const_default_obj ()) nd_change++;
360
+ if (v[v_offset ] != y.const_default_obj ()) nd_change++;
354
361
} else { // position.j() == jc
355
- if (v[m ] == y.const_default_obj ()) nd_change--;
362
+ if (v[v_offset ] == y.const_default_obj ()) nd_change--;
356
363
++position; // move iterator forward.
357
364
}
358
365
}
@@ -378,7 +385,7 @@ class row_iterator_T {
378
385
* Insert elements into a single row. Returns an iterator to the end of the insertion range.
379
386
*/
380
387
row_stored_nd_iterator insert (row_stored_nd_iterator position, size_t jj, size_t length, D const * v, size_t v_size, size_t & v_offset) {
381
- int nd_change = single_row_insertion_plan (position, jj, length, v, v_size);
388
+ int nd_change = single_row_insertion_plan (position, jj, length, v, v_size, v_offset );
382
389
383
390
// First record the position, just in case our iterator becomes invalid.
384
391
size_t pp = position.p ();
0 commit comments