<?xml version="1.0" encoding="UTF-8"?>
<Worksheet><Version major="6" minor="1"/><View-Properties><Zoom percentage="100"/></View-Properties><Styles><Layout alignment="left" bullet="none" firstindent="0.0" leftmargin="0.0" linebreak="space" linespacing="0.0" name="Normal" rightmargin="0.0" spaceabove="0.0" spacebelow="0.0"/><Layout alignment="centred" bullet="none" name="Maple Plot"/><Layout alignment="centred" bullet="none" linespacing="0.5" name="Maple Output"/><Font background="[0,0,0]" bold="true" executable="true" family="Monospaced" foreground="[255,0,0]" name="Maple Input" opaque="false" size="12"/><Font background="[0,0,0]" bold="false" executable="false" family="Times New Roman" foreground="[0,0,0]" italic="false" name="Text" opaque="false" size="12" underline="false"/><Font background="[0,0,0]" family="Times New Roman" foreground="[0,0,255]" name="2D Output" opaque="false" readonly="true" size="12"/></Styles><Group><Input><Text-field layout="Normal" style="Text">To do spline interpolation, we need a series of knots and a pair of slopes.  This is a demo program</Text-field><Text-field layout="Normal" style="Text">showing an interpolation for a 5 knot (four segment) spline curve.</Text-field><Text-field layout="Normal" style="Text"/></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">with( LinearAlgebra ):
with( plots ):</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Text">With the knots matrix and the end point slopes, our spline becomes fully defined.  </Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">knots := &lt; &lt;-3,2&gt; | &lt;-1,0.5&gt; | &lt;0,0&gt; | &lt;1,0.5&gt; | &lt;3,2&gt; &gt;;
endSlopes := Vector( [-1,1] );</Text-field></Input><Output><Text-field layout="Maple Output" style="2D Output"><Equation>NiM+SSZrbm90c0c2Ii1JJ1JUQUJMRUdGJTYlIik/JSpcQy1JJ01BVFJJWEdGJTYjNyQ3JyEiJCEiIiIiISIiIiIiJDcnIiIjJCIiJkYwRjFGNkY1SSdNYXRyaXhHNiRJKnByb3RlY3RlZEdGOkkoX3N5c2xpYkdGJQ==</Equation></Text-field></Output><Output><Text-field layout="Maple Output" style="2D Output"><Equation>NiM+SSplbmRTbG9wZXNHNiItSSdSVEFCTEVHRiU2JSIoU0d1Iy1JJ01BVFJJWEdGJTYjNyQ3IyEiIjcjIiIiJkknVmVjdG9yRzYkSSpwcm90ZWN0ZWRHRjVJKF9zeXNsaWJHRiU2I0knY29sdW1uR0Yl</Equation></Text-field></Output></Group><Group><Input><Text-field layout="Normal" style="Text">All we really care about is the coefficients for the cubic polynomials which make up our splines.  </Text-field><Text-field layout="Normal" style="Text">With five knots, we have four cubic polynomials, each with four polynomials, giving us 16 </Text-field><Text-field layout="Normal" style="Text">unknowns.  From the definition of a cubic spline, we build a matrix representing our relationships</Text-field><Text-field layout="Normal" style="Text">between the cubic polynomials and solve for the unknown coefficients.  We have:
</Text-field><Text-field layout="Normal" style="Text">	Matrix A:	Cubic polynomial equations
	Vector xv:	Coefficients for cubic polynomials (what we want to solve for)
	Vector bv:	Solutions (conditions) for each line in matrix A</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">numKnots := ColumnDimension( knots ):
unknowns := ( numKnots - 1 ) * 4:
A := Matrix( unknowns, unknowns ):
xv := Vector( unknowns ):
bv := Vector( unknowns ):</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Text">These are some general helper structures which will clean up our later computations.</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">cubicPoly := Vector( [1,x,x^2,x^3] ):
cubicOneDiff := Vector( [0,1,2*x,3*x^2] ):
cubicTwoDiff := Vector( [0,0,2,6*x] ):
currentRow := 1:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Text">For each segment, assert f_i( x_i ) = y_i</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">for j from 1 to ( numKnots - 1 ) do
    currentKnot := Column( knots, j ):
    A[ currentRow, (j * 4 - 3)..(j * 4) ] := Transpose( eval( cubicPoly, x=currentKnot[ 1 ] ) ): 
    bv[ currentRow ] := currentKnot[ 2 ]:
    currentRow := currentRow + 1:
