Group Abstract Group Abstract

Message Boards Message Boards

1
|
4.7K Views
|
2 Replies
|
2 Total Likes
View groups...
Share
Share this post:

Using AppendTo on function paramters?

Posted 9 years ago

Background, writing a function will take a list of {x,y} pairs and check that the first and last x-values of the list are 0 and 1. If not, then the list is fixed by adding points to the list. Then an interpolating function for the list is created. One constraint: would be best not to modify the original list.

Have tried a few iterations and settled on the following. My question is, how many copies of the list are being created with the code below. (I think 2) and is there a better alternative.

Thanks for your comments and suggestions.

Current implementation:

ClearAll[makeInterp, x1, x2, f1, f2];
makeInterp[ptsIn_List, intOrder_: 1] := Module[{ptsAll},
  ptsAll = ptsIn;
  If[ First[ptsAll][[1]] > 0, PrependTo[ptsAll, {0, First[ptsIn][[2]] }] ];
  If[ Last[ptsAll][[1]] < 1, AppendTo[ptsAll, {1, Last[ptsIn][[2]] }] ];
  Interpolation[ptsAll, InterpolationOrder -> intOrder]
  ]
x1 = {{0.1, 3}, {0.5, 5}, {0.7, 6} };
f1 = makeInterp[x1];

x2 = {{0, 0}, {0.1, 2}, {0.5, 8}, {0.7, 9}, {1, 8} };
f2 = makeInterp[x2];
Plot[{f1[x], f2[x]}, {x, 0, 1}] 

Is this code making two copies of the list? One copy when calling the function, which provides values for ptsIn; and one copy for ptsAll. I considered a few alternatives.

Alternative #1 -- operate directly on ptsIn. But this results in errors with PrependTo and AppendTo

makeInterp[ptsIn_, intOrder_: 1] := Module[{},
  If[ First[ptsIn][[1]] > 0, PrependTo[ptsIn, {0, First[ptList][[2]] }] ];
  If[ Last[ptsIn][[1]] < 1, AppendTo[ptsIn, {1, Last[ptList][[2]] }] ];
  Interpolation[ptsIn, InterpolationOrder -> intOrder]
  ]

Alternative #2 -- operate directly on ptsIn and use HoldFirst. This works, but it modifies the original list, which isn't a good idea.

ClearAll[makeInterp, x, f];
SetAttributes[makeInterp, {HoldFirst}] 
makeInterp[ptsIn_, intOrder_: 1] := Module[{},
  If[ First[ptsIn][[1]] > 0, PrependTo[ptsIn, {0, First[ptList][[2]] }] ];
  If[ Last[ptsIn][[1]] < 1, AppendTo[ptsIn, {1, Last[ptList][[2]] }] ];
  Interpolation[ptsIn, InterpolationOrder -> intOrder]
  ]
x = {{0.1, 3}, {0.5, 5}, {0.7, 6} };
f = makeInterp[x]
Plot[f[x], {x, 0, 1}]
x

Alternative #2A -- not sure why the following fails. Seems that cannot provide a pattern for the first argument, when using HoldFirst?

ClearAll[makeInterp, x, f];
SetAttributes[makeInterp, {HoldFirst}] 
makeInterp[ptsIn_List, intOrder_: 1] := Module[{},
  If[ First[ptsIn][[1]] > 0, PrependTo[ptsIn, {0, First[ptList][[2]] }] ];
  If[ Last[ptsIn][[1]] < 1, AppendTo[ptsIn, {1, Last[ptList][[2]] }] ];
  Interpolation[ptsIn, InterpolationOrder -> intOrder]
  ]
x = {{0.1, 3}, {0.5, 5}, {0.7, 6} };
f = makeInterp[x]
(*output:  makeInterp[x]*)
POSTED BY: Robert McHugh
2 Replies
Posted 9 years ago

Thanks Sander! Appreciate the recommendation. It is a big improvement.

makeInterp[ptsIn : {{0, _}, x___, {1, _}}, intOrder_Integer: 1] :=    Module[{},   
        Interpolation[ptsIn, InterpolationOrder -> intOrder]]
makeInterp[ptsIn : {{0, _}, x___}, intOrder_Integer: 1] :=    Module[{pEnd},   
        pEnd = {1, Last[ptsIn][[2]]}; 
        makeInterp[Append[ptsIn, pEnd], intOrder]]
makeInterp[ptsIn : {x___, {1, _}}, intOrder_Integer: 1] := Module[{pStart},
        pStart = {0, First[ptsIn][[2]]}; 
        makeInterp[Prepend[ptsIn, pStart], intOrder]]
makeInterp[ptsIn : {x___}, intOrder_Integer: 1] :=  Module[{pStart, pEnd},
       pStart = {0, First[ptsIn][[2]]}; 
       pEnd = {1, Last[ptsIn][[2]]}; 
       makeInterp[Append[Prepend[ptsIn, pStart], pEnd], intOrder]]
POSTED BY: Robert McHugh

The last one does not work because it will be symbolic x, and thus not be conform your List specification.

Why not use different function definitions (something like this):

ClearAll[makeInterp]
makeInterp[ptsIn:{{0,_},x___,{1,_}},intOrder_Integer: 1]:=Module[{},
   (* real deal here *)
]
makeInterp[ptsIn:{{0,_},x___},intOrder_Integer: 1]:=makeInterp[Append[ptsIn,{1,1}],intOrder]
makeInterp[ptsIn:{x___,{1,_}},intOrder_Integer: 1]:=makeInterp[Prepend[ptsIn,{0,0}],intOrder]
makeInterp[ptsIn:{x___},intOrder_Integer: 1]:=makeInterp[Append[Prepend[ptsIn,{0,0}],{1,1}],intOrder]

makeInterp[{{1,3},{2,4},{2,0}},2]
makeInterp[{{0,3},{2,4},{2,0}},2]
makeInterp[{{0,3},{2,4},{1,0}},2]
POSTED BY: Sander Huisman
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard