Re: Defining N for a new entity

*To*: mathgroup at smc.vnet.net*Subject*: [mg66891] Re: Defining N for a new entity*From*: ab_def at prontomail.com*Date*: Fri, 2 Jun 2006 04:09:51 -0400 (EDT)*References*: <200605280103.VAA23345@smc.vnet.net><e5bsuq$afo$1@smc.vnet.net> <e5ei6d$800$1@smc.vnet.net> <e5h5p7$ero$1@smc.vnet.net>*Sender*: owner-wri-mathgroup at wolfram.com

Peter Pein wrote: > Giuseppe Bilotta schrieb: > > On Sun, 28 May 2006 10:10:34 +0000 (UTC), Carl K. Woll wrote: > > > >> Giuseppe Bilotta wrote: > >>> So I was looking for a way to tell Mathematica that applying N to an > >>> AffineExpression should only actually apply it to c and xi, something > >>> like > >>> > >>> N[AffineExpression[c_, dev_]] := > >>> AffineExpression[N[c], MapAt[N,#,{2}]&/@ dev] > >>> > >>> but if I actually do this and then call > >>> > >>> AffineExpression[1, {{1, 1}}] > >>> N[%] > >>> > >>> the Mathematica kernel (5.2.0.0) dies without any message. > >>> > >>> Does anybody have an idea of what could the reason be? And what could > >>> I do as a workaround? > >> One idea is to use the attribute NHoldRest (or if you change your data > >> structure, NHoldFirst). For example: > >> > >> SetAttributes[AffineExpression, NHoldRest] > >> > >> In[42]:= N[AffineExpression[.5, {{1, .2}, {2, .1}}]] > >> > >> Out[42]= AffineExpression[0.5, {{1, 0.2}, {2, 0.1}}] > > > > Thank you very much, this does the trick. It has the rather small > > side-effect of preventi N from working on the coefficients > > (N at AffineExpression[.5,{{1,Pi/6}}] will not numerize Pi/6), but it's > > good enough for my application. > > > > Do you have any ideas on why the Mathematica kernel dies without a > > message? > > > > Salute Giuseppe, > > just guessing... > > N[AffineExpression[c_,dev_]]:=... might evaluate the left hand side before applying SetDelayed. This is an explanation, why Mathematica doesn't complain about N being protected. > But N[AffineExpression[c_,dev_]] evaluates to AffineExpression[c_,dev_], leaving you with a hidden recursion: > > N[f[x_]]:=f[N[x]] > N[f[13]] (* choose your favourite unlucky number here *) > > reproduces the crash. > > If you don't want the NHoldRest-solution, you might try: > > In[1]:= > a1=AffineExpression[1,{{1,1},{2,Pi}}]; > > AffineExpression /: HoldPattern[N][AffineExpression[c_, dev_]] := > AffineExpression[N[c], MapAt[N, #, 2]& /@ dev] > > N[a1] > --> AffineExpression[1.,{{1,1.},{2,3.14159}}] > > Ciao, > Peter The definition N[f[x_]] := f[N[x]] is stored in NValues[f]. What seems to be happening is that N[f[1]] evaluates to f[1.] but then Mathematica looks up NValues for symbols on the next evaluation step as well, and an infinite loop results: N[f[x_]] := (Print[x]; f[N[x]]) /; NumericQ[x] && !MachineNumberQ[x] N[f[1]] (*works fine, no NValues for f[1.]*) Clear[f] N[f[x_]] := (Print[x]; g[N[x]]) N[g[x_]] := (Print[x]; h[N[x]]) N[f[1]] (*works fine, no NValues for h[1.]*) N[f[x_]] := (Print[x]; f[N[x]]) N[f[1]] (*infinite loop*) The definition for HoldPattern[N][f[x_]] is stored in UpValues[f], hence the difference. For AffineExpression we can do something like this: In[1]:= Attributes[AffineExpression] = NHoldAll; N[AffineExpression[c_, dev_]] := AffineExpression[N[c], MapAt[N, #, {2}]& /@ dev] /; dev =!= {} && MemberQ[ Prepend[dev[[All, 2]], c], _?(NumericQ[#] && !MachineNumberQ[#]&)] In[3]:= LinearSolve[{{1.}}, {AffineExpression[1, {{2, 3}, {4, 5}}]}] Out[3]= {1.*AffineExpression[1., {{2, 3.}, {4, 5.}}]} NHoldAll is needed to prevent the application of the built-in rules for N. Maxim Rytin m.r at inbox.ru