« first day (665 days earlier)      last day (1982 days later) » 

12:01 AM
This is the final function. There has to be a better way to express this.
 
So again, 9.999…E6144 is max-128-bit-float, but it normally outputs as 1E6145, which is not valid input.
 
What I'm trying to express is "Get the color index of the closest point greater than 0"
 
@nathanrogers ⍸(⌊/ds)=ds(⊢⍳⌊/)ds or ds⍳⌊/ds
 
So the "128-bit float" in Dyalog is not binary128, but decimal128
 
That's what the 7 is. 5 is for binary. (somehow)
 
12:04 AM
@nathanrogers You have a Boolean from gtz←0<dists∊Pds Sds. No need to find indices of trues; just use it to compress: ds←gtz/dists and cs←gtz/∊Pcs Scs.
@Bubbler Correct:
]help ⎕FR
 
cs⍳⌊/ds @Adám?
 
@DyalogAPL Huh, that's odd.
@nathanrogers Index of lowest ds in ds.
 
(ds⍳⌊/ds)⊃cs ?
 
@Bubbler ⎕FR
@nathanrogers yes, but if there isn't any it will give an index 1+the max index of ds, so if cs and ds have the same length, you can get the default value 0 with (ds⍳⌊/ds)⊃cs,0
 
12:10 AM
I KNEW there was a way to use that trick here
just couldn't see it :(
 
@nathanrogers With time!
 
@nathanrogers Good job; that looks much cleaner, right?
 
⎕←1E9999
 
@Bubbler
SYNTAX ERROR
 
12:15 AM
it's true the succinctness helps to reveal the meaning much better than multiple declarations
 
ngn
@H.PWiz i got to 24 in yet another way: ∘.(≢∪~∩)⍨⊢↑¨∘↓(⌈⍀+\↑⍨⌸-)
 
⎕←1E999
 
@Bubbler
1E999
 
@nathanrogers That's why trains can be useful; they can be succinct enough to reveal patterns that otherwise may drown in code.
@nathanrogers I'm not sure I understand the phrase ⍉¨1⊂↑
@nathanrogers … I think it is the same as the idiomatic ↓⍉↑.
 
I get a value of two numbers back. I need to get the first value of each as colors, and the second value of each as distances
(1 2) (3 4)
1 2
3 4
1 | 2
3 | 4
colors dists←[1 3][2 4]
yes
and ↓⍉↑ does work
 
12:25 AM
@nathanrogers Right, that is a classic thing, basically a transpose, but on a vector of vectors instead of on a matrix, and ↓⍉↑ is the way to do it. That phrase is special-cased in the interpreter to be super fast and use less memory that each individual step.
 
@nathanrogers ∊Pds SdsPds,Sds?
 
no, because for some reason, sds is a vector?
I don't know why
I get a rank error
when using /
 
@nathanrogers I don't understand. Where exactly do you get a rank error? What is ≡Sds?
 
12:28 AM
@nathanrogers What is ⎕SE.Dyalog.Utils.repObj Sds?
 
,⊂0
 
@nathanrogers Well, if you expected Sds to be a simple vector, you probably have a bug somewhere then ;-)
 
I actually think it's something to do with the (+,-)
quadratic because spheres have 2 intersecting points
front and back
 
@ngn Very cool. I like the use of to do and ¨
 
@Adam Question about the structure of this program
and performance
 
12:34 AM
@nathanrogers ?
 
brief explanation: the Getcolors is a ∘.f function. Fxs and Fys are then combined to get a normal from the camera to the film plane, and ratios on the film plane to cast rays
I thought there might be a way to simple return a vector of normals from the camera to the plane, and evaluate them wholesale, without ¨ ,renaming GetColors to GetNormals, and calling Cast GetNormals
Is there a way to reduce that "eaching" so I don't have to Cast ¨ Fxs GetNormals Fys
In other words, this is at least an (≢objects)×n*2 operation, can you think of a way to vectorize the operations so that I don't have to do so much iteration?
Or as much calculations per iteration?
The equivalent C++ solution that I am working off of runs in ms, this one takes 15+ seconds.
 