end do:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Text">For each segment assert f_i( x_i+1) = y_i+1</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">for j from 1 to ( numKnots - 1 ) do
    currentKnot := Column( knots, j+1 ):
    A[ currentRow, (j * 4 - 3)..(j * 4) ] := Transpose( eval( cubicPoly, x=currentKnot[ 1 ] ) ): 
    bv[ currentRow ] := currentKnot[ 2 ]:
    currentRow := currentRow + 1:
end do:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Text">Where each segment meets, assert f_i ' ( x_i ) - f_i+1 ' ( x_i ) = 0</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">for j from 1 to ( numKnots - 2 ) do
    currentKnot := Column( knots, j+1 ): 
    A[ currentRow, (j * 4 - 3)..(j * 4) ] := Transpose( eval( cubicOneDiff, x=currentKnot[ 1 ] ) ): 
    A[ currentRow, (j * 4 + 1)..(j * 4 + 4) ] := (-1) * Transpose( eval( cubicOneDiff, x=currentKnot[ 1 ] ) ): 
    bv[ currentRow ] := 0:
    currentRow := currentRow + 1:
end do:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Text">Where each segment meets, assert f_i '' (x_i) - f_i+1 '' (x_i) = 0</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">for j from 1 to ( numKnots - 2 ) do
    currentKnot := Column( knots, j+1 ): 
    A[ currentRow, (j * 4 - 3)..(j * 4) ] := Transpose( eval( cubicTwoDiff, x=currentKnot[ 1 ] ) ): 
    A[ currentRow, (j * 4 + 1)..(j * 4 + 4) ] := (-1) * Transpose( eval( cubicTwoDiff, x=currentKnot[ 1 ] ) ): 
    bv[ currentRow ] := 0:
    currentRow := currentRow + 1:
end do:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Text">Finally, assert our end point slope conditions</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">currentKnot := Column( knots, 1 ):
A[ currentRow, 1..4 ] := Transpose( eval( cubicOneDiff, x=currentKnot[ 1 ] ) ):
bv[ currentRow ] := endSlopes[ 1 ]:
currentRow := currentRow + 1:
currentKnot := Column( knots, numKnots ):
A[ currentRow, (unknowns-3)..(unknowns) ] := Transpose( eval( cubicOneDiff, x=currentKnot[ 1 ] ) ):
bv[ currentRow ] := endSlopes[ 2 ]:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Text">Solve the coefficient matrix to find the coefficients for our components cubic polynomials.</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">xv := A^(-1) . bv:</Text-field></Input></Group><Group><Input><Text-field layout="Normal" style="Text">Represent our coefficients as cubic polynomials and build a piecwise function (the spline curve).</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">f := 0:
for j from 1 to ( numKnots - 1 ) do
    f := piecewise( x &lt; knots[ 1, j ], f, 
                    x &gt;= knots[ 1, j ] and x &lt; knots[ 1, j+1 ], xv[ (j * 4 - 3)..(j*4) ] . cubicPoly ):
