These are chat archives for libmir/public

16th
May 2016
Adam Stiff
@aestiff
May 16 2016 15:39
Hi -- hope this is an appropriate place to ask: are there plans to support any binary operators for compatible Slice types?
Ilya Yaroshenko
@9il
May 16 2016 15:50
Could you please write an example? I don’t understand the question :-/
Sebastian Wilzbach
@wilzbach
May 16 2016 15:54
@aestiff means &, | if supported
Ilya Yaroshenko
@9il
May 16 2016 15:57
They don’t work now?
Adam Stiff
@aestiff
May 16 2016 15:59
No, sorry, I mean +, -, etc. Currently I'm only able to use +=. Although I'm still using std.experimental.ndslice, are they supported in the development version?
Ilya Yaroshenko
@9il
May 16 2016 16:03
Example please! someSlice[] += 5 works
Oh, I understand
Adam Stiff
@aestiff
May 16 2016 16:04
What I'm looking for would be something like
auto a = 4.iota.sliced(2,2);
auto b = 4.iota.sliced(2,2);
auto c = a + b;
Sebastian Wilzbach
@wilzbach
May 16 2016 16:05
@9il didn't you want to avoid overloading mul, div to avoid confusion and make it explicit?
Ilya Yaroshenko
@9il
May 16 2016 16:05
No, this operations would not be supported in ndslice and Phobos.
@wilzbach No, just avoid allocations.
Sebastian Wilzbach
@wilzbach
May 16 2016 16:06
We should definitely put this into the docs then
Adam Stiff
@aestiff
May 16 2016 16:07
I'm trying to write an expression within a map!(), so I'm not quite sure how to do the allocation in that context (I'm fairly new to D generally).
Sebastian Wilzbach
@wilzbach
May 16 2016 16:08
@aestiff dupand each might work
Ilya Yaroshenko
@9il
May 16 2016 16:08
@wilzbach dup ?
Adam Stiff
@aestiff
May 16 2016 16:09
Object.dup or is there a template I'm not aware of?
I've tried Object.dup and it didn't compile.
Ilya Yaroshenko
@9il
May 16 2016 16:09
You can use slice function from Mir or Phobos github master
Sebastian Wilzbach
@wilzbach
May 16 2016 16:10
Oh sorry - It's slice or makeSlice for the Allocator api
Adam Stiff
@aestiff
May 16 2016 16:11
Oh! Perfect. Sorry I missed that.
Ilya Yaroshenko
@9il
May 16 2016 16:12
You are welcome :)
Sebastian Wilzbach
@wilzbach
May 16 2016 16:12
@aestiff it's not part of the official documentation, because it's only in master
Adam Stiff
@aestiff
May 16 2016 16:12
Oh, good to know. Now I'll definitely have to switch to the dev version.
Ilya Yaroshenko
@9il
May 16 2016 16:12
@aestiff will be released in DMD 2.072
or you can use mir instead
Sebastian Wilzbach
@wilzbach
May 16 2016 16:13
You can browse the docs for ndslice in mir here: http://docs.mir.dlang.io/latest/mir_ndslice.html
(ndslice is hidden from the mir documentation because it will be part of Phobos soon)
Adam Stiff
@aestiff
May 16 2016 16:14
Hey I'd like to help you guys with Mir if I can. I definitely don't trust myself writing low-level code yet, but if you need testing or documentation I might have some time this summer.
I'm working on an application that needs a lot of non-uniform random sampling, so I'd like to test that out as soon as it's available.
Sebastian Wilzbach
@wilzbach
May 16 2016 16:16
@aestiff highly appreciated! Yes just using Mir and pointing out missing features is great
Adam Stiff
@aestiff
May 16 2016 16:17
Then I'll continue to do that.
Sebastian Wilzbach
@wilzbach
May 16 2016 16:17
Have you seen our issue tracker already? It's mostly about implementation, but improving the docs is also an important milestone
Ilya Yaroshenko
@9il
May 16 2016 16:17
@aestiff This would be very helpful for Mir ) Also we have only one article about ndslice. When we relese BLAS for ndslice and non-uniform RNGs it would be awesome to have a small article in a blog
or article about your expirience
Adam Stiff
@aestiff
May 16 2016 16:19
Great, well I'll be happy to try things out and write about it.
Sebastian Wilzbach
@wilzbach
May 16 2016 16:19
Btw I have reserved the mir.rocks domain and we plan to put there tutorials to get started etc.
If you have ideas for that, see this libmir/mir.rocks#3 ;-)
And yes I will start to work on mir.random next week, so I hope you have something to play with soon.
Adam Stiff
@aestiff
May 16 2016 16:23
Excellent. Looking forward to that.
Adam Stiff
@aestiff
May 16 2016 18:20

