@ngn have you seen the gcc/clang builtins for multiplication overflow? the note about "promote the first two operands into infinite precision signed type" sounds a bit slow though
@coltim yes, i've seen them. if i understand correctly, the "infinite precision" thing is just to describe the semantics, not the way they actually work.
when i tried using __builtin_add_overflow() in a loop, the compiler (at least gcc; i'll try clang later) couldn't vectorize it as i hoped, but luckily it does vectorize the trick for detecting overflows manually: (x^r)&(y^r)
for multiplication, i'll probably have to go with marshall's advice and temporarily cast to a wider type
I was toying with the idea (if I ever get to implementing another K) of having a 2-level page directory, which would make append (and possibly prepend) an O(1) operation, Copy-On-Writes become per-page, at some cost for random access, and minuscule cost for vectorized operations. In such a setting, "upgrade on overflow" can be done per-page and may actually be the most reasonable implementation.
@chrispsn in a nutshell: i believe that the strange "rank-sensitive" definition of ? was motivated by a desire to have @ and ? work as mutual inverses, to the greatest extent possible
but i'd be very reluctant to implement ? this way
classic example: x?"ab" - i want this to find the positions of "ab" in x (or 0N if not found), whatever the inner structure of x may be
@ngn fwiw, I like the "rank-sensitive" version more. as I tried to articulate earlier, ? and its derivatives feel different than the other primitives since they're centered around relating otherwise disparate data. so putting a finger on the scale of making that "easier" (versus maintaining the structure of the right arg/consistency with other primitives) feels worth it
@ngn For gather/scatter it means double indirection, yes. But for vector operations, it means one additional indirection per page (so, for an 1024 element page, 1/1024 more accesses - less for longer pages). But you can still prefetch a page in advance. It's basically adding another foreach(page in array) loop around the linear per-page implementation, and you can prefetch the next page when you start this one.
@ngn well, yes, sort of. assume you have a vector with 10G floats, and you want to change one item in it. With linear arrays, you have to make a complete copy, paying both memory and CPU/BUS bandwidth. If the operating system let you play with the page tables, you would have been able to pay just virtual address space, but no memory and no bandwidth. In the simplest form, that's all such a 2-level thing will do.
But the reason I was reminded of it was the discussion about restarting with a different size after overflow; For very little additional cpu, you can make different pages different size ints; and then a restart would (a) only apply to the latest page, not from the beginning, and (b) wouldn't necessarily apply to the end.
@ngn you mention "slices", I was talking about uniform sized pages (was thinking of a compile time constant). For full-vector operations, general slices aren't even more complicated, but for gather scatter there is no solution I'm aware of that's not extermely complicated or O(log n) instead of O(1) per element
@ngn It's not simple, no, but no auto-enlarging solution is. You have to pick your complexity poison there (or trigger an exception and move complexity to the user)