@nathanrogers There may well be, but the problem is pretty complex for ≈1 AM, and I have to get up at 5 AM. Marshall may be the right one to answer this. I'll ask him to have a look tomorrow. Can you post your newest code, and maybe some valid arguments to try it on?
 
Ray is niladic, but I'll post it on TIO along with the codfns calls
 
@nathanrogers It is not niladic (only tradfns can be), but it may ignore any arguments. You really should make a point out of not using (semi-)globals, though.
 
like what?
 
12:47 AM
@nathanrogers Any name (esp. variables) in a fn which wasn't defined in that fn.
 
everything is defined in the function, except the display code
 
@nathanrogers P isn't defined in Cast.
@nathanrogers And just one last tip for this night morning: When doing assignments to multiple names, use parens. It helps both with clarity, and to disambiguate multi-assignments from modified assignment: a b←c(a b)←c
 
mistake
@Adám for morning ^^
 
 
11 hours later…
11:32 AM
@nathanrogers Reply from the reclusive Marshall Lochbaum:
For your ray tracer, I would recommend working with column vectors. This means that rather than storing a shape s array of vectors as a nested array which has shape s and contains 3-element vectors, you use a shape (3,s) array where each major cell corresponds to an axis. The advantage is that the cells are large and usually benefit from Dyalog's fast vector operations.

Looking at the three places where ray vectors are used, only small adjustments are needed to use column vectors:
PIntersect uses pN+.×⍺, where pN is a vector. This still works, but returns array. All the scalar functions in PIntersect will then work on this array, but later the elements of Pds will be arrays.
SIntersect uses a←+.×⍨dir, which needs to be changed to +⌿×⍨dir.
SIntersect uses dir+.×Cp-s, where Cp-s is a vector. Just swap the arguments, and this will work like pN+.×⍺ did.
GetColors requires some more significant modifications to work with column vectors. This leans heavily on the rank operator: using ⍤¯1 lets a function work with one axis at a time. Here are mag and norm adjusted to work on column vectors:
mag  ←{0.5*⍨+⌿⍵*2}
norm ←{⍵÷⍤¯1 99 mag ⍵}
Because individual vectors are just column vectors with scalar cells, these still serve the original purpose as well. Now we can push the ∘. inside GetColors so that it calls Cast on an array of column vectors:
GetColors←{Fx←⍺ ⋄ Fy←⍵
    Fo←(Fx∘.×⍨hFh×Cx)(∘.+⍤¯1)(Fy∘.×⍨hFw×Cy) ⍝ Film point calculated from Fx and Fy
    Cast norm Fo(+⍤¯1)Fc-Cp                 ⍝ Cast the ray in the direction of film
}
I'll leave out some of the details of converting Cast to work with column vectors, but finding the index of the minimum positive distance is something that requires explanation. Let's say dists is a nested vector, and each item is an entire array of distances. We want an array where each item gives the index of the item of dists which has the minimum positive distance for that position. The following function does it:
indmin ← {
    ⎕CT ← 0                ⍝ Comparisons with min should be intolerant
    inf ← ⌊⌿⍬              ⍝ Largest float.
    ds ← inf@(≤∘0)¨ ⍵      ⍝ Replace negative values with "infinity"
    m ← ⌊⌿ds               ⍝ Minimum
    ismin ← (m<inf) ∧ m=ds ⍝ Where is the minimum, if any?
    +⌿∧⍀~↑ ismin           ⍝ Count leading zeros of ismin
}
The use of split in the last line is needed because ∧⍀ is O(n²) on vectors of arrays, but O(n) on simple arrays. This is a known bug and I will probably fix it by version 18.0.
An iterative solution, which keeps a minimum array and an index array and updates each for every distance array, would also work and have good performance.
@nathanrogers Adám speaking again: I hope the above helps.
 
 
3 hours later…
2:48 PM
@Adám It's very interesting, but I'm a bit lost in the terminology.

https://chat.stackexchange.com/transcript/message/47705340#47705340

I don't understand what is meant by shape s and shape (3,s). "Each major cell corresponds to an axis" What is a major cell?
 
@nathanrogers Shape is simply what monadic would return. Shape s means a vector (list) of length s. Shape 3,s means a matrix with 3 rows and s columns.
@nathanrogers A major cell is the largest "sub-array". A 3D array's major cells are matrices. A matrix's major cells are rows (i.e. vectors). A vector's major cells are scalars.
 
