1*5f80ce2aSJacob Faibussowitsch #include <petsc/private/petscimpl.h> 2bebf13c0SMatthew G. Knepley #include <petscblaslapack.h> 3bebf13c0SMatthew G. Knepley 4bebf13c0SMatthew G. Knepley /*@C 5bebf13c0SMatthew G. Knepley PetscLinearRegression - Gives the best least-squares linear fit to some x-y data points 6bebf13c0SMatthew G. Knepley 7bebf13c0SMatthew G. Knepley Input Parameters: 8bebf13c0SMatthew G. Knepley + n - The number of points 9bebf13c0SMatthew G. Knepley . x - The x-values 10bebf13c0SMatthew G. Knepley - y - The y-values 11bebf13c0SMatthew G. Knepley 12bebf13c0SMatthew G. Knepley Output Parameters: 13bebf13c0SMatthew G. Knepley + slope - The slope of the best-fit line 14bebf13c0SMatthew G. Knepley - intercept - The y-intercept of the best-fit line 15bebf13c0SMatthew G. Knepley 16bebf13c0SMatthew G. Knepley Level: intermediate 17bebf13c0SMatthew G. Knepley 18bebf13c0SMatthew G. Knepley .seealso: PetscConvEstGetConvRate() 19bebf13c0SMatthew G. Knepley @*/ 20bebf13c0SMatthew G. Knepley PetscErrorCode PetscLinearRegression(PetscInt n, const PetscReal x[], const PetscReal y[], PetscReal *slope, PetscReal *intercept) 21bebf13c0SMatthew G. Knepley { 22bebf13c0SMatthew G. Knepley PetscScalar H[4]; 23bebf13c0SMatthew G. Knepley PetscReal *X, *Y, beta[2]; 24bebf13c0SMatthew G. Knepley 25bebf13c0SMatthew G. Knepley PetscFunctionBegin; 26*5f80ce2aSJacob Faibussowitsch if (n) { 27*5f80ce2aSJacob Faibussowitsch PetscValidRealPointer(x,2); 28*5f80ce2aSJacob Faibussowitsch PetscValidRealPointer(y,3); 29*5f80ce2aSJacob Faibussowitsch } 30*5f80ce2aSJacob Faibussowitsch PetscValidRealPointer(slope,4); 31*5f80ce2aSJacob Faibussowitsch PetscValidRealPointer(intercept,5); 32*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(n*2, &X, n*2, &Y)); 33*5f80ce2aSJacob Faibussowitsch for (PetscInt k = 0; k < n; ++k) { 34bebf13c0SMatthew G. Knepley /* X[n,2] = [1, x] */ 35bebf13c0SMatthew G. Knepley X[k*2+0] = 1.0; 36bebf13c0SMatthew G. Knepley X[k*2+1] = x[k]; 37bebf13c0SMatthew G. Knepley } 38bebf13c0SMatthew G. Knepley /* H = X^T X */ 39*5f80ce2aSJacob Faibussowitsch for (PetscInt i = 0; i < 2; ++i) { 40*5f80ce2aSJacob Faibussowitsch for (PetscInt j = 0; j < 2; ++j) { 41bebf13c0SMatthew G. Knepley H[i*2+j] = 0.0; 42*5f80ce2aSJacob Faibussowitsch for (PetscInt k = 0; k < n; ++k) H[i*2+j] += X[k*2+i] * X[k*2+j]; 43bebf13c0SMatthew G. Knepley } 44bebf13c0SMatthew G. Knepley } 45bebf13c0SMatthew G. Knepley /* H = (X^T X)^{-1} */ 46bebf13c0SMatthew G. Knepley { 47bebf13c0SMatthew G. Knepley PetscBLASInt two = 2, ipiv[2], info; 48bebf13c0SMatthew G. Knepley PetscScalar work[2]; 49bebf13c0SMatthew G. Knepley 50*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 51bebf13c0SMatthew G. Knepley PetscStackCallBLAS("LAPACKgetrf", LAPACKgetrf_(&two, &two, H, &two, ipiv, &info)); 52bebf13c0SMatthew G. Knepley PetscStackCallBLAS("LAPACKgetri", LAPACKgetri_(&two, H, &two, ipiv, work, &two, &info)); 53*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 54bebf13c0SMatthew G. Knepley } 55bebf13c0SMatthew G. Knepley /* Y = H X^T */ 56*5f80ce2aSJacob Faibussowitsch for (PetscInt i = 0; i < 2; ++i) { 57*5f80ce2aSJacob Faibussowitsch for (PetscInt k = 0; k < n; ++k) { 58bebf13c0SMatthew G. Knepley Y[i*n+k] = 0.0; 59*5f80ce2aSJacob Faibussowitsch for (PetscInt j = 0; j < 2; ++j) Y[i*n+k] += PetscRealPart(H[i*2+j]) * X[k*2+j]; 60bebf13c0SMatthew G. Knepley } 61bebf13c0SMatthew G. Knepley } 62bebf13c0SMatthew G. Knepley /* beta = Y error = [y-intercept, slope] */ 63*5f80ce2aSJacob Faibussowitsch for (PetscInt i = 0; i < 2; ++i) { 64bebf13c0SMatthew G. Knepley beta[i] = 0.0; 65*5f80ce2aSJacob Faibussowitsch for (PetscInt k = 0; k < n; ++k) beta[i] += Y[i*n+k] * y[k]; 66bebf13c0SMatthew G. Knepley } 67*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(X, Y)); 68bebf13c0SMatthew G. Knepley *intercept = beta[0]; 69bebf13c0SMatthew G. Knepley *slope = beta[1]; 70bebf13c0SMatthew G. Knepley PetscFunctionReturn(0); 71bebf13c0SMatthew G. Knepley } 72