6
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ Maybe real[m : {{__Real} ..}] := m * 10 $\endgroup$ – eldo Oct 5 '14 at 12:24
  • $\begingroup$ This is why you should put more effort in asking clear questions from the get go. $\endgroup$ – RunnyKine Oct 5 '14 at 13:57
  • $\begingroup$ I thought it was quite clear, but obviously not! What was unclear @RunnyKine? $\endgroup$ – Akoben Oct 5 '14 at 13:58
  • $\begingroup$ I just meant your clarification would have been nice from the beginning. $\endgroup$ – RunnyKine Oct 5 '14 at 14:02
4
$\begingroup$

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.
$\endgroup$
  • $\begingroup$ 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. $\endgroup$ – Akoben Oct 5 '14 at 13:47
3
$\begingroup$
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

$\endgroup$
2
$\begingroup$

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}}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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