Is he talking about the shape of world objects, or the shape of the ray matrix?
or the "film" matrix?
 
@nathanrogers The ray matrix, I think, as he continues in the next paragraph; Looking at.
@nathanrogers If s has two elements (i.e. the array is a matrix), then a (3,s) array is a 3D block with 3 layers, etc.
 
so he's talking about getting a (3,s) shape of the direction of the ray to the Film point
wait. now I don't get it
 
@nathanrogers The rays, I think; compute all the rays together. But I can ask, if you want.
 
3:08 PM
a 3d block with 3 layers?
 
@nathanrogers yes, one layer per dimension.
 
can you provide an illustration of what you mean? I thought he meant something like
1 2 3
4 5 6
7 8 9
. . .
. . .
. . .
What do you mean by layer?
 
Lets For 2×4 rays, you may have:
⎕←3 2 4⍴⍳24
 
@Adám
 1  2  3  4
 5  6  7  8

 9 10 11 12
13 14 15 16

17 18 19 20
21 22 23 24
 
where 1 9 17 is a single vector?
 
3:13 PM
@nathanrogers Yes.
 
@nathanrogers Think arrays — boom!
 
that's going to break my brains back bending that far this early
 
that doesn't look like an array to me
 
3:15 PM
@nathanrogers What doesn't look like an array?
 
3 2 4⍴⍳24
 
@nathanrogers What do you mean by that not looking like an array? WHat do you think an array is?
 
A list of values
 
@nathanrogers No that's what non-array languages call arrays, but they are just lists (which indeed is a specific case of an array). An array is an orthogonal (non-ragged, "rectangular") collection of data with 0 or more axes.
 
so the issue with performance in this case, is that each cell in my 2x2 matrix is a nested 3 vector, but instead, each cell in the 2x2 matrix should just be one "layer" of the 3d vector, where each layer is x, y, and z respectively
 
3:22 PM
@nathanrogers Exactly. As soon as you have nested arrays, performance drops.
 
gatcher
lemme read it again with my new glasses
 
@nathanrogers -○.○-
 
3:37 PM
how does ⍤¯1 work?
and why the constant 99 in norm?
@Adám
 
@nathanrogers ⍤¯1 applies the function on major cells; ¯1 means the rank of the argument-1.
@nathanrogers That's for "infinity", it applies to cells of the full rank of the argument, but since we don't know what the rank is, we use a value that's for sure higher (APL will just use the actual rank) and since max-rank in Dyalog currently is 15, 99 is safe.
 
 
3 hours later…
6:27 PM
@H.PWiz Very nice! Exceptionally clever, I like it. I like @ngn 's solution too. And both of you are doing exactly the same "logical" computation that I came up with, so that's great, as well. My only real gripe with the above are that they are computationally terrifying, but that's not what I asked for. :-)
My solution that I came up with is meant for more speed, and thus avoids the nested arguments as much as possible:
0⌈(∘.+⍨1+d)-2×(⍉+.=⊢)⌈\⌈⍀(⍳≢d)@(,d,¨⍳≢d)⊢0⍴⍨(1+⌈/d),≢d
However, I really, really like the Grade Up concept, and I think that's a really nice way to express it.
@ngn I like your use of Key in that solution!
@nathanrogers I just want to step in here and say that having a min-reduction on an empty vector return an empty vector is obviously not the right thing.
You can see that by going at it a few different ways, but the easiest way to see this is to note that you have a massive type discordance when you do that.
Types matter a lot in APL, even if you don't see them represented syntactically in the code, and messing with the type signatures of functions can result in chaos.
In the case of reduction, the rank of the result of a reduction is one less max 0 of the original value.
In other words, reducing a vector returns a scalar.
 
@arcfide By default CMCs (Chat Mini Challenges) are . If you want or , you need to say so.
 
So, when apply a min reduction against an empty vector, you're actually asking for the minimum scalar value.
@Adám Indeed, but I wanted shortest, not fastest. :-)
 
@arcfide Thanks. Credit goes to ngn for most of the method though. I sat for a significant amount of time without thinking of anything clever before peeking at his solution.
 
@arcfide Well, luckily we found a better way to express it, which doesn't require such special-casing.
 
