This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-07-01
Channels
- # beginners (10)
- # cljs-dev (33)
- # cljsjs (4)
- # cljsrn (12)
- # clojure (39)
- # clojure-belgium (2)
- # clojure-russia (80)
- # clojure-spec (9)
- # clojure-uk (6)
- # clojurescript (22)
- # core-async (141)
- # cursive (2)
- # datomic (20)
- # devops (1)
- # emacs (20)
- # hoplon (1)
- # jobs (3)
- # lambdaisland (12)
- # leiningen (3)
- # lumo (44)
- # onyx (2)
- # pedestal (1)
- # quil (1)
- # re-frame (9)
- # reagent (4)
- # robots (1)
- # rum (3)
- # spacemacs (5)
- # uncomplicate (80)
- # untangled (46)
- # yada (2)
I tried to post a question on https://groups.google.com/forum/#!forum/uncomplicate but it did not seem to go through. So I will ask it here. I have been following along with the linear algebra refresher posts - but also tried to use neantherthal to solve the systems of linear equations (using sv!
). And the answers were different from those in the book. I found that by changing the order of the rows I could get the right answer. I first thought this was because of the underlying lapack implementation but when I used python numpy I always got the same answer as the book independent of the order of the rows.
@rrottier You swapped the variables instead of the equations in your second example, because you forgot that the default matrix layout is column-oriented. Here's what you intended to do (the answer is also what you'd expect):
Now, maybe it is inconvenient to you to work with this "rotated" perspective. No problem, just add the option {:order :row}
to dge
and the matrix will be row-oriented:
(let [cs (dge 3 1 [0 8 16] {:order :row})]
(sv! (dge 3 3 [1 1 -1
4 0 1
0 4 1]
{:order :row})
cs)
cs)
=> #RealGEMatrix[double, mxn:3x1, order:row, offset:0, ld:1]
1.00
3.00
4.00
@blueberry Thanks. I did not realise the default matrix layout is column oriented. Thanks for pointing that out.
Is this a property of the underlying lapack or is it a neantherthal design decision?
@rrottier It's like the parentheses - after a few hours, you will not notice it :) BTW. matrix string prints out that information, and if I remember well, I mention it quite a few times in the tutorials. Please do this kind of feedback, and, if possible, suggest how to make it more obvious.
PS. Do I really need to specify {:order :row}
on (dge 3 1 ...)
? It seems like as it is only one column the orientation should be obvious.
Yeah #RealGEMatrix[double, mxn:3x1, order:column, offset:0, ld:3]
I did not really parse the type signature, was too focussed on the values 😊
Both LAPACK and neanderthal handle both, but column is the default in literature. In lapack, column is the only option for some operations, but neanderthal finds a way to provide roe even in most of these cases.
“column is the default in literature” I thought that row is the default in literature.
You need it even for 3x1 because the LAPACK solver requires matching layout for both matrices.
At least the literature that i read for systems of linear equations always represent the 2x + 3y + 4z
as [2 3 4]
I thought functional programming’s promise is: “You can write it just like the math”
Neanderthal also supports rows and columns. It's just about the default order, and does not have anything to do with floating point precision. In computing, a*b is not always equal to b*a.
I think I just stumbled into the column orientation with the mm
function as well. I tried to mutiply:
(dge 2 2 [1 2 3 4])
with (dge 2 1 [1 2])
and got a dimension error. Does that make sense?
I could also implement such castings, but that is something i want to avoid since it can shoot you in the foot when you need performance.
that does not ave anything to do with order. 2x1 * 2x2 is not allowed by math rules
RE: The castings - the way you do it is probably better, I agree that you want to be transparent to the underlying implementation. It is just confusing coming form another abstraction
but if the matrix is column oriented, it transfers the 1d vector [1 2 3 4] into columns.
Ok, I think I understand where all my issues are coming from… I just need to change the way I think about it.
you probably do not need to change the way you think about it, you just need to be aware of a few etails.
But I get the reasons - in haskell I started playing with dense
which uses the same kind of abstraction.
What I want, is to lay AA in memory in a way that is efficient, but still easy to work with. Obviously, those two dimensions have to be projected into one. But how? Should it be [1112|2313|1−1−2−6][1112|2313|1−1−2−6], or [121|13−1|11−2|23−6][121|13−1|11−2|23−6]? The answer is: it depends on how your algorithm accesses it most often. Neanderthal gives you both options. When you create any kind of matrix, you can specify whether you want it to be column-oriented (:column, which is the default), or row-oriented (:row). In the following example, we will use CPU matrices from the native namespace. The same options also work for functions that create GPU CUDA matrices (cuda namespace), or OpenCL's GPU and CPU matrices (opencl namespace).