/** * Clean up - free allocated matrices and vectors */ void clean_SingularValueDecomposition() { if (singular_values != NULL) { free_vector_double(singular_values); singular_values = NULL; } if (U_matrix != NULL) { int nu = Math_min(num_rows, num_columns); free_matrix_double(U_matrix, num_rows, nu); U_matrix = NULL; } if (V_matrix != NULL) { free_matrix_double(V_matrix, num_columns, num_columns); V_matrix = NULL; } }
/** Returns the diagonal matrix of singular values. @return S */ MatrixDouble svd_getS() { int i, j; if (S_matrix != NULL) free_matrix_double(S_matrix, num_columns, num_columns); S_matrix = matrix_double(num_columns, num_columns); for (i = 0; i < num_columns; i++) { for (j = 0; j < num_columns; j++) { S_matrix[i][j] = 0.0; } S_matrix[i][i] = singular_values[i]; } return (S_matrix); }
int main(int argc, const char * argv[]) { if ( argc != 12 ) { /* We print argv[0] assuming it is the program name */ printf( "usage: %s -DATA -EMBED_SIZE -LR -MAX_ITER -NUM_THREAD -ALPHA -DISTANCE -OCSAMPLE -ONSAMPLE -K -C\n", argv[0] ); } else { const char *indir = argv[1]; embed_size = atoi(argv[2]); lr = atof(argv[3]); max_iter = atoi(argv[4]); num_threads = atoi(argv[5]); alpha = atof(argv[6]); distance = atoi(argv[7]); ocsample = atoi(argv[8]); onsample = atoi(argv[9]); K = atoi(argv[10]); C = atof(argv[11]); char filename[BUFFER_SIZE]; time_t t; srand((unsigned) time(&t)); /* Load number of features, types, and mentions */ snprintf(filename, sizeof(filename), "Intermediate/%s/feature.txt", indir); feature_count = count_lines(filename); feautre_name = read_names(filename, feature_count); snprintf(filename, sizeof(filename), "Intermediate/%s/type.txt", indir); type_count = count_lines(filename); type_name = read_names(filename, type_count); snprintf(filename, sizeof(filename), "Intermediate/%s/mention.txt", indir); mention_count = count_lines(filename); printf("type: %d, feature: %d, mention: %d\n",type_count, feature_count, mention_count); /* Load type hierarchy */ snprintf(filename, sizeof(filename), "Intermediate/%s/supertype.txt", indir); hierarchy = new Hierarchy(filename); /* Load edit distances between types */ if (distance == 2) { // shortest path length snprintf(filename, sizeof(filename), "Intermediate/%s/type_type_sp.txt", indir); }else{ snprintf(filename, sizeof(filename), "Intermediate/%s/type_type_kb.txt", indir); } weights = load_weights(filename, type_count, alpha, distance, hierarchy); /* Initialize matrix A and B*/ A = malloc_matrix_double(feature_count, embed_size); B = malloc_matrix_double(type_count, embed_size); printf("Fininsh initialize matrix A and B\n"); Ag = (double *)calloc(feature_count * embed_size, sizeof(double)); Bg = (double *)calloc(type_count * embed_size, sizeof(double)); An = (int *)calloc(feature_count, sizeof(int)); Bn = (int *)calloc(type_count, sizeof(int)); snprintf(filename, sizeof(filename), "Intermediate/%s/mention_feature.txt", indir); train_x = (int **)malloc(mention_count * sizeof(int *)); x_count = (int *)calloc(mention_count, sizeof(int)); for(int i = 0; i < mention_count; i++){ train_x[i] = (int *)calloc(BUFFER_SIZE, sizeof(int)); if(train_x[i] == NULL){ printf("out of memory!\n"); exit(EXIT_FAILURE); } } load_data(filename, train_x, x_count); snprintf(filename, sizeof(filename), "Intermediate/%s/mention_type.txt", indir); train_y = (int **)malloc(mention_count * sizeof(int *)); y_count = (int *)calloc(mention_count, sizeof(int)); for(int i = 0; i < mention_count; i++){ train_y[i] = (int *)calloc(SMALL_BUFFER_SIZE, sizeof(int)); if(train_y[i] == NULL){ printf("out of memory!\n"); exit(EXIT_FAILURE); } } std::vector<std::vector<int> >clean_and_noise=load_data_noise(filename, train_y, y_count, hierarchy, mention_count); mention_set = clean_and_noise[0]; mention_set_noise = clean_and_noise[1]; printf("Start training process\n"); printf("Clean examples: %d, noise examples: %d\n", (int)mention_set.size(), (int)mention_set_noise.size()); long a; pthread_t *pt = (pthread_t *)malloc(num_threads * sizeof(pthread_t)); for (iter = 0; iter != max_iter; iter++) { error = 0; std::random_shuffle(mention_set.begin(), mention_set.end()); std::random_shuffle(mention_set_noise.begin(), mention_set_noise.end()); for (a = 0; a < num_threads; a++) pthread_create(&pt[a], NULL, train_BCD_thread, (void *)a); for (a = 0; a < num_threads; a++) pthread_join(pt[a], NULL); printf("Iter:%d, error:%f\n",iter, error); update_embedding(); } /* Save matrix A and B*/ snprintf(filename, sizeof(filename), "Results/%s/emb_pl_warp_bipartite_feature.txt", indir); print_matrix(filename, A, feature_count, embed_size, feautre_name); snprintf(filename, sizeof(filename), "Results/%s/emb_pl_warp_bipartite_type.txt", indir); print_matrix(filename, B, type_count, embed_size, type_name); free_matrix_double(A); return 0; } }
double * G_N4(int **edges_array,int **tri_edges,int *number_per_row,int *tri_number,int vertices,int edges,int *pos1,int *pos2,int *position) { int source=0; double **edge_dependency=zeros_double(edges/2,3); //if(co==1)print_2_matrix(tri_edges,edges/2,2); while(source<vertices){ double *vertex_dependency=init_matrix_double(vertices); int *distance=init_matrix(vertices); int i; for(i=0;i<vertices;i++) distance[i]--; int *weight=init_matrix(vertices); int *queue=init_matrix(vertices); int que_in=0,que_out=0; distance[source]=0; weight[source]=1; queue[que_in]=source; que_in++; int **edges_order=zeros(edges/2,2); i=0; while(que_in-que_out>0){ int v=queue[que_out]; que_out++; int step=0,pos=0; while(step<v){//! pos+=number_per_row[step]; step++; }//if(a&&co==1){printf("%d\n",v);a--;} while(pos<edges&&edges_array[pos][0]==v){ int w=edges_array[pos][1]; if(distance[w]<0){ queue[que_in]=w; que_in++; distance[w]=distance[v]+1; } if(distance[w]==distance[v]+1){ weight[w]+=weight[v]; edges_order[i][0]=v; edges_order[i][1]=w; i++; } pos++; } } //if(co==1&&a){print_matrix(weight,vertices);print_matrix(distance,vertices);print_2_matrix(edges_order,edges/2,2);a--;} i--; while(i>=0){ int w=edges_order[i][1]; while(i>=0&&edges_order[i][1]==w){ int v=edges_order[i][0]; double partialdependency=weight[v]*1.0/weight[w]; //if(a&&co==1){printf("%f %d %d\n",partialdependency,weight[v],weight[w]);a--;} partialdependency=partialdependency*(1+vertex_dependency[w]); vertex_dependency[v]+=partialdependency; int row_here=w; int col_here=v; if(w>v){ row_here=v; col_here=w; } int row=0,place=0; while(row<row_here){//! place+=tri_number[row]; row++; } while(place<edges/2&&tri_edges[place][1]!=col_here) place++; edge_dependency[place][2] = edge_dependency[place][2]+ partialdependency; edge_dependency[place][0] = row_here; edge_dependency[place][1] = col_here; i--; } }//if(a&&co==1){print_2_matrix_double(edge_dependency,edges/2,3);a--;} source++; free_matrix_double(vertex_dependency); free_matrix(queue); free_matrix(weight); free_matrix(distance); free_2_matrix(edges_order,edges/2); } double max=edge_dependency[0][2]; int step = 0; *position = 0; while(step < edges/2){ if(edge_dependency[step][2] > max){ *position = step; max = edge_dependency[step][2]; } step = step + 1; } *pos1 = 0; *pos2 = 0; step = 0; double *temp=row_num_double(edge_dependency,*position,edges/2,3); while(step < edges){ if(edges_array[step][0]==temp[0]&&edges_array[step][1]==temp[1]) *pos1 = step; if(edges_array[step][0]==temp[1]&&edges_array[step][1] == temp[0]) *pos2 = step; if(*pos1 > 0 && *pos2 > 0) break; step = step + 1; } //if(a&&co==1){print_2_matrix_double(edge_dependency,edges/2,3);a--;} //if(a&&co==1){print_matrix_double(row_num_double(edge_dependency,*position,edges/2,3),3);a--;} free_2_matrix_double(edge_dependency,edges/2); //return row_num_double(edge_dependency,*position,edges/2,3); return temp; }
Ellipsoid3D CalcErrorEllipsoid(Mtrx3D *pcov, double del_chi_2) { int ndx, iSwitched; MatrixDouble A_matrix, V_matrix; VectorDouble W_vector; double wtemp, vtemp; Ellipsoid3D ell; int ierr = 0; /* allocate A mtrx */ A_matrix = matrix_double(3, 3); /* load A matrix in NumRec format */ A_matrix[0][0] = pcov->xx; A_matrix[0][1] = A_matrix[1][0] = pcov->xy; A_matrix[0][2] = A_matrix[2][0] = pcov->xz; A_matrix[1][1] = pcov->yy; A_matrix[1][2] = A_matrix[2][1] = pcov->yz; A_matrix[2][2] = pcov->zz; /* allocate V mtrx and W vector */ V_matrix = matrix_double(3, 3); W_vector = vector_double(3); /* do SVD */ //if ((istat = nll_svdcmp0(A_matrix, 3, 3, W_vector, V_matrix)) < 0) { svd_helper(A_matrix, 3, 3, W_vector, V_matrix); if (W_vector[0] < SMALL_DOUBLE || W_vector[1] < SMALL_DOUBLE || W_vector[2] < SMALL_DOUBLE) { fprintf(stderr, "ERROR: invalid SVD singular value for confidence ellipsoids."); ierr = 1; } else { /* sort by singular values W */ iSwitched = 1; while (iSwitched) { iSwitched = 0; for (ndx = 0; ndx < 2; ndx++) { if (W_vector[ndx] > W_vector[ndx + 1]) { wtemp = W_vector[ndx]; W_vector[ndx] = W_vector[ndx + 1]; W_vector[ndx + 1] = wtemp; vtemp = V_matrix[0][ndx]; V_matrix[0][ndx] = V_matrix[0][ndx + 1]; V_matrix[0][ndx + 1] = vtemp; vtemp = V_matrix[1][ndx]; V_matrix[1][ndx] = V_matrix[1][ndx + 1]; V_matrix[1][ndx + 1] = vtemp; vtemp = V_matrix[2][ndx]; V_matrix[2][ndx] = V_matrix[2][ndx + 1]; V_matrix[2][ndx + 1] = vtemp; iSwitched = 1; } } } /* calculate ellipsoid axes */ /* length: w in Num Rec, 2nd ed, fig 15.6.5 must be replaced by 1/sqrt(w) since we are using SVD of Cov mtrx and not SVD of A mtrx (compare eqns 2.6.1 & 15.6.10) */ ell.az1 = atan2(V_matrix[0][0], V_matrix[1][0]) * RA2DE; if (ell.az1 < 0.0) ell.az1 += 360.0; ell.dip1 = asin(V_matrix[2][0]) * RA2DE; ell.len1 = sqrt(del_chi_2) / sqrt(1.0 / W_vector[0]); ell.az2 = atan2(V_matrix[0][1], V_matrix[1][1]) * RA2DE; if (ell.az2 < 0.0) ell.az2 += 360.0; ell.dip2 = asin(V_matrix[2][1]) * RA2DE; ell.len2 = sqrt(del_chi_2) / sqrt(1.0 / W_vector[1]); ell.len3 = sqrt(del_chi_2) / sqrt(1.0 / W_vector[2]); } free_matrix_double(A_matrix, 3, 3); free_matrix_double(V_matrix, 3, 3); free_vector_double(W_vector); if (ierr) { Ellipsoid3D EllipsoidNULL = {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}; return (EllipsoidNULL); } return (ell); }
void run(int dat, int opt, int exe, int band_size, int x_axis){ alloc_matrix_double(&a,MATRIX_SIZE); alloc_vector_double(&b,MATRIX_SIZE); alloc_vector_double(&x,MATRIX_SIZE); alloc_matrix_double(&d_a,MATRIX_SIZE); alloc_vector_double(&d_b,MATRIX_SIZE); alloc_vector_double(&d_x,MATRIX_SIZE); generate_linear_system(a,x,b, 1.0, band_size); if(exe & (GENP | GENP_ITERATION)){ int dim = MATRIX_SIZE; int inc = 1; double minus1 = -1; copy_linear_system(d_a,d_x,d_b, a,x,b); alloc_vector_double(&d_x_np, MATRIX_SIZE); solve_no_pivoting(d_a, d_b, d_x_np, NULL, NULL); daxpy_(&dim, &minus1, d_x, &inc, d_x_np, &inc); d_np_err = dnrm2_(&dim, d_x_np, &inc); free_vector_double(&d_x_np); } if(exe & (RDFT | RDFT_ITERATION)){ int dim = MATRIX_SIZE; int inc = 1; double minus1 = -1; dcomplex *fra=NULL, *frb=NULL, *r=NULL; copy_linear_system(d_a,d_x,d_b, a,x,b); alloc_vector_double(&d_x_rdft, MATRIX_SIZE); alloc_vector_double(&d_x_rdft_iter, MATRIX_SIZE); alloc_vector_double(&d_x_rdft_iter_another, MATRIX_SIZE); alloc_matrix_complex_double(&fra, MATRIX_SIZE); alloc_vector_complex_double(&r, MATRIX_SIZE); alloc_vector_complex_double(&frb, MATRIX_SIZE); //rdft_original_slow(d_a, d_b, d_x_rdft, d_x_rdft_iter, d_x_rdft_iter_another); fftw_rdft_original(d_a, d_b, d_x_rdft, d_x_rdft_iter, d_x_rdft_iter_another, fra, r, frb); daxpy_(&dim, &minus1, d_x, &inc, d_x_rdft, &inc); daxpy_(&dim, &minus1, d_x, &inc, d_x_rdft_iter, &inc); daxpy_(&dim, &minus1, d_x, &inc, d_x_rdft_iter_another, &inc); d_rdft_err = dnrm2_(&dim, d_x_rdft, &inc); d_rdft_iter_err = dnrm2_(&dim, d_x_rdft_iter, &inc); d_rdft_iter_another_err = dnrm2_(&dim, d_x_rdft_iter_another, &inc); free_matrix_complex_double(&fra); free_vector_complex_double(&r); free_vector_complex_double(&frb); free_vector_double(&d_x_rdft); free_vector_double(&d_x_rdft_iter); free_vector_double(&d_x_rdft_iter_another); } /* if(exe & (RDFT_PERM | RDFT_PERM_ITERATION)){} if(exe & (RDFT_GIVENS | RDFT_GIVENS_ITERATION)){} */ if(exe & (RDFT_GIVENS_TWO | RDFT_GIVENS_TWO_ITERATION)){ int dim = MATRIX_SIZE; int inc = 1; double minus1 = -1; dcomplex *fra,*r,*frb; double *ass; copy_linear_system(d_a,d_x,d_b, a,x,b); alloc_vector_double(&d_x_rdft_givens_two, MATRIX_SIZE); alloc_vector_double(&d_x_rdft_givens_two_iter, MATRIX_SIZE); alloc_vector_double(&d_x_rdft_givens_two_iter_another, MATRIX_SIZE); alloc_matrix_complex_double(&fra, MATRIX_SIZE); alloc_vector_complex_double(&r, MATRIX_SIZE); alloc_vector_complex_double(&frb, MATRIX_SIZE); alloc_matrix_double(&ass, MATRIX_SIZE); fftw_rdft_right_two_givens(d_a, d_b, d_x_rdft_givens_two, d_x_rdft_givens_two_iter, d_x_rdft_givens_two_iter_another, fra,r,frb, ass); daxpy_(&dim, &minus1, d_x, &inc, d_x_rdft_givens_two, &inc); daxpy_(&dim, &minus1, d_x, &inc, d_x_rdft_givens_two_iter, &inc); daxpy_(&dim, &minus1, d_x, &inc, d_x_rdft_givens_two_iter_another, &inc); d_rdft_givens_two_err = dnrm2_(&dim, d_x_rdft_givens_two, &inc); d_rdft_givens_two_iter_err = dnrm2_(&dim, d_x_rdft_givens_two_iter, &inc); d_rdft_givens_two_iter_another_err = dnrm2_(&dim, d_x_rdft_givens_two_iter_another, &inc); free_matrix_complex_double(&fra); free_vector_complex_double(&r); free_matrix_complex_double(&frb); free_matrix_double(&ass); free_vector_double(&d_x_rdft_givens_two); free_vector_double(&d_x_rdft_givens_two_iter); free_vector_double(&d_x_rdft_givens_two_iter_another); } /* if(exe & (RDFT_BOTH_GIVENS | RDFT_BOTH_GIVENS_ITERATION)){} */ if(exe & (GAUSS | GAUSS_ITERATION)){ int dim = MATRIX_SIZE; int inc = 1; double minus1 = -1; double *g=NULL,*ga=NULL; copy_linear_system(d_a,d_x,d_b, a,x,b); alloc_vector_double(&d_x_gauss, MATRIX_SIZE); alloc_vector_double(&d_x_gauss_iter, MATRIX_SIZE); alloc_vector_double(&d_x_gauss_iter_another, MATRIX_SIZE); alloc_matrix_double(&ga, MATRIX_SIZE); alloc_matrix_double(&g, MATRIX_SIZE); solve_with_gauss_iteration_double(d_a, d_b, d_x_gauss, d_x_gauss_iter, d_x_gauss_iter_another, g,ga); daxpy_(&dim, &minus1, d_x, &inc, d_x_gauss, &inc); daxpy_(&dim, &minus1, d_x, &inc, d_x_gauss_iter, &inc); daxpy_(&dim, &minus1, d_x, &inc, d_x_gauss_iter_another, &inc); d_gauss_err = dnrm2_(&dim, d_x_gauss, &inc); d_gauss_iter_err = dnrm2_(&dim, d_x_gauss_iter, &inc); d_gauss_iter_another_err = dnrm2_(&dim, d_x_gauss_iter_another, &inc); free_matrix_double(&g); free_matrix_double(&ga); free_vector_double(&d_x_gauss); free_vector_double(&d_x_gauss_iter); free_vector_double(&d_x_gauss_iter_another); } if(exe & (PP | PP_ITERATION)){ int dim = MATRIX_SIZE; int inc = 1; double minus1 = -1; copy_linear_system(d_a,d_x,d_b, a,x,b); alloc_vector_double(&d_x_pp, MATRIX_SIZE); solve_with_partial_pivot(d_a, d_b, d_x_pp, NULL, NULL); daxpy_(&dim, &minus1, d_x, &inc, d_x_pp, &inc); d_pp_err = dnrm2_(&dim, d_x_pp, &inc); free_vector_double(&d_x_pp); } free_matrix_double(&d_a); free_vector_double(&d_b); free_vector_double(&d_x); free_matrix_double(&a); free_vector_double(&b); free_vector_double(&x); // opt // 1: graph data // 2: readable data if(opt == 1){ // graph data printf("%d ", x_axis); printf("%d ", band_size); printf("%d ", 2*band_size-1); print_double(d_rdft_err); printf(" "); print_double(d_rdft_iter_err); printf(" "); print_double(d_rdft_iter_another_err); printf(" "); print_double(d_rdft_perm_err); printf(" "); print_double(d_rdft_perm_iter_err); printf(" "); print_double(d_rdft_perm_iter_another_err); printf(" "); print_double(d_rdft_givens_err); printf(" "); print_double(d_rdft_givens_iter_err); printf(" "); print_double(d_rdft_givens_iter_another_err); printf(" "); print_double(d_rdft_givens_two_err); printf(" "); print_double(d_rdft_givens_two_iter_err); printf(" "); print_double(d_rdft_givens_two_iter_another_err); printf(" "); print_double(d_rdft_both_givens_err); printf(" "); print_double(d_rdft_both_givens_iter_err); printf(" "); print_double(d_rdft_both_givens_iter_another_err); printf(" "); print_double(d_gauss_err); printf(" "); print_double(d_gauss_iter_err); printf(" "); print_double(d_gauss_iter_another_err); printf(" "); print_double(d_pp_err); printf(" "); print_double(d_pp_iter_err); printf(" "); print_double(d_pp_iter_another_err); printf(" "); print_double(d_np_err); printf("\n"); }else if(opt == 2){ if(exe & RDFT){ printf("RDFT :"); print_double(d_rdft_err); printf("\n"); } if(exe & RDFT_ITERATION){ printf("RDFT iteration :"); print_double(d_rdft_iter_err); printf("\n"); printf("RDFT iteration :"); print_double(d_rdft_iter_another_err); printf("\n"); } if(exe & RDFT_PERM){ printf("RDFT PERM :"); print_double(d_rdft_perm_err); printf("\n"); } if(exe & RDFT_PERM_ITERATION){ printf("RDFT PERM iteration:"); print_double(d_rdft_perm_iter_err); printf("\n"); printf("RDFT PERM iteration:"); print_double(d_rdft_perm_iter_another_err); printf("\n"); } if(exe & RDFT_GIVENS){ printf("RDFT GVN :"); print_double(d_rdft_givens_err); printf("\n"); } if(exe & RDFT_GIVENS_ITERATION){ printf("RDFT GVN iteration :"); print_double(d_rdft_givens_iter_err); printf("\n"); printf("RDFT GVN iteration :"); print_double(d_rdft_givens_iter_another_err); printf("\n"); } if(exe & RDFT_GIVENS_TWO){ printf("RDFT GTWO :"); print_double(d_rdft_givens_two_err); printf("\n"); } if(exe & RDFT_GIVENS_TWO_ITERATION){ printf("RDFT GTWO iteration:"); print_double(d_rdft_givens_two_iter_err); printf("\n"); printf("RDFT GTWO iteration:"); print_double(d_rdft_givens_two_iter_another_err); printf("\n"); } if(exe & RDFT_BOTH_GIVENS){ printf("RDFT BOTH :"); print_double(d_rdft_both_givens_err); printf("\n"); } if(exe & RDFT_BOTH_GIVENS_ITERATION){ printf("RDFT BOTH iteration:"); print_double(d_rdft_both_givens_iter_err); printf("\n"); printf("RDFT BOTH iteration:"); print_double(d_rdft_both_givens_iter_another_err); printf("\n"); } if(exe & GAUSS){ printf("GAUSS :"); print_double(d_gauss_err); printf("\n"); } if(exe & GAUSS_ITERATION){ printf("GAUSS iteration :"); print_double(d_gauss_iter_err); printf("\n"); printf("GAUSS iteration :"); print_double(d_gauss_iter_another_err); printf("\n"); } if(exe & GENP){ printf("GENP :"); print_double(d_np_err); printf("\n"); } if(exe & GENP_ITERATION){ printf("GENP :"); print_double(d_np_iter_err); printf("\n"); printf("GENP :"); print_double(d_np_iter_another_err); printf("\n"); } if(exe & PP){ printf("Partial Pivot :"); print_double(d_pp_err); printf("\n"); } } }
/** Constructs and returns a new singular value decomposition object; The decomposed matrices can be retrieved via instance methods of the returned decomposition object. @param A A rectangular matrix. @return A decomposition object to access <tt>U</tt>, <tt>S</tt> and <tt>V</tt>. @throws IllegalArgumentException if <tt>A.rows() < A.columns()</tt>. */ void SingularValueDecomposition(MatrixDouble A_matrix_orig, int nrows, int ncolumns) { int i, j, k; //Property.DEFAULT.checkRectangular(Arg); // Derived from LINPACK code. // Initialize. num_rows = nrows; num_columns = ncolumns; // make local copy of original A matrix MatrixDouble A_matrix = matrix_double(num_rows, num_columns); for (i = 0; i < num_rows; i++) { for (j = 0; j < num_columns; j++) { A_matrix[i][j] = A_matrix_orig[i][j]; } } clean_SingularValueDecomposition(); int nu = Math_min(num_rows, num_columns); singular_values = vector_double(Math_min(num_rows + 1, num_columns)); U_matrix = matrix_double(num_rows, nu); V_matrix = matrix_double(num_columns, num_columns); double *e = calloc(num_columns, sizeof (double)); double *work = calloc(num_rows, sizeof (double)); int wantu = 1; int wantv = 1; // Reduce A to bidiagonal form, storing the diagonal elements // in s and the super-diagonal elements in e. int nct = Math_min(num_rows - 1, num_columns); int nrt = Math_max(0, Math_min(num_columns - 2, num_rows)); for (k = 0; k < Math_max(nct, nrt); k++) { if (k < nct) { // Compute the transformation for the k-th column and // place the k-th diagonal in s[k]. // Compute 2-norm of k-th column without under/overflow. singular_values[k] = 0; for (i = k; i < num_rows; i++) { singular_values[k] = Algebra_hypot(singular_values[k], A_matrix[i][k]); } if (singular_values[k] != 0.0) { if (A_matrix[k][k] < 0.0) { singular_values[k] = -singular_values[k]; } for (i = k; i < num_rows; i++) { A_matrix[i][k] /= singular_values[k]; } A_matrix[k][k] += 1.0; } singular_values[k] = -singular_values[k]; } for (j = k + 1; j < num_columns; j++) { if ((k < nct) & (singular_values[k] != 0.0)) { // Apply the transformation. double t = 0; for (i = k; i < num_rows; i++) { t += A_matrix[i][k] * A_matrix[i][j]; } t = -t / A_matrix[k][k]; for (i = k; i < num_rows; i++) { A_matrix[i][j] += t * A_matrix[i][k]; } } // Place the k-th row of A into e for the // subsequent calculation of the row transformation. e[j] = A_matrix[k][j]; } if (wantu & (k < nct)) { // Place the transformation in U for subsequent back // multiplication. for (i = k; i < num_rows; i++) { U_matrix[i][k] = A_matrix[i][k]; } } if (k < nrt) { // Compute the k-th row transformation and place the // k-th super-diagonal in e[k]. // Compute 2-norm without under/overflow. e[k] = 0; for (i = k + 1; i < num_columns; i++) { e[k] = Algebra_hypot(e[k], e[i]); } if (e[k] != 0.0) { if (e[k + 1] < 0.0) { e[k] = -e[k]; } for (i = k + 1; i < num_columns; i++) { e[i] /= e[k]; } e[k + 1] += 1.0; } e[k] = -e[k]; if ((k + 1 < num_rows) & (e[k] != 0.0)) { // Apply the transformation. for (i = k + 1; i < num_rows; i++) { work[i] = 0.0; } for (j = k + 1; j < num_columns; j++) { for (i = k + 1; i < num_rows; i++) { work[i] += e[j] * A_matrix[i][j]; } } for (j = k + 1; j < num_columns; j++) { double t = -e[j] / e[k + 1]; for (i = k + 1; i < num_rows; i++) { A_matrix[i][j] += t * work[i]; } } } if (wantv) { // Place the transformation in V for subsequent // back multiplication. for (i = k + 1; i < num_columns; i++) { V_matrix[i][k] = e[i]; } } } } // Set up the final bidiagonal matrix or order p. int p = Math_min(num_columns, num_rows + 1); if (nct < num_columns) { singular_values[nct] = A_matrix[nct][nct]; } if (num_rows < p) { singular_values[p - 1] = 0.0; } if (nrt + 1 < p) { e[nrt] = A_matrix[nrt][p - 1]; } e[p - 1] = 0.0; // If required, generate U. if (wantu) { for (j = nct; j < nu; j++) { for (i = 0; i < num_rows; i++) { U_matrix[i][j] = 0.0; } U_matrix[j][j] = 1.0; } for (k = nct - 1; k >= 0; k--) { if (singular_values[k] != 0.0) { for (j = k + 1; j < nu; j++) { double t = 0; for (i = k; i < num_rows; i++) { t += U_matrix[i][k] * U_matrix[i][j]; } t = -t / U_matrix[k][k]; for (i = k; i < num_rows; i++) { U_matrix[i][j] += t * U_matrix[i][k]; } } for (i = k; i < num_rows; i++) { U_matrix[i][k] = -U_matrix[i][k]; } U_matrix[k][k] = 1.0 + U_matrix[k][k]; for (i = 0; i < k - 1; i++) { U_matrix[i][k] = 0.0; } } else { for (i = 0; i < num_rows; i++) { U_matrix[i][k] = 0.0; } U_matrix[k][k] = 1.0; } } } // If required, generate V. if (wantv) { for (k = num_columns - 1; k >= 0; k--) { if ((k < nrt) & (e[k] != 0.0)) { for (j = k + 1; j < nu; j++) { double t = 0; for (i = k + 1; i < num_columns; i++) { t += V_matrix[i][k] * V_matrix[i][j]; } t = -t / V_matrix[k + 1][k]; for (i = k + 1; i < num_columns; i++) { V_matrix[i][j] += t * V_matrix[i][k]; } } } for (i = 0; i < num_columns; i++) { V_matrix[i][k] = 0.0; } V_matrix[k][k] = 1.0; } } // Main iteration loop for the singular values. int pp = p - 1; int iter = 0; double eps = pow(2.0, -52.0); while (p > 0) { int k, kase; // Here is where a test for too many iterations would go. // This section of the program inspects for // negligible elements in the s and e arrays. On // completion the variables kase and k are set as follows. // kase = 1 if s(p) and e[k-1] are negligible and k<p // kase = 2 if s(k) is negligible and k<p // kase = 3 if e[k-1] is negligible, k<p, and // s(k), ..., s(p) are not negligible (qr step). // kase = 4 if e(p-1) is negligible (convergence). for (k = p - 2; k >= -1; k--) { if (k == -1) { break; } if (fabs(e[k]) <= eps * (fabs(singular_values[k]) + fabs(singular_values[k + 1]))) { e[k] = 0.0; break; } } if (k == p - 2) { kase = 4; } else { int ks; for (ks = p - 1; ks >= k; ks--) { if (ks == k) { break; } double t = (ks != p ? fabs(e[ks]) : 0.) + (ks != k + 1 ? fabs(e[ks - 1]) : 0.); if (fabs(singular_values[ks]) <= eps * t) { singular_values[ks] = 0.0; break; } } if (ks == k) { kase = 3; } else if (ks == p - 1) { kase = 1; } else { kase = 2; k = ks; } } k++; // Perform the task indicated by kase. switch (kase) { // Deflate negligible s(p). case 1: { double f = e[p - 2]; e[p - 2] = 0.0; for (j = p - 2; j >= k; j--) { double t = Algebra_hypot(singular_values[j], f); double cs = singular_values[j] / t; double sn = f / t; singular_values[j] = t; if (j != k) { f = -sn * e[j - 1]; e[j - 1] = cs * e[j - 1]; } if (wantv) { for (i = 0; i < num_columns; i++) { t = cs * V_matrix[i][j] + sn * V_matrix[i][p - 1]; V_matrix[i][p - 1] = -sn * V_matrix[i][j] + cs * V_matrix[i][p - 1]; V_matrix[i][j] = t; } } } } break; // Split at negligible s(k). case 2: { double f = e[k - 1]; e[k - 1] = 0.0; for (j = k; j < p; j++) { double t = Algebra_hypot(singular_values[j], f); double cs = singular_values[j] / t; double sn = f / t; singular_values[j] = t; f = -sn * e[j]; e[j] = cs * e[j]; if (wantu) { for (i = 0; i < num_rows; i++) { t = cs * U_matrix[i][j] + sn * U_matrix[i][k - 1]; U_matrix[i][k - 1] = -sn * U_matrix[i][j] + cs * U_matrix[i][k - 1]; U_matrix[i][j] = t; } } } } break; // Perform one qr step. case 3: { // Calculate the shift. double scale = Math_max(Math_max(Math_max(Math_max( fabs(singular_values[p - 1]), fabs(singular_values[p - 2])), fabs(e[p - 2])), fabs(singular_values[k])), fabs(e[k])); double sp = singular_values[p - 1] / scale; double spm1 = singular_values[p - 2] / scale; double epm1 = e[p - 2] / scale; double sk = singular_values[k] / scale; double ek = e[k] / scale; double b = ((spm1 + sp)*(spm1 - sp) + epm1 * epm1) / 2.0; double c = (sp * epm1)*(sp * epm1); double shift = 0.0; if ((b != 0.0) | (c != 0.0)) { shift = sqrt(b * b + c); if (b < 0.0) { shift = -shift; } shift = c / (b + shift); } double f = (sk + sp)*(sk - sp) + shift; double g = sk*ek; // Chase zeros. for (j = k; j < p - 1; j++) { double t = Algebra_hypot(f, g); double cs = f / t; double sn = g / t; if (j != k) { e[j - 1] = t; } f = cs * singular_values[j] + sn * e[j]; e[j] = cs * e[j] - sn * singular_values[j]; g = sn * singular_values[j + 1]; singular_values[j + 1] = cs * singular_values[j + 1]; if (wantv) { for (i = 0; i < num_columns; i++) { t = cs * V_matrix[i][j] + sn * V_matrix[i][j + 1]; V_matrix[i][j + 1] = -sn * V_matrix[i][j] + cs * V_matrix[i][j + 1]; V_matrix[i][j] = t; } } t = Algebra_hypot(f, g); cs = f / t; sn = g / t; singular_values[j] = t; f = cs * e[j] + sn * singular_values[j + 1]; singular_values[j + 1] = -sn * e[j] + cs * singular_values[j + 1]; g = sn * e[j + 1]; e[j + 1] = cs * e[j + 1]; if (wantu && (j < num_rows - 1)) { for (i = 0; i < num_rows; i++) { t = cs * U_matrix[i][j] + sn * U_matrix[i][j + 1]; U_matrix[i][j + 1] = -sn * U_matrix[i][j] + cs * U_matrix[i][j + 1]; U_matrix[i][j] = t; } } } e[p - 2] = f; iter = iter + 1; } break; // Convergence. case 4: { // Make the singular values positive. if (singular_values[k] <= 0.0) { singular_values[k] = (singular_values[k] < 0.0 ? -singular_values[k] : 0.0); if (wantv) { for (i = 0; i <= pp; i++) { V_matrix[i][k] = -V_matrix[i][k]; } } } // Order the singular values. while (k < pp) { if (singular_values[k] >= singular_values[k + 1]) { break; } double t = singular_values[k]; singular_values[k] = singular_values[k + 1]; singular_values[k + 1] = t; if (wantv && (k < num_columns - 1)) { for (i = 0; i < num_columns; i++) { t = V_matrix[i][k + 1]; V_matrix[i][k + 1] = V_matrix[i][k]; V_matrix[i][k] = t; } } if (wantu && (k < num_rows - 1)) { for (i = 0; i < num_rows; i++) { t = U_matrix[i][k + 1]; U_matrix[i][k + 1] = U_matrix[i][k]; U_matrix[i][k] = t; } } k++; } iter = 0; p--; } break; } } // clean up free(e); e = NULL; free(work); work = NULL; free_matrix_double(A_matrix, num_rows, nu); }