@arcfide You should note that it can be replaced by `-↑⍤0+` at the same character count
 
6:42 PM
@nathanrogers If you suddenly have a result that might return a scalar and might return an empty vector, that's a real problem. Remember that arrays are not lists. Lists have a nil element, such as in Lisp or Scheme. But APL's Zilde is not a semantic equivalent to nil. They are very, very different beasts, and so you want to be careful there with introducing serious type issues inside of a reduction.
@H.PWiz I use the range type solution in my Paper on Path Matrices.
Both of you are building a type of path matrix, which makes my heart all warm and fuzzy.
@Adám Yes, and that's good. :-) I just wanted to rant a bit about the dangers of forgetting about the types of your programs, which is actually, I claim, one of the fundamental skills you need to be thinking about when working with APL programs.
 
Hmm, my \ got removed :(
 
@H.PWiz Maybe scan for it? ;-\
 
 
3 hours later…
9:22 PM
@Adám
 
@nathanrogers Yes?
 
@Adám I'm having a bug in the quadratic function
working in higher dimensions is new for me in APL and I'm not sure what to try
 
@nathanrogers Do you have ]boxing on?
 
yes
Was ON
 
@nathanrogers ]box on -style=max?
 
9:25 PM
what does that do?
 
@nathanrogers That draws the dimensions clearer. Compare:
 
so what I'm getting is shape of a b and c are all different.
 
⎕←2 3⍴⍳3 ⊣ 'this is with normal boxing on'
 
@Adám
1 2 3
1 2 3
 
⎕←1 2 3⍴⍳3
@DyalogAPL Hello?
 
9:27 PM
haha
 
⎕←1 2 3⍴⍳3
 
@Adám
1 2 3
1 2 3
 
@DyalogAPL Thanks!
⎕←1 2 3⍴⍳3 ⊣ ⎕SE.UCMD'box -s=max'
 
@Adám
┌┌→────┐
↓↓1 2 3│
││1 2 3│
└└~────┘
 
and:
⎕←2 3⍴⍳3 ⊣ ⎕SE.UCMD'box -s=max'
 
9:28 PM
@Adám
┌→────┐
↓1 2 3│
│1 2 3│
└~────┘
 
1=≢c , (⊃⍴⍵)=⍴b, and ??=⍴a?
 
@nathanrogers It is verbose, but now you can see the exact shape ^
 
⍴a = w x h
in the base case 8 x 6
 
@nathanrogers Solving the quadratic should increase the rank by 1.
 
no this is a b and c, they don't match
before the quadratic
 
9:30 PM
@nathanrogers then it's not the quadratic functions fault..
 
@nathanrogers Ah, that sounds like a problem before the quadratic formula.
 
and based on the above, it should look like this a←+⌿×⍨dir ⋄ b←2×(Cp-s)+.×dir ⋄ c←(+.×⍨Cp-s)-r*2
that's what I meant @dzaima @Adám sorry
they shapes are all different
so when performing the quadratic, length error ensues
 
@nathanrogers Have you tried tracing through the function with a small 8×6 test case, inspecting the intermediary results as you go, to see where things go awry?
 
10 hours ago, by Adám
SIntersect uses a←+.×⍨dir, which needs to be changed to +⌿×⍨dir.
yes, there is the step before a b c, where ⍵ looks normal
but a b and c look off
it's just the 1 line
 