Hi again,
so, going back to binary operators, I realized that it might not be necessary to do an allocation, at least for simple element-wise operations like matrix sum (which I say having no idea what an actual implementation might look like). But I can do something like this:

auto a = 4.iota.sliced(2,2);
auto b = 4.iota.sliced(2,2);
auto c = zip(a.joiner, b.joiner).map!(a[0] + a[1])

which gives me the expected range of (I believe lazily-evaluated) elements. The only problem arises when I try to re-slice c, since its type isn't compatible with sliced() unless it's allocated. BUT, presumably, if this were all wrapped neatly inside of an opBinary!("+")(...), the implementation would have access to element types and whatnot and be able to safely cast the result accordingly (in the above example, back to a Slice!(2,int*)).
Again, I'm new to this, so I don't know if this is a dumb suggestion or how difficult it might be to implement. I can certainly just do the allocation for my application, but I thought I'd share the idea.

Ilya Yaroshenko
@9il
May 16 2016 18:25
a.byElement.map!”a+b” + b.byElement.map!"a+b"
or join(a.byElement, b.byElement).map!"a+b"
Sebastian Wilzbach
@wilzbach
May 16 2016 18:26
@9il couldn't we support opBinary for the ByElement struct?
Ilya Yaroshenko
@9il
May 16 2016 18:26
But common loops would be a little bit faster
@wilzbach Use case please
Sebastian Wilzbach
@wilzbach
May 16 2016 18:27
a.byElement + 3
Ilya Yaroshenko
@9il
May 16 2016 18:28
and what result you expect from that expression?
Adam Stiff
@aestiff
May 16 2016 18:29
A slice of type matching a
Sebastian Wilzbach
@wilzbach
May 16 2016 18:29
(iotaSlice(2,2).byElement + 3).equal(3.iota(7))
Ilya Yaroshenko
@9il
May 16 2016 18:30
auto a = iotaSlice(2, 2);
auto b = iotaSlice(2, 2);
auto c = slice!double(a.shape);
c[] = a;
c[] += b;
Sebastian Wilzbach
@wilzbach
May 16 2016 18:31
@9il fair enough - you are right!
btw if we already talk about map, did you had time to play with your idea for multi-dimensional folding (#209)?
Adam Stiff
@aestiff
May 16 2016 18:33
yeah but (as far as I know) it's really messy to do that allocation in the middle of a lambda, where you'd have to declare delegate return types and such.
Ilya Yaroshenko
@9il
May 16 2016 18:33
@aestiff Multidiensional folding with multiple slices is no implemented yet, so please use loops or byElement. Will be added after BLAS
@wilzbach I am working on BLAS now and have not time for folding
Sebastian Wilzbach
@wilzbach
May 16 2016 18:34
@9il just read it - sorry ;-)
@aestiff why middle of a lambda? Is your real example more complex?
Ilya Yaroshenko
@9il
May 16 2016 18:35
@aestiff +1, I don’t understand the your question
Adam Stiff
@aestiff
May 16 2016 18:36
I'm calculating a large-ish matrix of bivariate gaussian products
  // 1/(sqrt(det(2pi*(S1+S2)))) * exp ^ (-1/2 * (m1 - m2)^T*(S1 - S2)^-1*(m1-m2))                       
    auto scales = unitClass                                                                             
    .map!(pre => unitClass                                                                              
          .map!(post => numLayers.iota                                                                  
                .map!(layer =>                                                                          
                      (1 / (sqrt(det(zip(axon_classLayerCov[pre, layer].joiner,                         
                                         dend_classLayerCov[post, layer].joiner)                        
                                     .map!("a[0] + a[1]")                                               
                                     .array                                                             
                                     .sliced(2,2)                                                       
                                      ))))                                                              
                      )));
