private bool CoreBuildSpecial() { if (m_X.Count > 4) { return(false); } if (m_X.Count == 0) { m_A = new BigRational[] { BigRational.NaN }; m_B = new BigRational[] { 0 }; m_C = new BigRational[] { 0 }; m_D = new BigRational[] { 0 }; } else if (m_X.Count == 1) { m_A = new BigRational[] { m_Y[0] }; m_B = new BigRational[] { 0 }; m_C = new BigRational[] { 0 }; m_D = new BigRational[] { 0 }; } else if (m_X.Count == 2) { m_A = new BigRational[] { (m_Y[0] * m_X[1] - m_Y[1] * m_X[0]) / (m_X[1] - m_X[0]) }; m_B = new BigRational[] { (m_Y[1] - m_Y[0]) / (m_X[1] - m_X[0]) }; m_C = new BigRational[] { 0 }; m_D = new BigRational[] { 0 }; } else if (m_X.Count == 3) { BigRational[] s = MatrixLowLevel.Solve(new BigRational[][] { new BigRational[] { 1, m_X[0], m_X[0] * m_X[0], m_Y[0] }, new BigRational[] { 1, m_X[1], m_X[1] * m_X[1], m_Y[1] }, new BigRational[] { 1, m_X[2], m_X[2] * m_X[2], m_Y[2] }, }); m_A = new BigRational[] { s[0] }; m_B = new BigRational[] { s[1] }; m_C = new BigRational[] { s[2] }; m_D = new BigRational[] { 0 }; } else if (m_X.Count == 4) { BigRational[] s = MatrixLowLevel.Solve(new BigRational[][] { new BigRational[] { 1, m_X[0], m_X[0] * m_X[0], m_X[0] * m_X[0] * m_X[0], m_Y[0] }, new BigRational[] { 1, m_X[1], m_X[1] * m_X[1], m_X[1] * m_X[1] * m_X[1], m_Y[1] }, new BigRational[] { 1, m_X[2], m_X[2] * m_X[2], m_X[2] * m_X[2] * m_X[2], m_Y[2] }, new BigRational[] { 1, m_X[3], m_X[3] * m_X[3], m_X[3] * m_X[3] * m_X[3], m_Y[3] }, }); m_A = new BigRational[] { s[0] }; m_B = new BigRational[] { s[1] }; m_C = new BigRational[] { s[2] }; m_D = new BigRational[] { s[3] }; } return(true); }
// http://web.snauka.ru/issues/2015/05/53846 // https://en.wikipedia.org/wiki/Akima_spline private void CoreBuild() { if (CoreBuildSpecial()) { return; } int N = m_X.Count - 1; Dictionary <int, BigRational> m = new(); for (int i = 0; i < N; ++i) { m.Add(i, (m_Y[i + 1] - m_Y[i]) / (m_X[i + 1] - m_X[i])); } m.Add(-2, 3 * m[0] - 2 * m[1]); m.Add(-1, 2 * m[0] - 2 * m[1]); m.Add(N, 2 * m[N - 1] - 2 * m[N - 2]); m.Add(N + 1, 3 * m[N - 1] - 2 * m[N - 2]); BigRational[] s = new BigRational[N + 1]; for (int i = 0; i <= N; ++i) { s[i] = ((m[i + 1] - m[i]).Abs() * m[i - 1] + (m[i - 1] - m[i - 2]).Abs() * m[i]) / ((m[i + 1] - m[i]).Abs() + (m[i - 1] - m[i - 2]).Abs()); } for (int i = 0; i < N; ++i) { BigRational[][] mt = new BigRational[][] { new BigRational[] { 1, m_X[i], m_X[i] * m_X[i], m_X[i] * m_X[i] * m_X[i], m_Y[i] }, new BigRational[] { 1, m_X[i + 1], m_X[i + 1] * m_X[i + 1], m_X[i + 1] * m_X[i + 1] * m_X[i + 1], m_Y[i + 1] }, new BigRational[] { 0, 1, 2 * m_X[i], 3 * m_X[i] * m_X[i], s[i] }, new BigRational[] { 0, 1, 2 * m_X[i + 1], 3 * m_X[i + 1] * m_X[i + 1], s[i + 1] }, }; BigRational[] z = MatrixLowLevel.Solve(mt); m_A[i] = z[0]; m_B[i] = z[1]; m_C[i] = z[2]; m_D[i] = z[3]; } }
private void CoreBuild() { if (m_X.Count == 0) { m_A = new BigRational[] { BigRational.NaN }; m_Polynom = RationalPolynom.NaN; return; } else if (m_X.Count == 1) { m_A = new BigRational[] { m_Y[0] }; m_Polynom = new RationalPolynom(m_A); return; } BigRational[][] M = new BigRational[m_Y.Count][]; for (int r = 0; r < M.Length; ++r) { BigRational[] row = new BigRational[M.Length + 1]; row[M.Length] = m_Y[r]; BigRational x = m_X[r]; BigRational v = 1; for (int i = 0; i < M.Length; ++i) { row[i] = v; v *= x; } M[r] = row; } m_A = MatrixLowLevel.Solve(M); m_Polynom = new RationalPolynom(m_A); }
/// <summary> /// Reconstruct polynom from its values /// for P(0) = 1, P(1) = ?, P(2) = 9, P(3) = 16, P(4) = 25, P(5) = ? /// var result = Reconstruct(0, new BigRational[] {1, BigRational.NaN, 9, 16, 25, BigRational.NaN}); /// </summary> /// <param name="startAt">starting point</param> /// <param name="values">values (put BigRational.NaN for abscent points)</param> /// <returns></returns> public static RationalPolynom Reconstruct(int startAt, IEnumerable <BigRational> values) { if (values is null) { throw new ArgumentNullException(nameof(values)); } var points = values .Select((v, i) => (x: (BigRational)i + startAt, y: v)) .Where(item => !item.y.IsNaN) .ToArray(); if (points.Length == 0) { return(NaN); } BigRational[][] M = new BigRational[points.Length][]; for (int r = 0; r < M.Length; ++r) { BigRational[] row = new BigRational[M.Length + 1]; M[r] = row; row[M.Length] = points[r].y; BigRational x = points[r].x; BigRational v = 1; for (int c = 0; c < M.Length; ++c) { row[c] = v; v *= x; } } return(new RationalPolynom(MatrixLowLevel.Solve(M))); }