@nathanrogers so forget about quadratic for now and just spam (or my fds if you're dealing with nested arrays) everywhere
 
9:33 PM
I don't understand his suggestions for higher dimensional stuff
 
@dzaima You know about the trace bit?
 
@Adám didn't it only go by lines or something?
 
@nathanrogers Hm, I wish I could make Marshall come in here to chat directly ⍨ but I can of course ask him tomorrow morning. He did seem very engaged.
 
3 8 6=⍴⍵
 
@dzaima Yes, so? I think all the code has but a single statement per line.
 
9:36 PM
@Adám when I've had shape problems, I easily know what line's the faulty one. What part of the expression is, is the question.
 
but I'm building a b c then running the quadratic
so, I can plainly see that a is wrong and c is wrong
but I don't know why
 
@nathanrogers Well, observe them as they are created.
 
+⌿×⍨dir is a, and that was a change from previous
dir is 3 8 6
 
@nathanrogers That's just the sum (across layers) of squares.
@nathanrogers Right, that's your world.
 
yes
I understand the cube of x y and z planes
 
9:39 PM
@nathanrogers And so a will be 8 6≡⍴
 
so then it's just c that is wrong
because 1=≢c
 
@nathanrogers Yeah, that doesn't match.
 
it should be +⌿× too yeah?
 
(@nathanrogers Btw, have you noticed that you've begun to speak APL? It is now easier for you to express what's going on and what you have using APL snippets in your English sentences!)
 
I'm actually still in the mode of pushing myself to use the terminology
"array" is a new one today for me
but it should be +⌿× because camera position is a 3d vector
 
9:42 PM
@nathanrogers haven't you ever before heard the phrase "everything is an array in APL"?
 
so +.× will give a single value
but then according to @Adám s definition of array from earlier today, "nonragged", then not everything is an array
 
@nathanrogers Well, the items of an array may be numbers, characters, and arrays (and some nasty stuff with don't mention).
 
@nathanrogers (1 2)(1 2 3) is just an array of arrays, all three non-ragged
 
... I don't want to get more confused
 
@nathanrogers every array in APL is a non-ragged any-dimensional array, just that sometimes some of the items are pointers to other arrays
 
9:44 PM
@nathanrogers Shouldn't it be +⌿×⍨? ⍨
 
it's only a 3 element vector
 
@dzaima some of the items are pointers to other arrays.
@nathanrogers Sure, but monadic × is sign. You want square (i.e. multiplication selfie), no?
 
@Adám you already said that before, I thought that the idea of pointers would bring some sense to how it's actually implemented & how to work around/understand them
 
so it's the (+,-)
 
@dzaima The underlying implementation shouldn't matter. Technically (i.e. implementation-wise), 1'a'2 is also an array of three pointers, but you needn't worry about that.
 
9:47 PM
and also the ×/4 a c
4×a×c fixes one shape issue
but now the (2×a) isn't the same shape as the result of the (+,-)
 
@nathanrogers Yeah, you may have needed ×⌿4 a c.
 
@Adám but an implementation can give an understanding of how something works. Me understanding that arrays of arrays can be thought of as arrays of pointers is what finally made understand APLs depth & rank distinction and me implementing an APL parser for my APL played a big, big part in making me understand how ops & trains work
 
so 2×a is ⍴a, but ⍴ is 2 8 6(-b)(+,-)...
 
@dzaima OK, fair enough. I just think that initially, when teaching APL, one need not delve into such details (at least if not asked). It is enough to know that items must not necessarily be simple scalars.
 
so then I need to reshape 2×a to match the right?
 
9:52 PM
@nathanrogers You may be able to use ⍤2
 
((-b)(+,-)0.5*⍨(b*2)-4×a×c) (÷⍤2) 2×a
like that?
 
@nathanrogers Yes, that should pair matrices of the left (there are 3 of those) with matrices (well, the matrix) on the right.
 
it isn't
 
@nathanrogers What shape result do you expect?
 
well
it says 8 12
I suppose it's the comma
 
9:58 PM
@nathanrogers Yes, it is concatenating the two 8×6 arrays.
 
just re-reshaped it back into the right shape and it seems to be working
 
@nathanrogers I'm afraid that'll mangle the order of your data.
 
@nathanrogers Which ⎕IO do you use?
 
10:00 PM
@nathanrogers Try (+,[¯0.5]-) instead of (+,-)
 
yeah, looks good, result is ⍴2 8 6
 
@nathanrogers ,[¯0.5] concatenates the two arrays along a new axis right before the first (0), thus increasing the rank by one and prepending a length to the shape vector.
@nathanrogers Now the big question is if it renders right too.
 
⍤_⍤
well I have to correct a few other things now
 
@nathanrogers OK, how are you feeling about all this?
 
It's making more sense the more I'm thinking in this higher dimension
but the questions are more about "how do I do this thing along this other dimension" in the data
 
10:04 PM
@nathanrogers Great. Free your mind from the shackles of lesser language's deficient array models.
@nathanrogers Look into rank
 
like for instance (bool list)/list
I know about ⍤ it's like " in J
 
@nathanrogers It is exactly the same.
 
but like the (+,-) I would never have known about that trick
 
@nathanrogers you can select an axis for / by putting [k] right after /, but most often, you'll want /[0], which is just
Note that the kth element of B's shape vector will be removed by f/[k]B
 
ok, so these two 8 x 6 matrices relate, how would I go about making them into a cube?
 
10:09 PM
@nathanrogers What shape do you want the result to be?
 
yeah, I guess that's already true
hmm.
(0=11○ps)⌿ps)
I'm not getting it
It would be great if I could just get ⌊⌿ps first, but then there are imaginary points
:(
is there a tolerant ⌊?
 
@nathanrogers Tolerant of?
 
imaginary numbers
along all possible dimensions /[] fails
0 1 or 2
 
@nathanrogers ⌊c rounds complex numbers to the closest a+bi where a and b are integers and |a+bi| < c
@nathanrogers You can't reduce over more than one axis at a time, but for , you can ⌊/,
 
that isn't working because domain error
I need to find a way to phrase this for 2 8 6
(0=11○ps)⌿ps)
 
10:17 PM
@nathanrogers If you want to ignore the imaginary part, why not just do ⌊/9○ps?
 
so that I can ⌊⌿ because of DOMAIN ERROR
I want to get rid of imaginary numbers altogether
oh,that just answererd my qeustion
 
@nathanrogers Oh sorry, you're using dyadic . I'm getting tired.
 
wait no it didn't
 
@nathanrogers Well, that won't ignore complex numbers, but it'll make purely imaginary ones = 0.
 
I could take a card out of the book from earlier, set imaginary numbers to infinity
and get the min that way
 
10:20 PM
@nathanrogers But then you'll get infinity when there are no real numbers. I.e. exactly what you get now!
 
well I'd like for them to be zero, but I can't zero them because then I wont' know the min!
I could zero them out after
but that's inelegant and blegh
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 0 1 1
1 1 0 0 0 1
1 1 1 0 1 1
1 1 1 1 1 1
1 1 1 1 1 1
this is kind of neat. this is where all imaginary points are in an 8 by 6, the sphere is so cute
 
@nathanrogers Does ⌊⌿| help you?
 
9.848857802 9.848857802 9.848857802 9.848857802 9.848857802 9.848857802
9.848857802 9.848857802 9.848857802 9.848857802 9.848857802 9.848857802
9.848857802 9.848857802 9.848857802 9.848857802 9.848857802 9.848857802
9.848857802 9.848857802 9.848857802 8.786073574 9.848857802 9.848857802
9.848857802 9.848857802 8.786073574 8.049875621 8.786073574 9.848857802
9.848857802 9.848857802 9.848857802 8.786073574 9.848857802 9.848857802
9.848857802 9.848857802 9.848857802 9.848857802 9.848857802 9.848857802
maybe?
there is 8's everywhere the 0's appeared before
but then what's with the 9s?
I think it should be either 0 or the intersect distance
so zero where not imaginary
and the value if not imaginary
 
@nathanrogers zero where not imaginary and the value if not imaginary‽ Isn't that a contradiction?
 
no
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 0 1 1
1 1 0 0 0 1
1 1 1 0 1 1
1 1 1 1 1 1
1 1 1 1 1 1
in this array, where 1's should be zero, where 0 should be the least in that index accross dimensions
 
10:27 PM
@nathanrogers Ah so ~ that mask and multiply it by ⌊⌿9○
 
just answered my question again
yeah
I was thinking that, but talked myself out of it :P
 
@nathanrogers So you meant zero where yes imaginary and the value where not imaginary?
 
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 8.786073574 0 0
0 0 8.786073574 8.049875621 8.786073574 0
0 0 0 8.786073574 0 0
0 0 0 0 0 0
0 0 0 0 0 0
that worked out
I talked myself out of it because I thought it was possible to have 0's where there are legit values
but that's not true
⎕←(1↑0=11○ps)×⌊⌿9○ps
 
@nathanrogers
VALUE ERROR
 
@nathanrogers 1↑‽ Don't you want to consider all three layers when deciding what to filter out?
 

« first day (665 days earlier)      last day (1982 days later) »