Re: Compiling SingularValueDecomposition

• To: mathgroup at smc.vnet.net
• Subject: [mg89855] Re: Compiling SingularValueDecomposition
• From: Jean-Marc Gulliet <jeanmarc.gulliet at gmail.com>
• Date: Mon, 23 Jun 2008 02:45:32 -0400 (EDT)
• Organization: The Open University, Milton Keynes, UK
• References: <g3ihod\$fc9\$1@smc.vnet.net> <g3kunv\$7e2\$1@smc.vnet.net>

```Jean-Marc Gulliet wrote:

> Frank Hu wrote:
>> Hi, group,
>>
>> I'm trying to speed up a piece of code that uses
>> SingularValueDecomposition by compiling it.  But I couldn't get it to
>> compile.  For a simple demonstration, try
>>
>> fx=Compile[{{x, _Real, 2}},  SingularValueDecomposition[x],
>> {{SingularValueDecomposition, _Real, 3}}]
>>
>> and fx[[4]] is
>> {{1, 5}, {54, Function[{x}, SingularValueDecomposition[x]], 3, 2, 0,
>> 3, 2, 1}, {2}}
>>
>> The "Function" there tells fx wasn't compiled successfully.  Calling
>> fx[{{1., 2.}, {3., 4.}}] will generate the following warnings
>>
>> CompiledFunction::cfte: Compiled expression {<<1>>} should be a rank
>> 2 tensor of machine-size real numbers. >>
>> CompiledFunction::cfex: Could not complete external evaluation at
>> instruction 2; proceeding with uncompiled evaluation. >>
>
> Hi Frank,
>
> You must write the intermediate functions as full expressions, that is
> SingularValueDecomposition[_] rather than just
> SingularValueDecomposition. The following works as expected:
>
>
> In[1]:= fx = Compile[{{x, _Real, 2}}, SingularValueDecomposition[x],
>       {{SingularValueDecomposition[_], _Real, 3}}]
> fx[[4]]
> fx[{{1., 2.}, {3., 4.}}]
>
> Out[1]= CompiledFunction[]
>
> Out[2]= {{1, 5}, {54, Function[{x}, SingularValueDecomposition[x]], 3,
> 2, 0, 3,
>
>     3, 1}, {2}}
>
> Out[3]= {{{-0.404554, 0.914514}, {-0.914514, -0.404554}},
>
>    {{5.46499, 0.}, {0., 0.365966}},
>
>    {{-0.576048, -0.817416}, {-0.817416, 0.576048}}}

Note that the code above will failed to compiled when the input is not a
*square* matrix because Mathematica expects the returned value to be a
*full* array. (In a full array all parts at a particular level must be
lists of the same length.) When you feed the function fx with a
rectangular (non square) matrix, the result returned by
SingularValueDecomposition is a list of unequal-length elements.

In[1]:= fx = Compile[{{x, _Real, 2}},
SingularValueDecomposition[x],
{{SingularValueDecomposition[_], _Real, 3}}]
f1 = fx[{{1., 2.}, {3., 4.}}]
f2 = fx[{{1., 2.}, {3., 4.}, {5., 6.}}]
f3 = fx[{{1., 2., 3.}, {4., 5., 6.}}]
({ArrayDepth[#1], ArrayQ[#1]} & ) /@ {f1, f2, f3}

Out[1]= CompiledFunction[]

Out[2]= {{{-0.404554, 0.914514}, {-0.914514, -0.404554}},

{{5.46499, 0.}, {0., 0.365966}},

{{-0.576048, -0.817416}, {-0.817416, 0.576048}}}

During evaluation of In[1]:= CompiledFunction::cfte:Compiled expression
{<<1>>} should be a rank 3 tensor \
of machine-size real numbers. >>

During evaluation of In[1]:= CompiledFunction::cfex:Could not complete
external evaluation at instruction \
2; proceeding with uncompiled evaluation. >>

Out[3]= {{{-0.229848, 0.883461, 0.408248}, {-0.524745, 0.240782,
-0.816497},

{-0.819642, -0.401896, 0.408248}},

{{9.52552, 0.}, {0., 0.514301}, {0., 0.}},

{{-0.619629, -0.784894}, {-0.784894, 0.619629}}}

During evaluation of In[1]:= CompiledFunction::cfte:Compiled expression \
{{{-0.386318,-0.922366},{-0.922366,0.386318}},{{<<1>>},<<1>>},<<1>>}
should \
be a rank 3 tensor of machine-size real numbers. >>

During evaluation of In[1]:= CompiledFunction::cfex:Could not complete
external evaluation at instruction \
2; proceeding with uncompiled evaluation. >>

Out[4]= {{{-0.386318, -0.922366}, {-0.922366, 0.386318}},

{{9.50803, 0., 0.}, {0., 0.77287, 0.}},

{{-0.428667, 0.805964, 0.408248}, {-0.566307, 0.112382, -0.816497},

{-0.703947, -0.581199, 0.408248}}}

Out[5]= {{3, True}, {1, False}, {1, False}}

On the other hand, if we use a function such as SingularValueList, which
returns a one-dimensional vector, the compilation works with rectangular
inputs.

In[6]:= gx = Compile[{{x, _Real, 2}},
SingularValueList[x],
{{SingularValueList[_], _Real, 1}}]
g1 = gx[{{1., 2.}, {3., 4.}}]
g2 = gx[{{1., 2.}, {3., 4.}, {5., 6.}}]
g3 = gx[{{1., 2., 3.}, {4., 5., 6.}}]
({ArrayDepth[#1], ArrayQ[#1]} & ) /@ {g1, g2, g3}

Out[6]= CompiledFunction[]

Out[7]= {5.46499, 0.365966}

Out[8]= {9.52552, 0.514301}

Out[9]= {9.50803, 0.77287}

Out[10]= {{1, True}, {1, True}, {1, True}}

HTH,
-- Jean-Marc

```

• Prev by Date: Re: Mathematica performance improvements
• Next by Date: FullGraphics[] does not work properly
• Previous by thread: Re: Compiling SingularValueDecomposition
• Next by thread: Re: WorldPlot and excel data