  | 
  
Well, here is the Maple code for the basics on the gasket for your viewing pleasure:  
  
> 
#this procedure generates all words of length m in L letters... 
 
p:=proc(L,m) 
option remember; 
local L1; 
  if m = 1 then L 
  else 
    L1 := p(L,m-1); 
    [op(map(add_one,L1,0)),op(map(add_one,L1,1)),op(map(add_one,L1,2))] 
  fi; 
end;
 
> 
add_one:=(u,d)-> [op(u),d];
 
> 
#This function returns all vertices in Vm in a big list 
vertices:= proc(m) 
 
local i,outlist; 
option remember; 
 
if m = 1 then RETURN([[0],[1],[2],[0,1],[0,2],[1,2]]) fi; 
if m=2 then  
[[0],[1],[2],[0,1],[0,2],[1,2],[0,0,1],[0,0,2],[0,1,2],[1,0,1],[1,0,2],[1,1,2],[2,0,1],[2,0,2],[2,1,2]]; else  
   outlist:=[[0] , [1] , [2] , [0,1], [0,2], [1,2]]; 
   for i from 2 to m do 
      outlist:=[op(outlist),op(map(add_pair, p([[0],[1],[2]], (i-1)), [0,1])), op(map(add_pair, p([[0],[1],[2]], (i-1)), [0,2])),       op(map(add_pair, p([[0],[1],[2]], (i-1)), [1,2]))]; 
   od; 
   outlist;  
 
     
#[[0] , [1] , [2] , [0,1], [0,2], [1,2], op(map(add_pair, p([[0],[1],[2]], (m-1)), [0,1])), op(map(add_pair, p([[0],[1],[2]], (m-1)), [0,2])),       op(map(add_pair, p([[0],[1],[2]], (m-1)), [1,2]))]; 
fi; 
end; 
 
#vertices_m creates just the vertices in Vm, excluding Vk, k<m... 
vertices_m:=proc(m) 
 
option remember; 
if m = 0 then RETURN([[0],[1],[2]]);fi; 
if m = 1 then RETURN([[0,1],[0,2],[1,2]]);fi; 
if m > 1 then [op(map(add_pair, p([[0],[1],[2]], (m-1)), [0,1])), op(map(add_pair, p([[0],[1],[2]], (m-1)), [0,2])),       op(map(add_pair, p([[0],[1],[2]], (m-1)), [1,2]))]; fi; 
end;
 
> 
add_pair := (u,v) -> [op(u), op(v)];
 
> 
#This function returns a table of the gasket out to level m... 
gasket:=proc(m) 
    local i, vm, T; 
 
    vm:= vertices(m); 
    T:=table(); 
    for i from 1 to nops(vm) do  
        T[vm[i], 0] := vm[i]    od; 
 
 
   T;  
end;
 
> 
#This function makes stores the neighbors of each vertex out to level m in 
#the gasket table T.  The neighbors are ordered clockwise; i.e., the 1st neighbor 
#of 0,1 in V3 is 1,0,0,1, etc... 
make_neighbors:=proc(T,m,vm) 
   
  local i,j,depth,nb1,nb2,nb3,nb4,iverts,last_verts; 
 
#first, we have to deal with the special case of V1... 
  if m=1 then   
 
print(`Yo, V1 is STOOOOOOPID!`); 
  T[[0],1]:=[0,1]; 
  T[[0],2]:=[0,2]; 
   
  T[[1],1]:=[1,2]; 
  T[[1],2]:=[0,1];   
 
  T[[2],1]:=[0,2]; 
  T[[2],2]:=[1,2]; 
 
  T[[0,1],3]:=[0,2]; 
  T[[0,1],4]:=[0]; 
  T[[0,1],1]:=[1]; 
  T[[0,1],2]:=[1,2]; 
 
  T[[1,2],3]:=[0,1]; 
  T[[1,2],4]:=[1]; 
  T[[1,2],2]:=[0,2]; 
  T[[1,2],1]:=[2]; 
 
  T[[0,2],1]:=[0]; 
  T[[0,2],2]:=[0,1]; 
  T[[0,2],3]:=[1,2]; 
  T[[0,2],4]:=[2]; 
 
 
