To do spline interpolation, we need a series of knots and a pair of slopes. This is a demo programshowing an interpolation for a 5 knot (four segment) spline curve.with( LinearAlgebra ): with( plots ):With the knots matrix and the end point slopes, our spline becomes fully defined. knots := < <-3,2> | <-1,0.5> | <0,0> | <1,0.5> | <3,2> >; endSlopes := Vector( [-1,1] );NiM+SSZrbm90c0c2Ii1JJ1JUQUJMRUdGJTYlIik/JSpcQy1JJ01BVFJJWEdGJTYjNyQ3JyEiJCEiIiIiISIiIiIiJDcnIiIjJCIiJkYwRjFGNkY1SSdNYXRyaXhHNiRJKnByb3RlY3RlZEdGOkkoX3N5c2xpYkdGJQ==NiM+SSplbmRTbG9wZXNHNiItSSdSVEFCTEVHRiU2JSIoU0d1Iy1JJ01BVFJJWEdGJTYjNyQ3IyEiIjcjIiIiJkknVmVjdG9yRzYkSSpwcm90ZWN0ZWRHRjVJKF9zeXNsaWJHRiU2I0knY29sdW1uR0YlAll we really care about is the coefficients for the cubic polynomials which make up our splines. With five knots, we have four cubic polynomials, each with four polynomials, giving us 16 unknowns. From the definition of a cubic spline, we build a matrix representing our relationshipsbetween the cubic polynomials and solve for the unknown coefficients. We have: 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 AnumKnots := ColumnDimension( knots ): unknowns := ( numKnots - 1 ) * 4: A := Matrix( unknowns, unknowns ): xv := Vector( unknowns ): bv := Vector( unknowns ):These are some general helper structures which will clean up our later computations.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:For each segment, assert f_i( x_i ) = y_ifor 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:For each segment assert f_i( x_i+1) = y_i+1for 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:Where each segment meets, assert f_i ' ( x_i ) - f_i+1 ' ( x_i ) = 0for 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:Where each segment meets, assert f_i '' (x_i) - f_i+1 '' (x_i) = 0for 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:Finally, assert our end point slope conditionscurrentKnot := 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 ]:Solve the coefficient matrix to find the coefficients for our components cubic polynomials.xv := A^(-1) . bv:Represent our coefficients as cubic polynomials and build a piecwise function (the spline curve).f := 0: for j from 1 to ( numKnots - 1 ) do f := piecewise( x < knots[ 1, j ], f, x >= knots[ 1, j ] and x < knots[ 1, j+1 ], xv[ (j * 4 - 3)..(j*4) ] . cubicPoly ): end do: f := simplify( f );NiM+SSJmRzYiLUkqUElFQ0VXSVNFRzYkSSpwcm90ZWN0ZWRHRilJKF9zeXNsaWJHRiU2KDckJCIiIUYuMkkieEdGJSQhIiRGLjckLCokISsrK11QTSEjNSIiIkYwJCErKytESjUhIioqJEYwIiIjJCErTEwkZVIjRjcqJEYwIiIkJCErTExMM18hIzYyRjAkISIiRi43JCwmRjwkIitubW07ekY3RkAkIitubW07SEY3MkYwRi03JCwmRjxGSkZAJCErbm1tO0hGNzJGMCRGOEYuNyQsKkY1RjhGMCQiKysrREo1RjtGPEY+RkAkIitMTEwzX0ZEMkYwJEZBRi43JEYtMUZmbkYwPlot our spline curve.( 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));LSUlUExPVEc2JS0lJ0NVUlZFU0c2JDdgcDckJCEiJiIiISRGLEYsNyQkITNYTExMZSVHP3klISM8Ri03JCQhM09tbVQmZXNCZiVGMUYtNyQkITNATEwkM3MlM3pWRjFGLTckJCEzXkxMJGUvJFFrVEYxRi03JCQhM29tbVQ1PXFdUkYxRi03JCQhM0hMTDNfPmZfUEYxRi03JCQhM0srK3ZvMVlaTkYxRi03JCQhMztMTDMtT0pOTEYxRi03JCQhMz9tbSJ6QyFlSEtGMUYtNyQkITNvKioqXFAqbyVRNyRGMUYtNyQkITM3bSJIIz1xWXBJRjFGLTckJCEzK0wkM0Y5KDM6SUYxRi03JCQhMyEpRyNvI2UnKkczSUYxRi03JCQhMzBEIkdRPCNcLElGMUYtNyQkITMnMy0pUSpvJXAlKkhGMSQiM2MnZT0/OCxaKj5GMTckJCEzbTt6JVw/KCp5KUhGMSQiM3p4Ij0xb0l6KT5GMTckJCEzRjN4MU9BSXVIRjEkIjNyVWdPKW9fVyg+RjE3JCQhMygpKlwoPW5zcWdIRjEkIjNMVmJdQXowaD5GMTckJCEzNSQzRiVIdF5MSEYxJCIzLVx4N0hcXk0+RjE3JCQhM0ttbW0iUkZqIUhGMSQiM0slUUApPWFIMz5GMTckJCEzWyoqKlxQdUowIkdGMSQiMz1VQnlxVFM9PUYxNyQkITMzTEwkZTRPWnIjRjEkIjNDJlFWNGh2QHQiRjE3JCQhM3UqKioqKlxuXCEqXCNGMSQiM2JEP0VBPCxdOkYxNyQkITMlKSoqKioqXGl4Q0cjRjEkIjMjeTp1TVRAN1EiRjE3JCQhMyIqKioqKipcS3FQMiNGMSQiMyopKT08IypmJykqRzdGMTckJCEzOUxMMy1UQyUpPUYxJCIzOyIqXDU/Oz4oNCJGMTckJCEzWm1tbSI0eillO0YxJCIzNDlCRmkhb1VYKiEjPTckJCEzTG1tbW1gJ3pZIkYxJCIzQFxNbFVwaiY9KUZkcjckJCEzIyoqKipcKD10KWVDIkYxJCIzS1BPKkgqNDEqcCdGZHI3JCQhMyFvbW1taDUkXDVGMSQiMywmZjNEcT50TSZGZHI3JCQhM1MkKioqXCg9W2pMKUZkciQiM0EhNEclSGElPiJRRmRyNyQkITMpZioqKlxpWGcjRydGZHIkIjNdNFpgNHleLENGZHI3JCQhM21kbW1UJlEoUlRGZHIkIjNodCpIJGVAelw2RmRyNyQkITNIaG0iSGRHZTokRmRyJCIzRjlZPXApNHgncCEjPjckJCEzJFxtbVRnPT48I0ZkciQiMydSQjVudFtjViRGaHQ3JCQhM0VLJDNGcHk3ayJGZHIkIjMlR0NFVmdNTysjRmh0NyQkITNnKioqXDd5UTE2IkZkciQiMyoqKVwmcHhMeGwkKiEjPzckJCEzaEskM19EKT1gJSlGaHQkIjNHTypbOm0oeSFbJkZodTckJCEzRXBtInpwKSkqKnomRmh0JCIzXGQ/cmAqW2lnI0ZodTckJCEzI2YrRDE5KnlZSkZodCQiM1tubik0LUElW3ghI0A3JCQhM3VETUxMZSplJFxGaHUkIjNdcDJFaWFCRD4hI0E3JCQiMypcbVQmKTNSQkUjRmh0JCIzQ24sYCV6PSI9U0ZodjckJCIzYnNtVGd4RT1dRmh0JCIzTSZmeixtJnpjPkZodTckJCIzNyFvIkhLaz51eEZodCQiMyRRY0gpPU1rWllGaHU3JCQiM3dvbVQ1RCxgNUZkciQiM2tsd15IWnNQJSlGaHU3JCQiM0dxO3pXIyk+LztGZHIkIjMhSHNZLmoxcCI+Rmh0NyQkIjN6cm07elJRYkBGZHIkIjNyQVlcKHB4ZFEkRmh0NyQkIjNtT0xMJGUsXTYkRmRyJCIzTiVbbmAkeTkrb0ZodDckJCIzXiwrXSg9PlkyJUZkciQiMzkyVnRUbzA8NkZkcjckJCIzcnVtbSJ6WHU5J0ZkciQiM1VeJ2UnbyUpPjlCRmRyNyQkIjMjNCsrK115KSlHKUZkciQiMzAocDFKem8ieVBGZHI3JCQiM0grK11pX1FRNUYxJCIzP0lSKCo0c3BxX0ZkcjckJCIzYSsrRCJ5JTNUN0YxJCIzOF4xeFlxYW1tRmRyNyQkIjMrKytdUCFbaFkiRjEkIjMhKilcY0JVZk48KUZkcjckJCIzaUtMTCRReCRvO0YxJCIzMmlGT0kjeXZeKkZkcjckJCIzWSsrK3YuSSUpPUYxJCIzIW9bYT4xSXM0IkYxNyQkIjM/bW0ienBlKno/RjEkIjNPcHlvXjFRTDdGMTckJCIzOywrK0RcJ1FII0YxJCIzJik+LT1EXnoqUSJGMTckJCIzJUhMJGU5UzgmXCNGMSQiM2onUngielElb2EiRjE3JCQiMyVvbTsvNkUuZyNGMSQiMzxcUlxGeWdMO0YxNyQkIjNzKytEMSM9YnEjRjEkIjMqXE8nW2k4MUM8RjE3JCQiMyNvbSJIMkZPM0dGMSQiM1tPc2prQVQ7PUYxNyQkIjMiSExMJDNzPzZIRjEkIjM0LXEpUWB4SCI+RjE3JCQiM007enB0VjdRSEYxJCIzNVZCWUAlKikqUT5GMTckJCIzeipcaSFSOi9sSEYxJCIzVVZNTXgkPmAnPkYxNyQkIjNeInpXPDcrJnlIRjEkIjNkKlxIYWAwJ3k+RjE3JCQiM0EkM0ZXcWU+KkhGMSQiM2s2IUhnXHQ+Kj5GMTckJCIzM0gjb2Qqem8pKkhGMSQiM2Fwd0whUilvKSo+RjE3JCQiMyZcUDRyRzxhKyRGMUYtNyQkIjMhM19dJXlsOTdJRjFGLTckJCIzQW07enBlKCk9SUYxRi03JCQiM2xLM18rLXJzSUYxRi03JCQiM2EqKipcN2BXbDckRjFGLTckJCIzY0wkZSpbQUNJS0YxRi03JCQiM2VubW1tKlJSTCRGMUYtNyQkIjMkem1tVHZKZ2EkRjFGLTckJCIzXU1MZTl0T2NQRjFGLTckJCIzMSwrK11Ra1xSRjFGLTckJCIzek1MJDNkZzY8JUYxRi03JCQiMyV5bW1tdyhHcFZGMUYtNyQkIjNCKytEIm9LMGUlRjFGLTckJCIzNSwrdj01cyN5JUYxRi03JCQiIiZGLEYtLSUmQ09MT1JHNiYlJFJHQkckIiM1ISIiJEYsRmlibEZqYmwtJStBWEVTTEFCRUxTRzYkUSJ4NiJRInlGX2NsLSUlVklFV0c2JDskISNdRmlibCQiI11GaWJsOyRGaHVGaWJsJCIjU0ZpYmw=TTdSMApJNVJUQUJMRV9TQVZFLzI0NDk5NDIwWCwlKWFueXRoaW5nRzYiNiJbZ2whIiUhISEjKyIjIiYhIiQiIiMhIiIkIiImRikiIiFGLCIiIkYqCiIiJEYoRiYKTTdSMApJNFJUQUJMRV9TQVZFLzI3NDI4NDBYKiUpYW55dGhpbmdHNiI2IltnbCEjJSEhISIjIiMhIiIiIiJGJgo=