6

I am trying to write a generic matrix valued function in a package, of the form:

f[matrix_] := Module[...]

My problem is that I want to accept any matrix, but always assume that the functions/variables contained within the matrix are real. I realise that I can set assumptions when doing calculations, but for this it seems that I need to know the functions or variables before hand in order to set the assumptions up. How can I tell mathematica that any element of the matrix should be assumed to be real?

For clarification, lets say I do f[{{x,x^2},{h[x],S[y]^2}}]. I want mathematica to assume that x, x^2, h[x] and S[y] are all functions only involving real numbers, so I don't get Conjugate(S[y]^2) type answers in the output of my function.

Akoben
  • 747
  • 4
  • 13

3 Answers3

4

Update: after clarification I propose

f[m_] := Block[{$Assumptions = Alternatives @@ Flatten@m ∈ Reals}, 
  Conjugate[m[[1, 1]]] // Simplify]

f[{{x, x^2}, {h[x], S[y]^2}}]
(* x *)

Previous test-based answer:

From the documentation of MatrixQ

Test if a matrix has real numeric entries:

MatrixQ[{{Pi, Sin[1]}, {Cos[2], E}}, Im[#] == 0 &]

Faster test for real-valued numbers:

MatrixQ[{{1, 2.}, {3/4, 5`20}}, NumberQ[#] && ! MatchQ[#, _Complex] &]

So you can use

real[m_ /; MatrixQ[m, Im[#] == 0 &]] := m

or

real[m_ /; MatrixQ[m, NumberQ[#] && ! MatchQ[#, _Complex] &]] := m

For big matrices the following will be considerably faster

ClearAll[real]
real[m_ /; MatrixQ[m] && Norm[Im[m], ∞] == 0] := m

real[RandomReal[1, {3000, 3000}]] // Head // AbsoluteTiming
(* {0.332791, List} *)

Note: My method accept complex arrays with zero imaginary part.

  • If you don't want to accept, use kguler's solution.
  • If you want to accept and get rid of the imaginary part just use Re[m] inside the function.
ybeltukov
  • 43,673
  • 5
  • 108
  • 212
  • I'm not dealing with numeric matrices, and I don't want to 'test' to see if it's real. I want Mathematica to assume that any functions inside the matrix are real, so I avoid Conjugate(function) etc. – Akoben Oct 05 '14 at 13:47
3
rmQ = MatrixQ[#, Internal`RealValuedNumericQ] &;

ClearAll[realB, real]
real[m_ /; MatrixQ[m] && Norm[Im[m], \[Infinity]] == 0] := m
realB[m_?rmQ] := m

real[RandomReal[1, {3000, 3000}]] // Head // AbsoluteTiming
(* {0.312443,List} *)
realB[RandomReal[1, {3000, 3000}]] // Head // AbsoluteTiming
(* {0.093755,List} *)

See also: How to check if an expression is a real-valued number

kglr
  • 394,356
  • 18
  • 477
  • 896
2

Maybe this will work for you.

 validNum = Except[_Complex, _?NumericQ];
 f[m : {{validNum ..} ..}] := m

f will accept a wide variety number forms but not complex numbers.

f[{{1, 2.}, {3/4, π}, {5, 6}}]
{{1, 2.}, {3/4, π}, {5, 6}}
f[{{1 + I, 2.}, {3/4, π}, {5, 6}}]
f[{{1 + I, 2.}, {3/4, π}, {5, 6}}]

Nor will it accept forms that are not matrix-like.

{f[], f[1], f[{1, 2, 3}], f[{{1, 2.}, π, {5, 6}}]}
{f[], f[1], f[{1, 2, 3}], f[{{1, 2.}, π, {5, 6}}]}

However, it does not care if the matrix rows are not all the same length.

 f[{{1, 2.}, {π}, {5, 6}}]
 {{1, 2.}, {π}, {5, 6}}
m_goldberg
  • 107,779
  • 16
  • 103
  • 257