#hard coding reverse neighbors... 
  T[T[[0],1],4] := [0];   
  T[T[[0],2],1] := [0]; 
 
  T[T[[1],1],4] := [1]; 
  T[T[[1],2],1] := [1]; 
 
  T[T[[2],1],4] := [2]; 
  T[T[[2],2],1] := [2]; 
 
#done with hard coding (yay!) 
  fi; 
 
  if m <>1 then #but if we are not in V1... 
#hard coding the neighbors for V0,V1 
 
  T[[0],1]:=[seq(0,i=1..m),1]; 
  T[[0],2]:=[seq(0,i=1..m),2]; 
   
  T[[1],1]:=[seq(1,i=1..m),2]; 
  T[[1],2]:=[seq(1,i=1..m-1),0,1];   
 
  T[[2],1]:=[seq(2,i=1..m-1),0,2]; 
  T[[2],2]:=[seq(2,i=1..m-1),1,2]; 
 
  T[[0,1],3]:=[0,seq(1,i=1..m-2),1,2]; 
  T[[0,1],4]:=[0,seq(1,i=1..m-2),0,1]; 
  T[[0,1],1]:=[1,seq(0,i=1..m-2),0,1]; 
  T[[0,1],2]:=[1,seq(0,i=1..m-2),0,2]; 
 
  T[[1,2],3]:=[1,seq(2,i=1..m-2),0,2]; 
  T[[1,2],4]:=[1,seq(2,i=1..m-2),1,2]; 
  T[[1,2],2]:=[2,seq(1,i=1..m-2),0,1]; 
  T[[1,2],1]:=[2,seq(1,i=1..m-2),1,2]; 
 
  T[[0,2],1]:=[0,seq(2,i=1..m-2),0,2]; 
  T[[0,2],2]:=[0,seq(2,i=1..m-2),1,2]; 
  T[[0,2],3]:=[2,seq(0,i=1..m-2),0,1]; 
  T[[0,2],4]:=[2,seq(0,i=1..m-2),0,2]; 
 
 
#hard coding reverse neighbors... 
  T[T[[0],1],4] := [0];   
  T[T[[0],2],1] := [0]; 
 
  T[T[[1],1],4] := [1]; 
  T[T[[1],2],1] := [1]; 
 
  T[T[[2],1],4] := [2]; 
  T[T[[2],2],1] := [2]; 
 
   
  T[T[[0,1],1],4] := [0,1]; 
  T[T[[0,1],2],1] := [0,1]; 
  T[T[[0,1],3],4] := [0,1]; 
  T[T[[0,1],4],1] := [0,1]; 
 
  T[T[[1,2],1],4] := [1,2]; 
  T[T[[1,2],2],1] := [1,2]; 
  T[T[[1,2],3],4] := [1,2]; 
  T[T[[1,2],4],1] := [1,2]; 
 
  T[T[[0,2],1],4] := [0,2]; 
  T[T[[0,2],2],1] := [0,2]; 
  T[T[[0,2],3],4] := [0,2]; 
  T[T[[0,2],4],1] := [0,2]; 
 
#done with hard coding (yay!) 
   
 
# First, we compute the neighbors of all pts in Vk, 1<k<m.  Notice that all of the neighbors 
# will be in Vm... 
  for i from 2 to m-1 do 
 
   #doing the 01 endings first... 
    iverts:=pick_vertices01(vm,i); 
    for j from 1 to nops(iverts) do 
       nb1:=[op(iverts[j][1..i-1]),op(T[[0,1],1][1..m-i]),0,1]; 
       nb2:=[op(iverts[j][1..i-1]),op(T[[0,1],2][1..m-i]),0,2]; 
       nb3:=[op(iverts[j][1..i-1]),op(T[[0,1],3][1..m-i]),1,2];  
       nb4:=[op(iverts[j][1..i-1]),op(T[[0,1],4][1..m-i]),0,1]; 
       T[iverts[j],1]:=nb1: T[iverts[j],2]:=nb2: T[iverts[j],3]:=nb3: T[iverts[j],4]:=nb4; 
       T[nb1,4]:=iverts[j]: T[nb2,1]:=iverts[j]: T[nb3,4]:=iverts[j]: T[nb4,1]:=iverts[j]; 
    od; 
 
