9
$\begingroup$

How can I express multiplication of an array and a matrix so that

{x, y, z}*{{10, 20, 30}, {0, 1, 2}}

gives

{{10 x, 20 y, 30 z}, {0, y, 2 z}}
$\endgroup$
2
  • 5
    $\begingroup$ {x, y, z}*# & /@ {{10, 20, 30}, {0, 1, 2}} $\endgroup$
    – Bob Hanlon
    Oct 9, 2019 at 17:23
  • 6
    $\begingroup$ A vectorized method is this: {{10, 20, 30}, {0, 1, 2}}.DiagonalMatrix[{x, y, z}] $\endgroup$ Oct 9, 2019 at 17:46

4 Answers 4

8
$\begingroup$

I think the answers given in the comments to the question deserves being on record as a formal answer.

  • Bob Hanlon
{x, y, z}*# & /@ {{10, 20, 30}, {0, 1, 2}} 
  • Henrik Schumacher
{{10, 20, 30}, {0, 1, 2}}.DiagonalMatrix[{x, y, z}]
  • user1066
Inner[Times, {{10, 20, 30}, {0, 1, 2}}, {x,y,z}, List]

EDIT: Comparing the timings:

Clear["Global`*"]

n = 20; r = 100;

var = Array[x, n];

mat = Array[m, {r, n}];

t[1] = AbsoluteTiming[prod[1] = var*# & /@ mat;][[1]]

(* 0.001768 *)

t[2] = AbsoluteTiming[prod[2] = mat.DiagonalMatrix[var];][[1]]

(* 0.027773 *)

t[3] = AbsoluteTiming[prod[3] = Inner[Times, mat, var, List];][[1]]

(* 0.001384 *)

Comparing the timings

(t /@ Range[3])/t[3]

(* {1.27746, 20.0672, 1.} *)

Verifying that the different approaches provide identical results.

Equal @@ (prod /@ Range[3])

(* True *)
$\endgroup$
4
  • $\begingroup$ Timing tests would be useful. If no one adds this before I have a chance, I will edit with them. $\endgroup$ Oct 9, 2019 at 20:26
  • $\begingroup$ You might want to compare on packed arrays of reals as well, but you will need to repack the diagonal matrix before using Dot. $\endgroup$
    – Carl Woll
    Oct 9, 2019 at 23:54
  • $\begingroup$ In addition {{10, 20, 30}, {0, 1, 2}}.DiagonalMatrix[{x,y,z}]==Inner[Times, {{10, 20, 30}, {0, 1, 2}}, {x,y,z}, List]==Inner[Times, {{10, 20, 30}, {0, 1, 2}}, DiagonalMatrix[{x,y,z}]] but timings may be important $\endgroup$
    – user1066
    Oct 10, 2019 at 3:28
  • $\begingroup$ m.DiagonalMatrix[v] == Inner[Times, m, DiagonalMatrix[v]] == Inner[Times, m, v, List], where m is matrix, v is vector $\endgroup$
    – user1066
    Oct 10, 2019 at 3:29
1
$\begingroup$
m = {{10, 20, 30}, {0, 1, 2}};

v = {x, y, z};

Using Threaded (new in 13.1}

m * Threaded[v]

{{10 x, 20 y, 30 z}, {0, y, 2 z}}

$\endgroup$
1
$\begingroup$
m = {{10, 20, 30}, {0, 1, 2}};

v = {x, y, z};

Using Cases:

Cases[m, x_ :> x*v]

(*{{10 x, 20 y, 30 z}, {0, y, 2 z}}*)

Or using MapThread:

MapThread[#1*#2 &, {Array[v &, Length@#], #} &@m]

(*{{10 x, 20 y, 30 z}, {0, y, 2 z}}*)
$\endgroup$
0
$\begingroup$

Perhaps something as simple as this, which can be more efficient for large elements:

(a*{b, c}) /. {a -> {x, y, z}, b -> {10, 20, 30}, c -> {0, 1, 2}}

(* {{10 x, 20 y, 30 z}, {0, y, 2 z}} *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.