www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Basic Linear Algebra and D's Array Operation

reply Andrew Edwards <edwards.ac gmail.com> writes:
Sooo... I'm trying to learn this stuff so that I can fully grasp 
the content of Jens Mueller's 2019 DConf talk and its 
applications in financial sector (forex and options/futures 
trading). Unfortunately, I'm doing so using python but I'd like 
to accomplish the same in D. Here goes:

Array (Vector) Algebra

	auto V = [1, 2, 3];
	auto v = V[] * 4; // v == [4, 8, 12]

Output:
	Error: array operation V[] * 4 without destination memory not 
allowed

Huh? What? That makes no sense, but okay... whatever.

	int[3] v = V[] * 4; // v == [4, 8, 12]
	v[] = v[] + v[]; // v == [8, 16, 24]
	v[] = v[] / 2; // v == [4, 8, 12]
	v[] = v[] - v[]; // v = [0, 0, 0]

so far so good. On to the fun stuff.

Multidimensional Array (Matrix) Algebra

	auto M = [[1, 2, 3], [1, 2, 3], [1,2,3]];
	int[3][3] m = M[] * 4;
	
Output:
	Error: incompatible types for (M[]) * (4): int[][] and int

Okay, I'm lost on that one. But let's press on.

	int[3][3] m = M[] * [[4]];

Output:
	Error: cannot implicitly convert expression M[] * [[4]] of type 
int[][] to int[]

	int[3][3] m = M[] * [[4,4,4], [4,4,4], [4,4,4]];

Output:
	Error: cannot implicitly convert expression M[] * [[4, 4, 4], 
[4, 4, 4], [4, 4, 4]] of type int[][] to int[]

I'm so confused. Maybe it's the way I'm accessing M?

	int[3][3] m = M[][] * 4;

Output:
	Error: incompatible types for (M[]) * (4): int[][] and int

And... it begins again!!!

So the question is, how do I pull this off in D using just 
builtin arrays and phobos?

Any assistance is appreciated.

Thanks,
Andrew

P.S. Why do we still have two sets of documentations ([1],[2]) 
for the language? Which is the official one and when can we get 
rid of the other?

[1] https://dlang.org/library/std/array.html
[2] https://dlang.org/phobos/std_array.html
May 18 2019
next sibling parent reply Alex <sascha.orlov gmail.com> writes:
On Sunday, 19 May 2019 at 06:34:18 UTC, Andrew Edwards wrote:
 Sooo... I'm trying to learn this stuff so that I can fully 
 grasp the content of Jens Mueller's 2019 DConf talk and its 
 applications in financial sector (forex and options/futures 
 trading). Unfortunately, I'm doing so using python but I'd like 
 to accomplish the same in D. Here goes:

 Array (Vector) Algebra

 	auto V = [1, 2, 3];
 	auto v = V[] * 4; // v == [4, 8, 12]

 Output:
 	Error: array operation V[] * 4 without destination memory not 
 allowed

 Huh? What? That makes no sense, but okay... whatever.

 	int[3] v = V[] * 4; // v == [4, 8, 12]
 	v[] = v[] + v[]; // v == [8, 16, 24]
 	v[] = v[] / 2; // v == [4, 8, 12]
 	v[] = v[] - v[]; // v = [0, 0, 0]

 so far so good. On to the fun stuff.

 Multidimensional Array (Matrix) Algebra

 	auto M = [[1, 2, 3], [1, 2, 3], [1,2,3]];
 	int[3][3] m = M[] * 4;
 	
 Output:
 	Error: incompatible types for (M[]) * (4): int[][] and int

 Okay, I'm lost on that one. But let's press on.

 	int[3][3] m = M[] * [[4]];

 Output:
 	Error: cannot implicitly convert expression M[] * [[4]] of 
 type int[][] to int[]

 	int[3][3] m = M[] * [[4,4,4], [4,4,4], [4,4,4]];

 Output:
 	Error: cannot implicitly convert expression M[] * [[4, 4, 4], 
 [4, 4, 4], [4, 4, 4]] of type int[][] to int[]

 I'm so confused. Maybe it's the way I'm accessing M?

 	int[3][3] m = M[][] * 4;

 Output:
 	Error: incompatible types for (M[]) * (4): int[][] and int

 And... it begins again!!!

 So the question is, how do I pull this off in D using just 
 builtin arrays and phobos?

 Any assistance is appreciated.
