#picotron 0.1.1d is up on lexaloffle and humble! // picotron.net

Now with batch gfx operations (/system/demos/pixeldust.p64), stackable files (mousewheel to flip through), userdata:lerp, a new context menu, and many small fixes. changelog: https://www.lexaloffle.com/dl/docs/picotron_changelog.txt

@zep Didn’t see it in the release notes, but looks like indexed copy made it! (At least provisionally?)
@luchak Oops -- added to the changelog, thx. I think it is complete but I haven't tested it much yet (or worked out some finer details) so there's still a warning in the manual :)
https://www.lexaloffle.com/dl/docs/picotron_manual.html#Copy_with_Lookup_Table
Picotron User Manual

@zep Couple quick thoughts after trying to adapt smoke sim, if that's ok. Might be a couple toots :)

1. Ambiguity between indexed and non-indexed strided copy. (I think?) For example, fluid sim contains lines like:

a:copy(a,true,W,0,W,0,0,1)

to populate margin/boundary cells from interior/"real" cells. These still work for now but syntax overlap makes me uneasy.

2. Is there a better way to convert from float to int than idx:set(0,x:get(0,N))?

3. Would love for :mutate() to allow flattening.

@zep

4. Still haven't figured out semantics of 2D index arrays in copy. Was hoping it would just produce an output of same size as index, but I think there's an extra factor of index width in there. I feel like there must be a motivating use case for this behavior but I don't know what it is.

@zep Wait, scratch (4). I'm confused about something but not sure what just yet.

@zep Hm. If I do dst=src_2d:copy(idx_2d), dst has the same shape as idx_2d, but it's not the case that dst[i]==src_2d[idx_2d[i]] for all i in bounds. If I do dst=src_2d:copy(idx_2d,nil,0,0,1,1,1,W*H) I get a dst with shape (W*H,H). src_2d and idx_2d both have shape (W, H); idx_2d contains flat indices into src_2d. Flattening src_2d does not fix it, flattening idx_2d does.

So I have a fix, still not sure I understand the underlying mechanics!

@luchak
1. ah, that's a bug! for a:copy(idx, ..), the only time idx is meant to be observed is if it is used as the index and so is i32. So set to nil if just want a plain copy of a. The bug is: a:copy(b, ..) is returning a copy of b when b is not i32 (instead of ignoring it and returning a).

So I think it will be unambiguous when fixed. The reason for extending :copy() to impl lookups is that it is the only unary ud operation, and so had that (in theory) unused parameter kicking around.

@luchak

2. not currently -- will add that to ud:convert

3,4. You mean to e.g. change a 2d 4x4 userdata to 1d with 16 elements? I think it is meant to -- will check that. Ditto for shape output, I remember being unsure about that.

Thanks for testing; the 5x5 smoke looks amazing!

@zep Ah, I think I figured out my confusion on (3)! Probably based on my numpy experience, I expected there to be a distinction between "1D array" and "2D array of height 1" - but, looking at attribs, it seems there is not? Mutating a (2,3) UD by providing just a width of 6 (nil height) does not work, but providing a shape (6,1) does.

@zep Thanks for the reply! think there is a case for a:copy(b,true,...) where b is not an index and b!=a - copying blocks of b into a can be very useful.

The FFT code does this a lot, one simpler example (concatenation):

z:copy(x,true,0,0,VEC_SIZE) z:copy(y,true,0,VEC_SIZE,VEC_SIZE)

There are also more complex examples like extracting matrix rows at intervals from a vector:

local src=j*l+i
m_xt:copy(x,true,src*vec_size,j*vec_size,vec_size)

But I may still be missing a better way!

@zep Maybe this is handled now by indexed copy with strides? (edit: Some cases maybe? But the "write into some blocks only" case I don't think is...)

@luchak Aha ~ I would have said to write that as "b:copy(nil, a, ...)" but it turns out that combination was also broken in 0.1.1d! With that fixed, I was able to rewrite picotron_smoke-0 using unambiguous copy parameters.

BUT! Still feels like a semantic tightrope.

When using :copy with a scalar, it has to be: a:copy(3,true,...). Seeing that, it would be reasonable to assume a:copy(ud,true,...) does the same per element.

Time to allow both forms and move to :take(idx) for lookups I think.

@zep Oh wow, I didn't even realize that "b:copy(nil, a, ...)" was supposed to be a valid form! But I've never been 100% confident in my understanding of the u0,u1,u2 args. I'd certainly be on board with a more explicit distinction for indexing.

I also just updated the smoke cart on the BBS - but not sure the code illuminates anything new at this point. Managed to get most of the complexity into a `sample_bilinear()` function at least!

@zep Got the smoke sim from 9x9 to 5x5 pixel cells - biggest single improvement yet!