source: git/Singular/intvec.cc @ 5812c69

spielwiese
Last change on this file since 5812c69 was 5812c69, checked in by Hans Schönemann <hannes@…>, 26 years ago
cosmetic changes git-svn-id: file:///usr/local/Singular/svn/trunk@2517 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 10.2 KB
Line 
1/*****************************************
2*  Computer Algebra System SINGULAR      *
3*****************************************/
4/* $Id: intvec.cc,v 1.10 1998-09-24 09:59:43 Singular Exp $ */
5/*
6* ABSTRACT: class intvec: lists/vectors of integers
7*/
8
9#include "mod2.h"
10#include "tok.h"
11#include "febase.h"
12#include "intvec.h"
13
14/*0 implementation*/
15intvec::intvec(intvec* iv)
16{
17  row = iv->rows();
18  col = iv->cols();
19  v   = (int *)Alloc(sizeof(int)*row*col);
20  for (int i=0; i<row*col; i++)
21  {
22    v[i] = (*iv)[i];
23  }
24}
25
26intvec::intvec(int s, int e)
27{
28  int inc;
29  col = 1;
30  if (s<e)
31  {
32    row =  e-s+1;
33    inc =  1;
34  }
35  else
36  {
37    row = s-e+1;
38    inc = -1;
39  }
40  v = (int *)Alloc(sizeof(int)*row);
41  //if (v!=NULL)
42  {
43    for (int i=0; i<row; i++)
44    {
45      v[i] = s;
46      s+=inc;
47    }
48  }
49  //else
50  //{
51  //  Werror("internal error: creating intvec(%d)",row);
52  //  row=0;
53  //}
54}
55
56intvec::intvec(int r, int c, int init)
57{
58  row = r;
59  col = c;
60  int l = r*c;
61  if ((r>0) && (c>0))
62    v = (int *)Alloc(sizeof(int)*l);
63  else
64    v = NULL;
65  if (v!=NULL)
66  {
67    for (int i=0; i<l; i++)
68    {
69      v[i] = init;
70    }
71  }
72  else
73  {
74    Werror("internal error: creating intmat(%d,%d)",row,col);
75    row=0;
76  }
77}
78
79char * intvec::ivString(int mat,int spaces)
80{
81  StringSetS("");
82  if ((col == 1)&&(mat!=INTMAT_CMD))
83  {
84    int i;
85    for (i=0; i<row-1; i++)
86    {
87      StringAppend("%d,",v[i]);
88    }
89    if (i<row)
90    {
91      StringAppend("%d",v[i]);
92    }
93  }
94  else
95  {
96    for (int j=0; j<row; j++)
97    {
98      if (j<row-1)
99      {
100        for (int i=0; i<col; i++)
101        {
102          StringAppend("%d%c",v[j*col+i],',');
103        }
104      }
105      else
106      {
107        for (int i=0; i<col; i++)
108        {
109          StringAppend("%d%c",v[j*col+i],i<col-1 ? ',' : ' ');
110        }
111      }
112      if (j+1<row)
113      {
114        StringAppend("\n");
115        if (spaces>0) StringAppend("%-*.*s",spaces,spaces," ");
116      }
117    }
118  }
119  return StringAppend("");
120}
121
122char * intvec::String()
123{
124  return mstrdup(ivString());
125}
126
127void intvec::show(int mat,int spaces)
128{
129  if (spaces>0)
130    Print("%-*.*s%s",spaces,spaces," ",ivString(mat,spaces));
131  else
132    PrintS(ivString(mat,0));
133}
134
135void intvec::operator+=(int intop)
136{
137  for (int i=0; i<row*col; i++) { v[i] += intop; }
138}
139
140void intvec::operator-=(int intop)
141{
142  for (int i=0; i<row*col; i++) { v[i] -= intop; }
143}
144
145void intvec::operator*=(int intop)
146{
147  for (int i=0; i<row*col; i++) { v[i] *= intop; }
148}
149
150void intvec::operator/=(int intop)
151{
152  if (intop == 0) return;
153  for (int i=0; i<row*col; i++) { v[i] /= intop; }
154}
155
156void intvec::operator%=(int intop)
157{
158  if (intop == 0) return;
159  if (intop<0) intop*=(-1);
160  for (int i=0; i<row*col; i++)
161  { v[i] %= intop; if (v[i]<0) v[i] += intop; }
162}
163
164int intvec::compare(intvec* op)
165{
166  if ((col!=1) ||(op->cols()!=1))
167  {
168    if((col!=op->cols())
169    || (row!=op->rows()))
170      return -2;
171  }
172  int i;
173  for (i=0; i<min(length(),op->length()); i++)
174  {
175    if (v[i] > (*op)[i])
176      return 1;
177    if (v[i] < (*op)[i])
178      return -1;
179  }
180  // this can only happen for intvec: (i.e. col==1)
181  for (; i<row; i++)
182  {
183    if (v[i] > 0)
184      return 1;
185    if (v[i] < 0)
186      return -1;
187  }
188  for (; i<op->rows(); i++)
189  {
190    if (0 > (*op)[i])
191      return 1;
192    if (0 < (*op)[i])
193      return -1;
194  }
195  return 0;
196}
197int intvec::compare(int o)
198{
199  for (int i=0; i<row*col; i++)
200  {
201    if (v[i] <o) return -1;
202    if (v[i] >o) return 1;
203  }
204  return 0;
205}
206
207intvec * ivCopy(intvec * o)
208{
209  intvec * iv=new intvec(o);
210  return iv;
211}
212
213intvec * ivAdd(intvec * a, intvec * b)
214{
215  intvec * iv;
216  int mn, ma, i;
217  if (a->cols() != b->cols()) return NULL;
218  mn = min(a->rows(),b->rows());
219  ma = max(a->rows(),b->rows());
220  if (a->cols() == 1)
221  {
222    iv = new intvec(ma);
223    for (i=0; i<mn; i++) (*iv)[i] = (*a)[i] + (*b)[i];
224    if (ma > mn)
225    {
226      if (ma == a->rows())
227      {
228        for(i=mn; i<ma; i++) (*iv)[i] = (*a)[i];
229      }
230      else
231      {
232        for(i=mn; i<ma; i++) (*iv)[i] = (*b)[i];
233      }
234    }
235    return iv;
236  }
237  if (mn != ma) return NULL;
238  iv = new intvec(a);
239  for (i=0; i<mn*a->cols(); i++) { (*iv)[i] += (*b)[i]; }
240  return iv;
241}
242
243intvec * ivSub(intvec * a, intvec * b)
244{
245  intvec * iv;
246  int mn, ma, i;
247  if (a->cols() != b->cols()) return NULL;
248  mn = min(a->rows(),b->rows());
249  ma = max(a->rows(),b->rows());
250  if (a->cols() == 1)
251  {
252    iv = new intvec(ma);
253    for (i=0; i<mn; i++) (*iv)[i] = (*a)[i] - (*b)[i];
254    if (ma > mn)
255    {
256      if (ma == a->rows())
257      {
258        for(i=mn; i<ma; i++) (*iv)[i] = (*a)[i];
259      }
260      else
261      {
262        for(i=mn; i<ma; i++) (*iv)[i] = -(*b)[i];
263      }
264    }
265    return iv;
266  }
267  if (mn != ma) return NULL;
268  iv = new intvec(a);
269  for (i=0; i<mn*a->cols(); i++) { (*iv)[i] -= (*b)[i]; }
270  return iv;
271}
272
273intvec * ivTranp(intvec * o)
274{
275  int i, j, r = o->rows(), c = o->cols();
276  intvec * iv=new intvec(c, r, 0);
277  for (i=0; i<r; i++)
278  {
279    for (j=0; j<c; j++)
280      (*iv)[j*r+i] = (*o)[i*c+j];
281  }
282  return iv;
283}
284
285int ivTrace(intvec * o)
286{
287  int i, s = 0, m = min(o->rows(),o->cols()), c = o->cols();
288  for (i=0; i<m; i++)
289  {
290    s += (*o)[i*c+i];
291  }
292  return s;
293}
294
295intvec * ivMult(intvec * a, intvec * b)
296{
297  int i, j, k, sum,
298      ra = a->rows(), ca = a->cols(),
299      rb = b->rows(), cb = b->cols();
300  intvec * iv;
301  if (ca != rb) return NULL;
302  iv = new intvec(ra, cb, 0);
303  for (i=0; i<ra; i++)
304  {
305    for (j=0; j<cb; j++)
306    {
307      sum = 0;
308      for (k=0; k<ca; k++)
309        sum += (*a)[i*ca+k]*(*b)[k*cb+j];
310      (*iv)[i*cb+j] = sum;
311    }
312  }
313  return iv;
314}
315
316/*3
317* gcd of a and b
318*/
319static int ivIntGcd(int a,int b)
320{
321  int x;
322
323  while (b!=0)
324  {
325    x = b;
326    b = a % x;
327    a = x;
328  }
329  return a;
330}
331
332/*2
333*computes a triangular matrix of the lower right submatrix
334*beginning with the field (srw,cl) by Gaussian elimination
335*/
336void ivTriangMat(intvec * imat, int srw, int cl)
337{
338  int i=srw,t,j,k,tgcd,mult1,mult2;
339
340  if ((cl>imat->cols()) || (srw>imat->rows())) return;
341  ivCancelContent(imat,srw);
342  while ((i<=imat->rows()) && (IMATELEM(*imat,i,cl)==0)) i++;
343  if ((i>srw ) && (i<=imat->rows()))
344  {
345    for (j=cl;j<=imat->cols();j++)
346    {
347      t = IMATELEM(*imat,srw,j);
348      IMATELEM(*imat,srw,j) = IMATELEM(*imat,i,j);
349      IMATELEM(*imat,i,j) = t;
350    }
351  }
352  if (i<=imat->rows())
353  {
354    for (k=srw+1;k<=imat->rows();k++)
355    {
356      if (IMATELEM(*imat,k,cl)!=0)
357      {
358        tgcd = ivIntGcd(IMATELEM(*imat,srw,cl),IMATELEM(*imat,k,cl));
359        mult1 = IMATELEM(*imat,k,cl) / tgcd;
360        mult2 = IMATELEM(*imat,srw,cl) / tgcd;
361        IMATELEM(*imat,k,cl) = 0;
362        for (j=cl+1;j<=imat->cols();j++)
363        {
364          IMATELEM(*imat,k,j) =
365              mult2*IMATELEM(*imat,k,j)-mult1*IMATELEM(*imat,srw,j);
366        }
367      }
368    }
369    srw++;
370  }
371  ivTriangMat(imat,srw,cl+1);
372  return;
373}
374
375/*2
376*returns the number of the first zero row,
377*-1 for no zero row
378*/
379int ivFirstEmptyRow(intvec * imat)
380{
381  int i,j;
382
383  for (i=1;i<=imat->rows();i++)
384  {
385    j = 1;
386    while ((j<=imat->cols()) && (IMATELEM(*imat,i,j)==0)) j++;
387    if (j>imat->cols()) return i;
388  }
389  return -1;
390}
391
392/*2
393*divide out the content for every row >= from
394*/
395void ivCancelContent(intvec * imat,int from)
396{
397  if (imat->cols()<2) return;
398  int i,j,tgcd;
399
400  for (i=from;i<=imat->rows();i++)
401  {
402    tgcd = ivIntGcd(IMATELEM(*imat,i,1),IMATELEM(*imat,i,2));
403    j = 3;
404    while ((j<=imat->cols()) && ((ABS(tgcd)>1) || (tgcd==0)))
405    {
406      tgcd = ivIntGcd(tgcd,IMATELEM(*imat,i,j));
407      j++;
408    }
409    if ((j>imat->cols()) && (ABS(tgcd)>1))
410     for (j=1;j<=imat->cols();j++) IMATELEM(*imat,i,j) /= tgcd;
411  }
412  return;
413}
414
415/*3
416*searches the independent columns of the system given by imat
417*imat is assumed to be in triangular shape
418*/
419static intvec * ivIndepCols(intvec * imat)
420{
421  intvec * result=new intvec(1,imat->cols(),0);
422  int i,j;
423
424  for (i=1;i<=imat->rows();i++)
425  {
426    j=1;
427    while ((j<=imat->cols()) && (IMATELEM(*imat,i,j)==0)) j++;
428    if (j<=imat->cols()) IMATELEM(*result,1,j)=i;
429  }
430  return result;
431}
432
433/*3
434* computes basic solutions of the system given by imat
435*/
436static intvec * ivBasicSol(intvec * imat)
437{
438  intvec * result = new intvec(2*imat->cols(),imat->cols(),0);
439  intvec * indep=ivIndepCols(imat),*actsol=new intvec(imat->cols());
440  int actPosSol=1,actNegSol=imat->cols()+1,i=imat->cols(),j,k;
441  int tgcd,tlcm;
442  BOOLEAN isNeg;
443
444  while (i>0)
445  {
446    if ((*indep)[i-1]==0)
447    {
448      for (j=0;j<actsol->length();j++) (*actsol)[j] = 0;
449      (*actsol)[i-1] = 1;
450      isNeg = FALSE;
451      j = i-1;
452      while (j>0)
453      {
454        if ((*indep)[j-1]!=0)
455        {
456          tlcm = 0;
457          for (k=0;k<i;k++)
458            tlcm += IMATELEM(*imat,(*indep)[j-1],k+1)*(*actsol)[k];
459          tgcd = ivIntGcd(tlcm,IMATELEM(*imat,(*indep)[j-1],j));
460          tlcm /= tgcd;
461          tgcd = IMATELEM(*imat,(*indep)[j-1],j) / tgcd;
462          if (tgcd<0)
463          {
464            tgcd = -tgcd;
465            tlcm = -tlcm;
466          }
467          for (k=0;k<i;k++) (*actsol)[k] *= tgcd;
468          (*actsol)[j-1] = -tlcm;
469          isNeg = isNeg || (tlcm>0);
470        }
471        j--;
472      }
473/*writes the solution into result depending on the sign*/
474      if (isNeg)
475      {
476        for (j=1;j<=imat->cols();j++)
477          IMATELEM(*result,actNegSol,j) = (*actsol)[j-1];
478        actNegSol++;
479      }
480      else
481      {
482        for (j=1;j<=imat->cols();j++)
483          IMATELEM(*result,actPosSol,j) = (*actsol)[j-1];
484        actPosSol++;
485      }
486    }
487    i--;
488  }
489  delete actsol;
490  delete indep;
491  return result;
492}
493
494/*2
495*returns an integer solution of imat which is assumed to be
496*in triangular form
497*the solution contains as many positive entrees as possible
498*/
499intvec * ivSolveIntMat(intvec * imat)
500{
501  intvec * result=new intvec(imat->cols());
502  intvec * basesol=ivBasicSol(imat);
503  int i=imat->cols(),j,k,l,t;
504
505/*adds all base solutions*/
506  for (j=1;j<=2*i;j++)
507  {
508    for (k=1;k<=i;k++)
509      (*result)[k-1] += IMATELEM(*basesol,j,k);
510  }
511/*tries to cancel negative entrees by adding positive solutions*/
512  j = 1;
513  while (j<=i)
514  {
515    if ((*result)[j-1]<0)
516    {
517      t = -1;
518      l = 0;
519      for (k=1;k<=i;k++)
520      {
521        if (IMATELEM(*basesol,k,j)>t)
522        {
523          t = IMATELEM(*basesol,k,j);
524          l = k;
525        }
526      }
527      if (t>0)
528      {
529        t = ((*result)[j-1] / t) +1;
530        for (k=1;k<=i;k++)
531        {
532          (*result)[k-1] += t*IMATELEM(*basesol,l,k);
533        }
534      }
535    }
536    j++;
537  }
538  delete basesol;
539  return result;
540}
Note: See TracBrowser for help on using the repository browser.