| 3992 | |
| 3993 | template<typename typ> |
| 3994 | static void |
| 3995 | lstsq(char **args, npy_intp const *dimensions, npy_intp const *steps, |
| 3996 | void *NPY_UNUSED(func)) |
| 3997 | { |
| 3998 | using ftyp = fortran_type_t<typ>; |
| 3999 | using basetyp = basetype_t<typ>; |
| 4000 | GELSD_PARAMS_t<ftyp> params; |
| 4001 | int error_occurred = get_fp_invalid_and_clear(); |
| 4002 | fortran_int n, m, nrhs; |
| 4003 | fortran_int excess; |
| 4004 | |
| 4005 | INIT_OUTER_LOOP_7 |
| 4006 | |
| 4007 | m = (fortran_int)dimensions[0]; |
| 4008 | n = (fortran_int)dimensions[1]; |
| 4009 | nrhs = (fortran_int)dimensions[2]; |
| 4010 | excess = m - n; |
| 4011 | |
| 4012 | if (init_gelsd(¶ms, m, n, nrhs, dispatch_scalar<ftyp>{})) { |
| 4013 | LINEARIZE_DATA_t a_in, b_in, x_out, s_out, r_out; |
| 4014 | |
| 4015 | init_linearize_data(&a_in, n, m, steps[1], steps[0]); |
| 4016 | init_linearize_data_ex(&b_in, nrhs, m, steps[3], steps[2], fortran_int_max(n, m)); |
| 4017 | init_linearize_data_ex(&x_out, nrhs, n, steps[5], steps[4], fortran_int_max(n, m)); |
| 4018 | init_linearize_data(&r_out, 1, nrhs, 1, steps[6]); |
| 4019 | init_linearize_data(&s_out, 1, fortran_int_min(n, m), 1, steps[7]); |
| 4020 | |
| 4021 | BEGIN_OUTER_LOOP_7 |
| 4022 | int not_ok; |
| 4023 | linearize_matrix((typ*)params.A, (typ*)args[0], &a_in); |
| 4024 | linearize_matrix((typ*)params.B, (typ*)args[1], &b_in); |
| 4025 | params.RCOND = (basetyp*)args[2]; |
| 4026 | not_ok = call_gelsd(¶ms); |
| 4027 | if (!not_ok) { |
| 4028 | delinearize_matrix((typ*)args[3], (typ*)params.B, &x_out); |
| 4029 | *(npy_int*) args[5] = params.RANK; |
| 4030 | delinearize_matrix((basetyp*)args[6], (basetyp*)params.S, &s_out); |
| 4031 | |
| 4032 | /* Note that linalg.lstsq discards this when excess == 0 */ |
| 4033 | if (excess >= 0 && params.RANK == n) { |
| 4034 | /* Compute the residuals as the square sum of each column */ |
| 4035 | int i; |
| 4036 | char *resid = args[4]; |
| 4037 | ftyp *components = (ftyp *)params.B + n; |
| 4038 | for (i = 0; i < nrhs; i++) { |
| 4039 | ftyp *vector = components + i*m; |
| 4040 | /* Numpy and fortran floating types are the same size, |
| 4041 | * so this cast is safe */ |
| 4042 | basetyp abs = abs2((typ *)vector, excess, |
| 4043 | dispatch_scalar<typ>{}); |
| 4044 | memcpy( |
| 4045 | resid + i*r_out.column_strides, |
| 4046 | &abs, sizeof(abs)); |
| 4047 | } |
| 4048 | } |
| 4049 | else { |
| 4050 | /* Note that this is always discarded by linalg.lstsq */ |
| 4051 | nan_matrix((basetyp*)args[4], &r_out); |
nothing calls this directly
no test coverage detected