00001 #include <stdlib.h>
00002 #include <polylib/polylib.h>
00003
00004 static void RearrangeMatforSolveDio(Matrix *M);
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 int SolveDiophantine(Matrix *M, Matrix **U, Vector **X) {
00065
00066 int i, j, k1, k2, min, rank;
00067 Matrix *A, *temp, *hermi, *unimod, *unimodinv ;
00068 Value *C;
00069 Value *T;
00070 Value sum, tmp;
00071
00072 #ifdef DOMDEBUG
00073 FILE *fp;
00074 fp = fopen("_debug", "a");
00075 fprintf(fp,"\nEntered SOLVEDIOPHANTINE\n");
00076 fclose(fp);
00077 #endif
00078
00079 value_init(sum); value_init(tmp);
00080
00081
00082 A = Matrix_Copy(M);
00083 RearrangeMatforSolveDio(A);
00084 temp = Matrix_Alloc(A->NbRows-1, A->NbColumns-1);
00085
00086
00087 for (i = 0; i < A->NbRows -1; i++)
00088 for (j = 0; j < A->NbColumns-1; j++)
00089 value_assign(temp->p[i][j],A->p[i][j]);
00090
00091
00092 C = (Value *) malloc (sizeof(Value) * (A->NbRows-1));
00093 k1 = A->NbRows-1;
00094
00095 for (i = 0; i < k1; i++) {
00096 value_init(C[i]);
00097 value_oppose(C[i],A->p[i][A->NbColumns-1]);
00098 }
00099 Matrix_Free (A);
00100
00101
00102 Hermite(temp, &hermi, &unimod);
00103
00104
00105
00106 min=(hermi->NbRows <= hermi->NbColumns ) ? hermi->NbRows : hermi->NbColumns ;
00107 rank = 0;
00108 for (i = 0; i < min ; i++) {
00109 if (value_notzero_p(hermi->p[i][i]))
00110 rank ++;
00111 else
00112 break ;
00113 }
00114
00115
00116
00117 T = (Value *) malloc(sizeof(Value) * temp->NbColumns);
00118 k2 = temp->NbColumns;
00119 for(i=0;i< k2; i++)
00120 value_init(T[i]);
00121
00122 for (i = 0; i < rank ; i++) {
00123 value_set_si(sum,0);
00124 for (j = 0; j < i; j++) {
00125 value_addmul(sum, T[j], hermi->p[i][j]);
00126 }
00127 value_subtract(tmp,C[i],sum);
00128 value_modulus(tmp,tmp,hermi->p[i][i]);
00129 if (value_notzero_p(tmp)) {
00130 *U = Matrix_Alloc(0,0);
00131 *X = Vector_Alloc (0);
00132 value_clear(sum); value_clear(tmp);
00133 for (i = 0; i < k1; i++)
00134 value_clear(C[i]);
00135 for (i = 0; i < k2; i++)
00136 value_clear(T[i]);
00137 free(C);
00138 free(T);
00139 return (-1);
00140 };
00141 value_subtract(tmp,C[i],sum);
00142 value_division(T[i],tmp,hermi->p[i][i]);
00143 }
00144
00145
00146
00147 for (i = rank; i < hermi->NbColumns; i++)
00148 value_set_si(T[i],0);
00149
00150
00151
00152
00153
00154 for (i = rank; i < hermi->NbRows; i++) {
00155 value_set_si(sum,0);
00156 for (j = 0; j < hermi->NbColumns; j++) {
00157 value_addmul(sum, T[j], hermi->p[i][j]);
00158 }
00159 if (value_ne(sum,C[i])) {
00160 *U = Matrix_Alloc(0,0);
00161 *X = Vector_Alloc (0);
00162 value_clear(sum); value_clear(tmp);
00163 for (i = 0; i < k1; i++)
00164 value_clear(C[i]);
00165 for (i = 0; i < k2; i++)
00166 value_clear(T[i]);
00167 free(C);
00168 free(T);
00169 return (-1);
00170 }
00171 }
00172 unimodinv = Matrix_Alloc(unimod->NbRows, unimod->NbColumns);
00173 Matrix_Inverse(unimod, unimodinv);
00174 Matrix_Free(unimod);
00175 *X = Vector_Alloc(M->NbColumns-1);
00176
00177 if (rank == hermi->NbColumns)
00178 *U = Matrix_Alloc(0,0);
00179 else {
00180
00181 *U = Matrix_Alloc(hermi->NbColumns, hermi->NbColumns-rank);
00182 for (i = 0; i < U[0]->NbRows; i++)
00183 for (j = 0; j < U[0]->NbColumns; j++)
00184 value_assign(U[0]->p[i][j],unimodinv->p[i][j+rank]);
00185 }
00186
00187 for (i = 0; i < unimodinv->NbRows; i++) {
00188
00189
00190 value_set_si(sum,0);
00191 for (j = 0; j < unimodinv->NbColumns; j++) {
00192 value_addmul(sum, unimodinv->p[i][j], T[j]);
00193 }
00194 value_assign(X[0]->p[i],sum);
00195 }
00196
00197
00198
00199
00200
00201 Matrix_Free (unimodinv);
00202 Matrix_Free (hermi);
00203 Matrix_Free (temp);
00204 value_clear(sum); value_clear(tmp);
00205 for (i = 0; i < k1; i++)
00206 value_clear(C[i]);
00207 for (i = 0; i < k2; i++)
00208 value_clear(T[i]);
00209 free(C);
00210 free(T);
00211 return (rank);
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 static void RearrangeMatforSolveDio(Matrix *M) {
00232
00233 int i, j, curend, curRow, min, rank=1;
00234 Bool add = True;
00235 Matrix *A, *L, *H, *U;
00236
00237
00238
00239
00240
00241 L = Matrix_Alloc(M->NbRows-1,M->NbColumns-1);
00242 for (i = 0; i < L->NbRows; i++)
00243 for (j = 0; j < L->NbColumns; j++)
00244 value_assign(L->p[i][j],M->p[i][j]);
00245
00246
00247 curend = L->NbRows-1;
00248 for (i = 0; i < curend; i++) {
00249 for (j = 0; j < L->NbColumns; j++)
00250 if (value_notzero_p(L->p[i][j]))
00251 break;
00252 if (j == L->NbColumns) {
00253 ExchangeRows(M,i,curend);
00254 curend --;
00255 }
00256 }
00257
00258
00259
00260 if (curend > 0) {
00261
00262 Matrix *temp;
00263 A = Matrix_Alloc(1, L->NbColumns);
00264
00265 for (i = 0; i <L->NbColumns; i++)
00266 value_assign(A->p[0][i],L->p[0][i]);
00267 curRow = 1;
00268 while (add == True ) {
00269 temp= AddANullRow(A);
00270 for (i = 0;i <A->NbColumns; i++)
00271 value_assign(temp->p[curRow][i],L->p[curRow][i]);
00272 Hermite(temp, &H, &U);
00273 for (i = 0; i < H->NbRows; i++)
00274 if (value_zero_p(H->p[i][i]))
00275 break;
00276 if (i != H->NbRows) {
00277 ExchangeRows(M, curRow, curend);
00278 curend --;
00279 }
00280 else {
00281 curRow ++;
00282 rank ++;
00283 Matrix_Free (A);
00284 A = Matrix_Copy (temp);
00285 Matrix_Free (temp);
00286 }
00287 Matrix_Free (H);
00288 Matrix_Free (U);
00289 min = (curend >= L->NbColumns) ? L->NbColumns : curend ;
00290 if (rank==min || curRow >= curend)
00291 break;
00292 }
00293 Matrix_Free (A);
00294 }
00295 Matrix_Free (L);
00296 return;
00297 }