#doing the 12 endings second... 
    iverts:=pick_vertices12(vm,i); 
    for j from 1 to nops(iverts) do 
       nb1:=[op(iverts[j][1..i-1]),op(T[[1,2],1][1..m-i]),1,2]; 
       nb2:=[op(iverts[j][1..i-1]),op(T[[1,2],2][1..m-i]),0,1]; 
       nb3:=[op(iverts[j][1..i-1]),op(T[[1,2],3][1..m-i]),0,2];  
       nb4:=[op(iverts[j][1..i-1]),op(T[[1,2],4][1..m-i]),1,2]; 
       T[iverts[j],1]:=nb1: T[iverts[j],2]:=nb2: T[iverts[j],3]:=nb3: T[iverts[j],4]:=nb4; 
       T[nb1,4]:=iverts[j]: T[nb2,1]:=iverts[j]: T[nb3,4]:=iverts[j]: T[nb4,1]:=iverts[j]; 
    od; 
 
#doing the 02 endings third... 
    iverts:=pick_vertices02(vm,i); 
    for j from 1 to nops(iverts) do 
       nb1:=[op(iverts[j][1..i-1]),op(T[[0,2],1][1..m-i]),0,2]; 
       nb2:=[op(iverts[j][1..i-1]),op(T[[0,2],2][1..m-i]),1,2]; 
       nb3:=[op(iverts[j][1..i-1]),op(T[[0,2],3][1..m-i]),0,1];  
       nb4:=[op(iverts[j][1..i-1]),op(T[[0,2],4][1..m-i]),0,2]; 
       T[iverts[j],1]:=nb1: T[iverts[j],2]:=nb2: T[iverts[j],3]:=nb3: T[iverts[j],4]:=nb4; 
       T[nb1,4]:=iverts[j]: T[nb2,1]:=iverts[j]: T[nb3,4]:=iverts[j]: T[nb4,1]:=iverts[j]; 
    od; 
  od; 
 
 
#Here we do the neighbors of the vertices in Vm... 
#Notice that we only have to assign 2 neighbors because each pt in 
#Vm has 2 neighbors in Vm and 2 neighbors in Vk, k<m. 
  last_verts:=pick_vertices01(vm,m); 
  for j from 1 to nops(last_verts) do  
     nb2:=[op(last_verts[j][1..m-1]),1,2]; 
     nb3:=[op(last_verts[j][1..m-1]),0,2]; 
     T[last_verts[j],2]:=nb2: T[last_verts[j],3]:=nb3; 
  od;  
 
 last_verts:=pick_vertices12(vm,m); 
  for j from 1 to nops(last_verts) do  
     nb2:=[op(last_verts[j][1..m-1]),0,2]; 
     nb3:=[op(last_verts[j][1..m-1]),0,1]; 
     T[last_verts[j],2]:=nb2: T[last_verts[j],3]:=nb3; 
  od; 
  
 last_verts:=pick_vertices02(vm,m); 
  for j from 1 to nops(last_verts) do  
     nb2:=[op(last_verts[j][1..m-1]),0,1]; 
     nb3:=[op(last_verts[j][1..m-1]),1,2]; 
     T[last_verts[j],2]:=nb2: T[last_verts[j],3]:=nb3; 
  od;  
 
 
fi; 
  T; 
 
 
 
 
 
end; 
 
 
> 
#picks vertices out of vm of length i with ending [0,1] 
pick_vertices01:=proc(vm,i) 
  select(len_list_eq, vm,i,[0,1]); 
end;
 
 
> 
len_list_eq:=proc(l,i,ending) 
  evalb(nops(l) = i+1 and l[nops(l)-1..nops(l)] = ending); 
end;
 
> 
#like pick_vertices01... 
pick_vertices12:=proc(vm,i) 
  select(len_list_eq, vm,i,[1,2]); 
