function CubicSpline.AtTime(Z,t)local u=#Z.Points local B=math.clamp(t,0,u)local a=math.floor(B)local x=B-a local A=a%(u-1)+1 local b,g,Q,R=unpack(Z.Coefficients)return((b[A]+g[A]*x)+(Q[A]*x)*x)+((R[A]*x)*x)*x end function CubicSpline.AtPercentage(Z,t)local u=t*Z.TotalLength local B=Z.Lengths if t>=1 then return Z.Points[#Z.Points]end local a=1 while u>B[a]do u=u-B[a]a=a+1 end local x=u/B[a]for t=1,NEWTON_N,1 do x=x-(integrate(Z,a,x)-u)/arcLengthIntegrand(Z,a,x)end return Z:AtTime((a-1)+x)end
-- Public Functions

function CubicSpline:AtTime(t)
	local n = #self.Points
	local ct = math.clamp(t, 0, n)
	local floor = math.floor(ct)
	local ft = ct - floor

	local spline = (floor % (n - 1)) + 1
	local a, b, c, d = unpack(self.Coefficients)

	return a[spline] + b[spline] * ft + c[spline] * ft * ft + d[spline] * ft * ft * ft
end

function CubicSpline:AtPercentage(p)
	local t = p * self.TotalLength
	local lengths = self.Lengths

	if p >= 1 then
		return self.Points[#self.Points]
	end

	local spline = 1
	while t > lengths[spline] do
		t = t - lengths[spline]
		spline = spline + 1
	end

	local s = t / lengths[spline]

	for i = 1, NEWTON_N do
		s = s - (integrate(self, spline, s) - t) / arcLengthIntegrand(self, spline, s)
	end

	return self:AtTime((spline - 1) + s)
end
