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

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
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
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard