/* curveFitting.h - Library for fitting curves to given points using Least Squares method, with Cramer's rule used to solve the linear equation. Max polynomial order 20. Created by Rowan Easter-Robinson, August 23, 2018. Released into the public domain. */ #include #include "curveFitting.h" void printMat(const char *s, ld*m, int n){ Serial.println(s); char buf[40]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { snprintf(buf, 40, "%30.4f\t", m[i*n+j]); Serial.print(buf); } Serial.println(); } } void showmat(const char *s, ld **m, int n){ Serial.println(s); char buf[40]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++){ snprintf(buf, 40, "%30.4f\t", m[i][j]); Serial.print(buf); } Serial.println(); } } void cpyArray(ld *src, ld*dest, int n){ for (int i = 0; i < n*n; i++){ dest[i] = src[i]; } } void subCol(ld *mat, ld* sub, uint8_t coln, uint8_t n){ if (coln >= n) return; for (int i = 0; i < n; i++){ mat[(i*n)+coln] = sub[i]; } } /*Determinant algorithm taken from https://codeforwin.org/2015/08/c-program-to-find-determinant-of-matrix.html */ int trianglize(ld **m, int n) { int sign = 1; for (int i = 0; i < n; i++) { int max = 0; for (int row = i; row < n; row++) if (fabs(m[row][i]) > fabs(m[max][i])) max = row; if (max) { sign = -sign; ld *tmp = m[i]; m[i] = m[max], m[max] = tmp; } if (!m[i][i]) return 0; for (int row = i + 1; row < n; row++) { ld r = m[row][i] / m[i][i]; if (!r) continue; for (int col = i; col < n; col ++) m[row][col] -= m[i][col] * r; } } return sign; } ld det(ld *in, int n, uint8_t prnt) { ld *m[n]; m[0] = in; for (int i = 1; i < n; i++) m[i] = m[i - 1] + n; if(prnt) showmat("Matrix", m, n); int sign = trianglize(m, n); if (!sign) return 0; if(prnt) showmat("Upper triangle", m, n); ld p = 1; for (int i = 0; i < n; i++) p *= m[i][i]; return p * sign; } /*End of Determinant algorithm*/ //Raise x to power ld curveFitPower(ld base, int exponent){ if (exponent == 0){ return 1; } else { ld val = base; for (int i = 1; i < exponent; i++){ val = val * base; } return val; } } int fitCurve (int order, int nPoints, ld py[], int nCoeffs, ld *coeffs) { uint8_t maxOrder = MAX_ORDER; if (nCoeffs != order + 1) return ORDER_AND_NCOEFFS_DO_NOT_MATCH; // no of coefficients is one larger than the order of the equation if (nCoeffs > maxOrder || nCoeffs < 2) return ORDER_INCORRECT; //matrix memory hard coded for max of 20 order, which is huge if (nPoints < 1) return NPOINTS_INCORRECT; //Npoints needs to be positive and nonzero int i, j; ld T[MAX_ORDER] = {0}; //Values to generate RHS of linear equation ld S[MAX_ORDER*2+1] = {0}; //Values for LHS and RHS of linear equation ld denom; //denominator for Cramer's rule, determinant of LHS linear equation ld x, y; ld px[nPoints]; //Generate X values, from 0 to n for (i=0; i maxOrder || nCoeffs < 2) return ORDER_INCORRECT; //Matrix memory hard coded for max of 20 order, which is huge if (nPoints < 1) return NPOINTS_INCORRECT; //Npoints needs to be positive and nonzero int i, j; ld T[MAX_ORDER] = {0}; //Values to generate RHS of linear equation ld S[MAX_ORDER*2+1] = {0}; //Values for LHS and RHS of linear equation ld denom; //denominator for Cramer's rule, determinant of LHS linear equation ld x, y; for (i=0; i