local function U(U,L,H)local q,u,h,Q=unpack(U.Coefficients)local z=(u[L]+(2*h[L])*H)+((3*Q[L])*H)*H return z.Magnitude end local function L(L,H,q)local u=q/SIMPSON_N local h,Q,z=U(L,H,q),0,0 for q=0,SIMPSON_N-1,1 do local h=q*u if q%2==0 then z=z+U(L,H,h)else Q=Q+U(L,H,h)end end return(u*((h+2*z)+4*Q))/3 end local function H(U,L,H)local q=#U local u,h,Q,z={unpack(U)},{},{},{}local e={}e[1]=3*(u[2]-u[1])-3*L e[q]=3*H-3*(u[q]-u[q-1])for U=2,q-1,1 do e[U]=3*((u[U+1]-2*u[U])+u[U-1])end local t,K,M={2},{.5},{e[1]/2}for U=2,q-1,1 do t[U]=4-K[U-1]K[U]=1/t[U]M[U]=(e[U]-M[U-1])/t[U]end t[q]=2-K[q-1]M[q]=(e[q]-M[q-1])/t[q]Q[q]=M[q]for L=q-1,1,-1 do Q[L]=M[L]-K[L]*Q[L+1]z[L]=(Q[L+1]-Q[L])/3 h[L]=((U[L+1]-U[L])-Q[L])-z[L]end return u,h,Q,z end local function q(U)local L=#U local H,q,u,h={unpack(U)},{},{},{}local Q={}for U=2,L-1,1 do Q[U]=3*((H[U+1]-2*H[U])+H[U-1])end local z=Vector3.new(0,10,0)local e,t,K={1},{0},{ZERO}e[L],K[L],u[L]=1,ZERO,ZERO for U=2,L-1,1 do e[U]=4-t[U-1]t[U]=1/e[U]K[U]=(Q[U]-K[U-1])/e[U]end for L=L-1,1,-1 do u[L]=K[L]-t[L]*u[L+1]h[L]=(u[L+1]-u[L])/3 q[L]=((U[L+1]-U[L])-u[L])-h[L]end return H,q,u,h end
-- Private Functions

local function arcLengthIntegrand(self, spline, t)
	local a, b, c, d = unpack(self.Coefficients)
	local dv = b[spline] + 2 * c[spline] * t + 3 * d[spline] * t * t
	return dv.Magnitude
end

local function integrate(self, spline, t)
	local h = t / SIMPSON_N
	local xi0, xi1, xi2 = arcLengthIntegrand(self, spline, t), 0, 0

	for i = 0, SIMPSON_N - 1 do
		local x = i * h
		if i % 2 == 0 then
			xi2 = xi2 + arcLengthIntegrand(self, spline, x)
		else
			xi1 = xi1 + arcLengthIntegrand(self, spline, x)
		end
	end

	return h * (xi0 + 2 * xi2 + 4 * xi1) / 3
end

local function clampedCubicSpline(p, fpo, fpn)
	local n = #p
	local a, b, c, d = { unpack(p) }, {}, {}, {}

	local aa = {}
	aa[1] = 3 * (a[2] - a[1]) - 3 * fpo
	aa[n] = 3 * fpn - 3 * (a[n] - a[n - 1])

	for i = 2, n - 1 do
		aa[i] = 3 * (a[i + 1] - 2 * a[i] + a[i - 1])
	end

	local l, mu, z = { 2 }, { 0.5 }, { aa[1] / 2 }

	for i = 2, n - 1 do
		l[i] = 4 - mu[i - 1]
		mu[i] = 1 / l[i]
		z[i] = (aa[i] - z[i - 1]) / l[i]
	end

	l[n] = 2 - mu[n - 1]
	z[n] = (aa[n] - z[n - 1]) / l[n]
	c[n] = z[n]

	for j = n - 1, 1, -1 do
		c[j] = z[j] - mu[j] * c[j + 1]
		d[j] = (c[j + 1] - c[j]) / 3
		b[j] = p[j + 1] - p[j] - c[j] - d[j]
	end

	return a, b, c, d
end

local function naturalCubicSpline(p)
	local n = #p
	local a, b, c, d = { unpack(p) }, {}, {}, {}

	local aa = {}

	for i = 2, n - 1 do
		aa[i] = 3 * (a[i + 1] - 2 * a[i] + a[i - 1])
	end

	local start = Vector3.new(0, 10, 0)
	local l, mu, z = { 1 }, { 0 }, { ZERO }
	l[n], z[n], c[n] = 1, ZERO, ZERO

	for i = 2, n - 1 do
		l[i] = 4 - mu[i - 1]
		mu[i] = 1 / l[i]
		z[i] = (aa[i] - z[i - 1]) / l[i]
	end

	for j = n - 1, 1, -1 do
		c[j] = z[j] - mu[j] * c[j + 1]
		d[j] = (c[j + 1] - c[j]) / 3
		b[j] = p[j + 1] - p[j] - c[j] - d[j]
	end

	return a, b, c, d
end