end; 
 
 
> 
#like pick_vertices01... 
pick_vertices02:=proc(vm,i) 
  select(len_list_eq, vm,i,[0,2]); 
end; 
 
 
> 
#This function stores the x and y coordinates of each vertex 
#in the 5 and 6 slots of T, respectively 
make_points:=proc(T,m) 
  local i; 
 
  #func:=select(the_points,[indices(T)],0,3); 
 
 
# first, we have to manually set the values of x and y out to V1... 
  T[[0],5]:=0; 
  T[[1],5]:=.5; 
  T[[2],5]:=-.5; 
 
  T[[0],6]:=sqrt(3)/2; 
  T[[1],6]:=0; 
  T[[2],6]:=0; 
 
  T[[0,1],5]:=.25; 
  T[[0,1],6]:=sqrt(3)/4; 
  T[[1,2],5]:=0; 
  T[[1,2],6]:=0; 
  T[[0,2],5]:=-.25; 
  T[[0,2],6]:=sqrt(3)/4;  
 
#gen_points recursively creates the rest of the coordinates out to Vm...  
 
gen_points(T,m-1,[0],[0,1],[0,2]); 
gen_points(T,m-1,[1],[1,2],[0,1]); 
gen_points(T,m-1,[2],[0,2],[1,2]);          
 
end;
 
> 
the_points:=proc(L,funcno,minlen,maxlen) 
  evalb(L[2] = funcno and nops(L[1]) >= minlen and nops(L[1]) <= maxlen); 
end;
 
> 
#This function is called by make_points.  It calls itself recursively 'n stuff. 
gen_points:=proc(T,m,add0,add1,add2) 
   if m <> 0 then 
 