Sebastian Wilzbach
@wilzbach
May 16 2016 18:41
This message was deleted
Ilya Yaroshenko
@9il
May 16 2016 18:41
This should be lazy?
Adam Stiff
@aestiff
May 16 2016 18:41
I guess it's a tensor, not a matrix. And without the variable declarations the code probably is not much help.
I can definitely do it with plain old for loops.
Ilya Yaroshenko
@9il
May 16 2016 18:42
In your code it is 3D lazy range composed of memory allocated 2D slices
Adam Stiff
@aestiff
May 16 2016 18:42
Yeah, but I intend to continue using the results later. Performance isn't an issue, I'm just trying to really understand how to use the ranges.
Ilya Yaroshenko
@9il
May 16 2016 18:42
5D after all
Do you want to use ranges or slices?
Adam Stiff
@aestiff
May 16 2016 18:43
Aren't slices ranges?
Ilya Yaroshenko
@9il
May 16 2016 18:43
Slices are ranges. But ranges are not slices
Sebastian Wilzbach
@wilzbach
May 16 2016 18:43
This message was deleted
Ilya Yaroshenko
@9il
May 16 2016 18:44
the result of map is not a slice
Adam Stiff
@aestiff
May 16 2016 18:44
That could be the main issue I'm facing.
Ilya Yaroshenko
@9il
May 16 2016 18:46
The same for zip and others.
Adam Stiff
@aestiff
May 16 2016 18:48
Right. OK. So I probably need to pause and reconsider how I think everything should work together. In any event, thank you for taking a minute to clarify.
Sebastian Wilzbach
@wilzbach
May 16 2016 18:52
I don't know exactly what variables you have, but shouldn't something like this work (=loops)?
foreach (ref scale; scales)
    foreach (numLayers; scale)
        foreach (ref layer; numLayers.iota)
        {
            auto S12 = S1.slice;
            S12[] -= S2;
            auto t = exp ^^ (-1/2 * (m1 - m2)^^T*(S12)^^-1*(m1-m2));
            S12[] = S1;
            S12[] += S2;
            S12[] *= 2pi;
            auto d = det(S12);
            // do something with 1 / sqrt(d) * t;
        }
Ilya Yaroshenko
@9il
May 16 2016 18:54
what is S1, m1, m2?
Sebastian Wilzbach
@wilzbach
May 16 2016 18:56
@9il I don't know, was just to show the style.
@aestiff can you clarify?
Adam Stiff
@aestiff
May 16 2016 19:50
For what it's worth, S1, S2 are 2x2 covariance matrices (like I said, allocation is not a big deal, this is mostly an exercise for me to see how far I can push this style). m1, m2 are 1x2 points in a plane (means). The product of two bivariate normal distributions N(m1,S1) x N(m2,S2) = c3 * N(m3, S3). I'm calculating a tensor of c3 for every combination of hundreds of distributions. Slices of that tensor will later be used (along with other things) as a probability for a discrete random sample. It seemed like I ought to be able to defer any allocation up until that sampling step. If not, it's really not a big deal with respect to my application, because performance is not very important.
However, I've found the lack of binary operators a bit un-intuitive. And @9il since you said the main reason for not wanting to implement them was to avoid allocation, that was my initial motivation for thinking of how to implement the element-wise operations without doing any allocation.
I do appreciate that it might be a pain or otherwise a distraction.