3

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.

Anixx
  • 3,585
  • 1
  • 20
  • 32

1 Answers1

6

$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]. )

xzczd
  • 65,995
  • 9
  • 163
  • 468