3
$\begingroup$

The following code implements matrix arithmetic:

Clear["Global`*"]
Unprotect[Power];
Power[0, 0] = 1;
Protect[Power];
Unprotect[Dot];
Dot[x_?NumberQ, y_] := x y;
Protect[Dot];
Matrix /: Matrix[x_?MatrixQ] := 
  First[First[x]] /; x == First[First[x]] IdentityMatrix[Length[x]];
Matrix /: Dot[Matrix[x_], Matrix[y_]] := Matrix[x . y];
Matrix /: Matrix[x_] + Matrix[y_] := Matrix[x + y];
Matrix /: x_?(Head[#] != Matrix &) + Matrix[y_] := 
  Matrix[x IdentityMatrix[Length[y]] + y];
Matrix /: x_?NumericQ  Matrix[y_] := Matrix[x y];
Matrix /: Matrix[x_]*Matrix[y_] := Matrix[x . y] /; x . y == y . x;
Matrix /: Power[Matrix[x_ ?MatrixQ], y_?NumericQ ] := 
  Matrix[MatrixPower[x, y]];
Matrix /: Power[Matrix[x_?MatrixQ], Matrix[y_?MatrixQ]] := 
  Exp[Matrix[y] . Log[Matrix[x]]];
Matrix /: Im[Matrix[x_?MatrixQ]] := Matrix[Im[x]];
Matrix /: Re[Matrix[x_?MatrixQ]] := Matrix[Re[x]];
Matrix /: Arg[Matrix[x_?MatrixQ]] := Matrix[Arg[x]];
Matrix /: Dot[Matrix[A_?SquareMatrixQ], Matrix[B_?SquareMatrixQ]] := 
 Matrix[KroneckerProduct[A, 
    IdentityMatrix[LCM[Length[A], Length[B]]/Length[A]]] . 
   KroneckerProduct[B, 
    IdentityMatrix[LCM[Length[A], Length[B]]/Length[B]]]]

$Post = FullSimplify[# /. 
f_[args1___?NumericQ, Matrix[mat_], args2___?NumericQ] :> 
 Matrix[MatrixFunction[f[args1, #, args2] &, mat]]] &;

But the output gives expressions like Matrix[{{0,1/2},{1/2,0}}]. How can I format output to MatrixForm? Adding the line $PrePrint=MatrixForm does not help.

$\endgroup$
1

1 Answer 1

6
$\begingroup$

$PrePrint = MatrixForm won't help because MatrixForm only has effect on expression whose outermost head is List, it doesn't penetrate into inner sub-expressions. A simpler example illustrating the issue:

MatrixForm[aaa[{{1, 2}, {4, 6}}]]

enter image description here

If you just need to make Matrix[…] display as a 2D matrix in traditional math notation,

$PrePrint = (# /. Matrix -> MatrixForm)&;

or

Format@Matrix[a_] := MatrixForm@a

will be enough. But as we all know, one of the advantage of Mathematica notebook is, output in notebook can be directly edited and used as input, while the definition in $PrePrint ruins it. So here's an advanced solution:

$PrePrint =.; FormatValues@Matrix = {};
MakeBoxes[Matrix[a_?MatrixQ], StandardForm] ^:= 
 With[{box = 
    GridBox[Map[MakeBoxes, a, {2}], RowSpacings -> 1, ColumnSpacings -> 1, 
     RowAlignments -> Baseline, ColumnAlignments -> Center]},
    TemplateBox[{box}, "Matrix", 
   DisplayFunction -> (RowBox@{"[", "\[NoBreak]", #, "\[NoBreak]", "]"} &)]]

The advantage of this advanced solution is, it works with the shortcut Ctrl+Shift+i and Ctrl+Shift+n, and the 2D form of Matrix[…] is still editable:

enter image description here

You cannot achieve these with $PrePrint or Format!

Based on the knowledge obtained here, the following is a more advanced but shorter and more general solution:

$PrePrint =.; FormatValues@Matrix = {};
MakeBoxes[Matrix[a_], StandardForm] ^:= 
    Block[{Internal`$ConvertForms = {}}, 
  TemplateBox[{MakeBoxes[MatrixForm@a][[1, 1, 3]]}, "Matrix", 
   DisplayFunction -> (RowBox@{"[", "\[NoBreak]", #, "\[NoBreak]", "]"} &)]]

You can further customize the notation for matrix using StyleBox:

$PrePrint =.; FormatValues@Matrix = {};
Hold[MakeBoxes[Matrix[a_], StandardForm] ^:= 
    Block[{Internal`$ConvertForms = {}}, 
     TemplateBox[{MakeBoxes[MatrixForm@a][[1, 1, 3]]}, "Matrix", 
      DisplayFunction -> (RowBox@{style@"[", "\[NoBreak]", #, "\[NoBreak]", 
           style@"]"} &)]]] /. 
  style[string_] -> StyleBox[string, FontColor -> Blue] // ReleaseHold

Notice I've used the Hold & ReleaseHold technique to generate the code, because things like StyleBox[#, FontColor -> Blue] & simply doesn't work. Even changing style[string_] -> to style[string_] :> will break the code, because the Blue cannot be interpreted. (When using ->, Blue will evaluate to RGBColor[0, 0, 1]. )

$\endgroup$
3
  • $\begingroup$ Is there a way to make the brackets in another color (say, red)? $\endgroup$
    – Anixx
    Nov 8, 2022 at 18:38
  • 1
    $\begingroup$ @Anixx Of course, see my edit. $\endgroup$
    – xzczd
    Nov 9, 2022 at 2:31
  • $\begingroup$ This is working very well! I am thinking now, what other matrix functions I can add to this code. $\endgroup$
    – Anixx
    Nov 15, 2022 at 11:06

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.