Matrix operations are a pain in D. This is due to static arrays and dynamic arrays are different types and don't mix a priori: https://dlang.org/spec/arrays.html Slice operations exist, but they are defined mainly for arrays and not for arrays of arrays. Some basic operations (like setting) are possible, but as you see, even multiplication fails. You could reinvent something like ´´´ import std; void main() { int[][] M = [[1,2,3],[1,2,3],[1,2,3]]; M.recursiveMultiplier(4); writeln(M); } void recursiveMultiplier(T, V)(T arr, V val) nogc { static if(isArray!(ElementType!T)) arr.each!(el => el.recursiveMultiplier(val)); else arr[] = arr[] * val; } ´´´ BUT: As I saw, in the talk, NDarrays are referenced. The common (widely used and recommended) way to use this functionality in D is by using mir.ndslices. http://docs.algorithm.dlang.io/latest/mir_ndslice.html
 Thanks,
 Andrew

 P.S. Why do we still have two sets of documentations ([1],[2]) 
 for the language? Which is the official one and when can we get 
 rid of the other?

 [1] https://dlang.org/library/std/array.html
 [2] https://dlang.org/phobos/std_array.html
May 19 2019
parent reply Andrew Edwards <edwards.ac gmail.com> writes:
On Sunday, 19 May 2019 at 10:07:35 UTC, Alex wrote:
 On Sunday, 19 May 2019 at 06:34:18 UTC, Andrew Edwards wrote:
 So the question is, how do I pull this off in D using just 
 builtin arrays and phobos?

 Any assistance is appreciated.
Slice operations exist, but they are defined mainly for arrays and not for arrays of arrays. Some basic operations (like setting) are possible, but as you see, even multiplication fails. You could reinvent something like ´´´ import std; void main() { int[][] M = [[1,2,3],[1,2,3],[1,2,3]]; M.recursiveMultiplier(4); writeln(M); } void recursiveMultiplier(T, V)(T arr, V val) nogc { static if(isArray!(ElementType!T)) arr.each!(el => el.recursiveMultiplier(val)); else arr[] = arr[] * val; } ´´´
Can you do me a favor and extend it to cover the cases where V is either an array or multidimensional array? The text I'm using has exercise to implement a bunch of matrix operations so that would help out a lot.
 BUT:
 As I saw, in the talk, NDarrays are referenced. The common 
 (widely used and recommended) way to use this functionality in 
 D is by using mir.ndslices.
 http://docs.algorithm.dlang.io/latest/mir_ndslice.html
Yes, I'm aware. I'm actually am using Lubeck to accomplish much of this stuff but when it comes to the implementation exercises, I have to ditch the library and stick with vanilla D.
May 19 2019
parent reply Alex <sascha.orlov gmail.com> writes:
On Sunday, 19 May 2019 at 16:17:17 UTC, Andrew Edwards wrote:
 ´´´
 import std;

 void main()
 {
     int[][] M = [[1,2,3],[1,2,3],[1,2,3]];
     M.recursiveMultiplier(4);
     writeln(M);
 }

 void recursiveMultiplier(T, V)(T arr, V val)  nogc
 {
     static if(isArray!(ElementType!T))
         arr.each!(el => el.recursiveMultiplier(val));
     else
         arr[] = arr[] * val;
 }
 ´´´
Can you do me a favor and extend it to cover the cases where V is either an array or multidimensional array? The text I'm using has exercise to implement a bunch of matrix operations so that would help out a lot.
Not really. For a general matrix-matrix multiplication special algorithms exist. ndslices use blas for calculation. For different numeric types, things get involved very fast, not to speak about special algorithms for special-formed matrices. And I don't even know, which representation (row/column major) you expect ;) The operation itself is, however, a simple one. To implement a basic version I would cite http://rosettacode.org/wiki/Matrix_multiplication#D
May 19 2019
parent Andrew Edwards <edwards.ac gmail.com> writes:
On Sunday, 19 May 2019 at 17:13:11 UTC, Alex wrote:
 The operation itself is, however, a simple one. To implement a 
 basic version I would cite
 http://rosettacode.org/wiki/Matrix_multiplication#D
This is awesome. Thank you very much. Andrew
May 19 2019
prev sibling parent James Blachly <james.blachly gmail.com> writes:
On 5/19/19 2:34 AM, Andrew Edwards wrote:
 P.S. Why do we still have two sets of documentations ([1],[2]) for the 
 language? Which is the official one and when can we get rid of the other?
 
 [1] https://dlang.org/library/std/array.html
 [2] https://dlang.org/phobos/std_array.html
I have wondered this myself -- anyone?
May 19 2019