#So the general strategy is as follows:  We can't assign values to the next level of  
#vertices without knowing the orientation of the triangle (because we need to know whether we need to assign 
#to a 0,1 point, 1,2 point, etc.).  So what we do is call the function with 3 addresses 
#and make it so that the 0th address (add0) is one of the vertices of the outside triangle 
#(i.e., going from the V0 triangle, the triangles would be T1=([0],[0,1],[0,2]),T2=([1],[1,2],[0,1]) 
#and so forth).  Thus, by looking at add1 of this triangle, we can determine the orientation of 
#the triangle by checking whether add1 ends in 0,1, 0,2 or 1,2.  Then we assign the values 
#accordingly, after which we call gen_points recursively, making sure to keep the orientation 
#of the 3 addresses in the recursive calls.  We use this same method to generate harmonic functions 
#and n-harmonic functions, as well as several other things.  Notice that this recursive process 
#has it's base case as V1, therefore requiring 3 seperate calls to gen_points from make_points. 
#This is due to the idiosyncratic addressing of the vertices of V0.  Oh well.... 
 
      if add1[nops(add1)-1..nops(add1)] = [0,1] then 
          T[[op(add1[1..nops(add1)-2]),0,0,1],5] := .5 * T[add0,5] + .5 * T[add1,5];    
          T[[op(add1[1..nops(add1)-2]),0,1,2],5] := .5 * T[add1,5] + .5 * T[add2,5]; 
          T[[op(add1[1..nops(add1)-2]),0,0,2],5] := .5 * T[add0,5] + .5 * T[add2,5];  
          T[[op(add1[1..nops(add1)-2]),0,0,1],6] := .5 * T[add0,6] + .5 * T[add1,6];   
          T[[op(add1[1..nops(add1)-2]),0,1,2],6] := .5 * T[add1,6] + .5 * T[add2,6]; 
          T[[op(add1[1..nops(add1)-2]),0,0,2],6] := .5 * T[add0,6] + .5 * T[add2,6]; 
          gen_points(T,m-1,add0,[op(add1[1..nops(add1)-2]),0,0,1],[op(add1[1..nops(add1)-2]),0,0,2]); 
          gen_points(T,m-1,add1,[op(add1[1..nops(add1)-2]),0,1,2],[op(add1[1..nops(add1)-2]),0,0,1]); 
          gen_points(T,m-1,add2,[op(add1[1..nops(add1)-2]),0,0,2],[op(add1[1..nops(add1)-2]),0,1,2]); 
      fi; 
      if add1[nops(add1)-1..nops(add1)] = [1,2] then 
          T[[op(add1[1..nops(add1)-2]),1,1,2],5] := .5 * T[add0,5] + .5 * T[add1,5];   
          T[[op(add1[1..nops(add1)-2]),1,0,2],5] := .5 * T[add1,5] + .5 * T[add2,5]; 
          T[[op(add1[1..nops(add1)-2]),1,0,1],5] := .5 * T[add0,5] + .5 * T[add2,5]; 
          T[[op(add1[1..nops(add1)-2]),1,1,2],6] := .5 * T[add0,6] + .5 * T[add1,6];   
          T[[op(add1[1..nops(add1)-2]),1,0,2],6] := .5 * T[add1,6] + .5 * T[add2,6]; 
          T[[op(add1[1..nops(add1)-2]),1,0,1],6] := .5 * T[add0,6] + .5 * T[add2,6]; 
          gen_points(T,m-1,add0,[op(add1[1..nops(add1)-2]),1,1,2],[op(add1[1..nops(add1)-2]),1,0,1]); 
          gen_points(T,m-1,add1,[op(add1[1..nops(add1)-2]),1,0,2],[op(add1[1..nops(add1)-2]),1,1,2]); 
          gen_points(T,m-1,add2,[op(add1[1..nops(add1)-2]),1,0,1],[op(add1[1..nops(add1)-2]),1,0,2]); 
      fi; 
      if add1[nops(add1)-1..nops(add1)] = [0,2] then 
          T[[op(add1[1..nops(add1)-2]),2,0,2],5] := .5 * T[add0,5] + .5 * T[add1,5];   
          T[[op(add1[1..nops(add1)-2]),2,0,1],5] := .5 * T[add1,5] + .5 * T[add2,5]; 
          T[[op(add1[1..nops(add1)-2]),2,1,2],5] := .5 * T[add0,5] + .5 * T[add2,5]; 
          T[[op(add1[1..nops(add1)-2]),2,0,2],6] := .5 * T[add0,6] + .5 * T[add1,6];   
          T[[op(add1[1..nops(add1)-2]),2,0,1],6] := .5 * T[add1,6] + .5 * T[add2,6]; 
          T[[op(add1[1..nops(add1)-2]),2,1,2],6] := .5 * T[add0,6] + .5 * T[add2,6]; 
          gen_points(T,m-1,add0,[op(add1[1..nops(add1)-2]),2,0,2],[op(add1[1..nops(add1)-2]),2,1,2]); 
          gen_points(T,m-1,add1,[op(add1[1..nops(add1)-2]),2,0,1],[op(add1[1..nops(add1)-2]),2,0,2]); 
          gen_points(T,m-1,add2,[op(add1[1..nops(add1)-2]),2,1,2],[op(add1[1..nops(add1)-2]),2,0,1]); 
      fi; 
   fi;  
end; 
 
> 
#This function returns a list of x,y,z coordinates from a function 
#stored in T.  This list can be sent directly into pointplot3d for plotting 
SG_plot:=proc(T,m,funcno) 
  local i,plot_pts,func; 
 
  #func:=select(the_points,[indices(T)],5,0,m+1); 
  func:=vertices(m); 
 
  plot_pts:=[seq([T[func[i],5],T[func[i],6],T[func[i],funcno]],i=1..nops(func))]; 
 
  plot_pts; 
end;  
 
 
> 
#This is used to animate a time series of basis values. 
#It takes the parameters in vals, which is a list of lists, 
#with each sublist corresponding to a particular spline function 
#representation.  Funcno is just some place in which to store the 
#actual values of the function.  The output is a list of plot 
#structures, which can then be sent directly to display, and if you 
#use insequence = true, it will animate for you... 
 
make_animation:=proc(T,m_basis,m_func,vals,funcno,harm_funcno) 
 
local S,vm,SG_plots,final_points,inds,i; 
 
SG_plots:=[]; 
 