end do:
f := simplify( f );</Text-field></Input><Output><Text-field layout="Maple Output" style="2D Output"><Equation>NiM+SSJmRzYiLUkqUElFQ0VXSVNFRzYkSSpwcm90ZWN0ZWRHRilJKF9zeXNsaWJHRiU2KDckJCIiIUYuMkkieEdGJSQhIiRGLjckLCokISsrK11QTSEjNSIiIkYwJCErKytESjUhIioqJEYwIiIjJCErTEwkZVIjRjcqJEYwIiIkJCErTExMM18hIzYyRjAkISIiRi43JCwmRjwkIitubW07ekY3RkAkIitubW07SEY3MkYwRi03JCwmRjxGSkZAJCErbm1tO0hGNzJGMCRGOEYuNyQsKkY1RjhGMCQiKysrREo1RjtGPEY+RkAkIitMTEwzX0ZEMkYwJEZBRi43JEYtMUZmbkYw</Equation></Text-field></Output></Group><Group><Input><Text-field layout="Normal" style="Text">Plot our spline curve.</Text-field></Input></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input">( xMin, xMax ) := rtable_scanblock( Row( knots, 1 ), [1..numKnots],'Minimum','Maximum'):
( yMin, yMax ) := rtable_scanblock( Row( knots, 2 ), [1..numKnots],'Minimum','Maximum'):
plot( f, x=(xMin-2)..(xMax+2), y=(yMin-2)..(yMax+2));</Text-field></Input><Output><Text-field layout="Maple Plot"><Plot height="400" plot-scale="1.0" plot-xtrans="0.0" plot-ytrans="0.0" type="two-dimensional" width="400">LSUlUExPVEc2JS0lJ0NVUlZFU0c2JDdgcDckJCEiJiIiISRGLEYsNyQkITNYTExMZSVHP3klISM8Ri03JCQhM09tbVQmZXNCZiVGMUYtNyQkITNATEwkM3MlM3pWRjFGLTckJCEzXkxMJGUvJFFrVEYxRi03JCQhM29tbVQ1PXFdUkYxRi03JCQhM0hMTDNfPmZfUEYxRi03JCQhM0srK3ZvMVlaTkYxRi03JCQhMztMTDMtT0pOTEYxRi03JCQhMz9tbSJ6QyFlSEtGMUYtNyQkITNvKioqXFAqbyVRNyRGMUYtNyQkITM3bSJIIz1xWXBJRjFGLTckJCEzK0wkM0Y5KDM6SUYxRi03JCQhMyEpRyNvI2UnKkczSUYxRi03JCQhMzBEIkdRPCNcLElGMUYtNyQkITMnMy0pUSpvJXAlKkhGMSQiM2MnZT0/OCxaKj5GMTckJCEzbTt6JVw/KCp5KUhGMSQiM3p4Ij0xb0l6KT5GMTckJCEzRjN4MU9BSXVIRjEkIjNyVWdPKW9fVyg+RjE3JCQhMygpKlwoPW5zcWdIRjEkIjNMVmJdQXowaD5GMTckJCEzNSQzRiVIdF5MSEYxJCIzLVx4N0hcXk0+RjE3JCQhM0ttbW0iUkZqIUhGMSQiM0slUUApPWFIMz5GMTckJCEzWyoqKlxQdUowIkdGMSQiMz1VQnlxVFM9PUYxNyQkITMzTEwkZTRPWnIjRjEkIjNDJlFWNGh2QHQiRjE3JCQhM3UqKioqKlxuXCEqXCNGMSQiM2JEP0VBPCxdOkYxNyQkITMlKSoqKioqXGl4Q0cjRjEkIjMjeTp1TVRAN1EiRjE3JCQhMyIqKioqKipcS3FQMiNGMSQiMyopKT08IypmJykqRzdGMTckJCEzOUxMMy1UQyUpPUYxJCIzOyIqXDU/Oz4oNCJGMTckJCEzWm1tbSI0eillO0YxJCIzNDlCRmkhb1VYKiEjPTckJCEzTG1tbW1gJ3pZIkYxJCIzQFxNbFVwaiY9KUZkcjckJCEzIyoqKipcKD10KWVDIkYxJCIzS1BPKkgqNDEqcCdGZHI3JCQhMyFvbW1taDUkXDVGMSQiMywmZjNEcT50TSZGZHI3JCQhM1MkKioqXCg9W2pMKUZkciQiM0EhNEclSGElPiJRRmRyNyQkITMpZioqKlxpWGcjRydGZHIkIjNdNFpgNHleLENGZHI3JCQhM21kbW1UJlEoUlRGZHIkIjNodCpIJGVAelw2RmRyNyQkITNIaG0iSGRHZTokRmRyJCIzRjlZPXApNHgncCEjPjckJCEzJFxtbVRnPT48I0ZkciQiMydSQjVudFtjViRGaHQ3JCQhM0VLJDNGcHk3ayJGZHIkIjMlR0NFVmdNTysjRmh0NyQkITNnKioqXDd5UTE2IkZkciQiMyoqKVwmcHhMeGwkKiEjPzckJCEzaEskM19EKT1gJSlGaHQkIjNHTypbOm0oeSFbJkZodTckJCEzRXBtInpwKSkqKnomRmh0JCIzXGQ/cmAqW2lnI0ZodTckJCEzI2YrRDE5KnlZSkZodCQiM1tubik0LUElW3ghI0A3JCQhM3VETUxMZSplJFxGaHUkIjNdcDJFaWFCRD4hI0E3JCQiMypcbVQmKTNSQkUjRmh0JCIzQ24sYCV6PSI9U0ZodjckJCIzYnNtVGd4RT1dRmh0JCIzTSZmeixtJnpjPkZodTckJCIzNyFvIkhLaz51eEZodCQiMyRRY0gpPU1rWllGaHU3JCQiM3dvbVQ1RCxgNUZkciQiM2tsd15IWnNQJSlGaHU3JCQiM0dxO3pXIyk+LztGZHIkIjMhSHNZLmoxcCI+Rmh0NyQkIjN6cm07elJRYkBGZHIkIjNyQVlcKHB4ZFEkRmh0NyQkIjNtT0xMJGUsXTYkRmRyJCIzTiVbbmAkeTkrb0ZodDckJCIzXiwrXSg9PlkyJUZkciQiMzkyVnRUbzA8NkZkcjckJCIzcnVtbSJ6WHU5J0ZkciQiM1VeJ2UnbyUpPjlCRmRyNyQkIjMjNCsrK115KSlHKUZkciQiMzAocDFKem8ieVBGZHI3JCQiM0grK11pX1FRNUYxJCIzP0lSKCo0c3BxX0ZkcjckJCIzYSsrRCJ5JTNUN0YxJCIzOF4xeFlxYW1tRmRyNyQkIjMrKytdUCFbaFkiRjEkIjMhKilcY0JVZk48KUZkcjckJCIzaUtMTCRReCRvO0YxJCIzMmlGT0kjeXZeKkZkcjckJCIzWSsrK3YuSSUpPUYxJCIzIW9bYT4xSXM0IkYxNyQkIjM/bW0ienBlKno/RjEkIjNPcHlvXjFRTDdGMTckJCIzOywrK0RcJ1FII0YxJCIzJik+LT1EXnoqUSJGMTckJCIzJUhMJGU5UzgmXCNGMSQiM2onUngielElb2EiRjE3JCQiMyVvbTsvNkUuZyNGMSQiMzxcUlxGeWdMO0YxNyQkIjNzKytEMSM9YnEjRjEkIjMqXE8nW2k4MUM8RjE3JCQiMyNvbSJIMkZPM0dGMSQiM1tPc2prQVQ7PUYxNyQkIjMiSExMJDNzPzZIRjEkIjM0LXEpUWB4SCI+RjE3JCQiM007enB0VjdRSEYxJCIzNVZCWUAlKikqUT5GMTckJCIzeipcaSFSOi9sSEYxJCIzVVZNTXgkPmAnPkYxNyQkIjNeInpXPDcrJnlIRjEkIjNkKlxIYWAwJ3k+RjE3JCQiM0EkM0ZXcWU+KkhGMSQiM2s2IUhnXHQ+Kj5GMTckJCIzM0gjb2Qqem8pKkhGMSQiM2Fwd0whUilvKSo+RjE3JCQiMyZcUDRyRzxhKyRGMUYtNyQkIjMhM19dJXlsOTdJRjFGLTckJCIzQW07enBlKCk9SUYxRi03JCQiM2xLM18rLXJzSUYxRi03JCQiM2EqKipcN2BXbDckRjFGLTckJCIzY0wkZSpbQUNJS0YxRi03JCQiM2VubW1tKlJSTCRGMUYtNyQkIjMkem1tVHZKZ2EkRjFGLTckJCIzXU1MZTl0T2NQRjFGLTckJCIzMSwrK11Ra1xSRjFGLTckJCIzek1MJDNkZzY8JUYxRi03JCQiMyV5bW1tdyhHcFZGMUYtNyQkIjNCKytEIm9LMGUlRjFGLTckJCIzNSwrdj01cyN5JUYxRi03JCQiIiZGLEYtLSUmQ09MT1JHNiYlJFJHQkckIiM1ISIiJEYsRmlibEZqYmwtJStBWEVTTEFCRUxTRzYkUSJ4NiJRInlGX2NsLSUlVklFV0c2JDskISNdRmlibCQiI11GaWJsOyRGaHVGaWJsJCIjU0ZpYmw=</Plot></Text-field></Output></Group><Group><Input><Text-field layout="Normal" prompt="&gt; " style="Maple Input"/></Input></Group><Text-field/><Text-field/><RTable handle="24499420" >TTdSMApJNVJUQUJMRV9TQVZFLzI0NDk5NDIwWCwlKWFueXRoaW5nRzYiNiJbZ2whIiUhISEjKyIjIiYhIiQiIiMhIiIkIiImRikiIiFGLCIiIkYqCiIiJEYoRiYK</RTable><RTable handle="2742840" >TTdSMApJNFJUQUJMRV9TQVZFLzI3NDI4NDBYKiUpYW55dGhpbmdHNiI2IltnbCEjJSEhISIjIiMhIiIiIiJGJgo=</RTable></Worksheet>