S:=gasket(m_basis); 
vm:=vertices(m_basis); 
make_neighbors(S,m_basis,vm); 
make_points(T,m_func); 
 
for i from 1 to nops(vals) do 
 
   print(`computing plot number `,i); 
   make_pretty_picture(T,S,m_basis,m_func,vm,funcno,harm_funcno,vals[i]); 
   final_points:=SG_plot(T,m_func,funcno); 
   SG_plots:=[op(SG_plots),pointplot3d(final_points,color=BLUE,symbol=POINT)]; 
od; 
 
SG_plots; 
end; 
 
> 
 
> 
 
> 
#This function will take a line of the sierpinski gasket, and  
#returns, in order, a list of the vertices along that line.  It is 
#used in conjunction with SG_plot_line in order to create line 
#plots of a function along a line of the SG.  The line is defined 
#by starting at startpt.  From there, we go to first_neighbor.  After 
#that, we continue following rest_neighbor, until the ending (ie, last 
#2 digits) change, thereby indicating we have gotten to the end of the line. 
#for example, the line from [0,2] to [1,2] would be gotten by 
#line_vertices(4,[0,2],3,1), since we would start by taking the 3rd neighbor, 
#and then continue along the 1st neighbor (the endings would all be 0,1) 
#until we got to 1,2, at which point, the ending of rest_neighbor would be 
#1,2, indicating that we have gotten to the end of the line. 
 
 
line_vertices:=proc(m_func,startpt,first_neighbor,rest_neighbor) 
local lineT,vm,outlist,ending,last_pt; 
 
lineT:=gasket(m_func); 
vm:=vertices(m_func); 
make_neighbors(lineT,m_func,vm); 
 
outlist:=[startpt,lineT[startpt,first_neighbor]]; 
 
ending:=last_digits(lineT[startpt,first_neighbor]); 
last_pt:=lineT[startpt,first_neighbor]; 
 
while last_digits(lineT[last_pt,rest_neighbor])=ending do 
   outlist:=[op(outlist),lineT[last_pt,rest_neighbor]]; 
   last_pt:=lineT[last_pt,rest_neighbor]; 
od; 
 
outlist:=[op(outlist),lineT[last_pt,rest_neighbor]]; 
 
outlist; 
end; 
 
 
 
 
> 
 
> 
 
> 
#This function is just like make_animation, except that it makes 2d line plots 
#of the function along a line defined by startpt, first_neighbor, rest_neighbor. 
#You also need to input linelength to tell the program how long the line should 
#be.  For instance, the line from [0,2] to [1,2] would require linelength to be 
#1/2.  For more information about how startpt, first_neighbor, and rest_neighbor 
#define a line, look at line_vertices above. 
 
 
make_animation_line:=proc(T,m_basis,m_func,vals,funcno,harm_funcno,startpt,first_neighbor,rest_neighbor,linelength) 
 
local linepts,S,vm,SG_plots,final_points,inds,i; 
 
SG_plots:=[]; 
 
S:=gasket(m_basis); 
vm:=vertices(m_basis); 
make_neighbors(S,m_basis,vm); 
make_points(T,m_func); 
 
linepts:=line_vertices(m_func,startpt,first_neighbor,rest_neighbor); 
 
for i from 1 to nops(vals) do 
 
   print(`computing plot number `,i); 
   make_pretty_picture(T,S,m_basis,m_func,vm,funcno,harm_funcno,vals[i]); 
   final_points:=SG_plot_line(T,m_func,funcno,linepts,linelength); 
   SG_plots:=[op(SG_plots),plot(final_points,color=BLUE,symbol=POINT)]; 
od; 
 
SG_plots; 
end; 
 
> 
 
> 
#This function is just like SG_plot, except that it creates a 2d 
#line plot along a line which is defined by linepts, and is of length 
#linelength. 
 
SG_plot_line:=proc(T,m,funcno,linepts,linelength) 
  local i,plot_pts,numpts; 
 
  numpts:=nops(linepts); 
 
  plot_pts:=[seq([(i-1)*linelength/(numpts-1),T[linepts[i],funcno]],i=1..numpts)]; 
 
  plot_pts; 
end;  
 
 |