source: git/kernel/intvec.cc @ 6b9532

spielwiese
Last change on this file since 6b9532 was 11120fd, checked in by Hans Schönemann <hannes@…>, 20 years ago
*hannes: debug stuff git-svn-id: file:///usr/local/Singular/svn/trunk@7199 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 14.0 KB
Line 
1/*****************************************
2*  Computer Algebra System SINGULAR      *
3*****************************************/
4/* $Id: intvec.cc,v 1.2 2004-05-27 12:05:41 Singular Exp $ */
5/*
6* ABSTRACT: class intvec: lists/vectors of integers
7*/
8#ifndef INTVEC_CC
9#define INTVEC_CC
10#include "mod2.h"
11#include "structs.h"
12#include "febase.h"
13#include "intvec.h"
14#include "omalloc.h"
15
16/*0 implementation*/
17
18
19intvec::intvec(intvec* iv)
20{
21  row = iv->rows();
22  col = iv->cols();
23  v   = (int *)omAlloc(sizeof(int)*row*col);
24  for (int i=0; i<row*col; i++)
25  {
26    v[i] = (*iv)[i];
27  }
28}
29
30intvec::intvec(int s, int e)
31{
32  int inc;
33  col = 1;
34  if (s<e)
35  {
36    row =  e-s+1;
37    inc =  1;
38  }
39  else
40  {
41    row = s-e+1;
42    inc = -1;
43  }
44  v = (int *)omAlloc(sizeof(int)*row);
45  for (int i=0; i<row; i++)
46  {
47    v[i] = s;
48    s+=inc;
49  }
50}
51
52intvec::intvec(int r, int c, int init)
53{
54  row = r;
55  col = c;
56  int l = r*c;
57  if ((r>0) && (c>0))
58    v = (int *)omAlloc(sizeof(int)*l);
59  else
60    v = NULL;
61  for (int i=0; i<l; i++)
62  {
63    v[i] = init;
64  }
65}
66
67char * intvec::ivString(int not_mat,int spaces, int dim)
68{
69  //Print("ivString:this=%x,v=%x,row=%d\n",this,v,row);
70  omCheckAddr(this);
71  omCheckAddr(v);
72  StringSetS("");
73  if ((col == 1)&&(not_mat))
74  {
75    int i=0;
76    for (; i<row-1; i++)
77    {
78      StringAppend("%d,",v[i]);
79    }
80    if (i<row)
81    {
82      StringAppend("%d",v[i]);
83    }
84  }
85  else
86  {
87    for (int j=0; j<row; j++)
88    {
89      if (j<row-1)
90      {
91        for (int i=0; i<col; i++)
92        {
93          StringAppend("%d%c",v[j*col+i],',');
94        }
95      }
96      else
97      {
98        for (int i=0; i<col; i++)
99        {
100          StringAppend("%d%c",v[j*col+i],i<col-1 ? ',' : ' ');
101        }
102      }
103      if (j+1<row)
104      {
105        if (dim > 1) StringAppendS("\n");
106        if (spaces>0) StringAppend("%-*.*s",spaces,spaces," ");
107      }
108    }
109  }
110  return StringAppendS("");
111}
112
113void intvec::resize(int new_length)
114{
115  assume(new_length > 0 && col == 1);
116  v = (int*) omRealloc0Size(v, row*sizeof(int), new_length*sizeof(int));
117  row = new_length;
118}
119
120char * intvec::String(int dim)
121{
122  return omStrDup(ivString(1, 0, dim));
123}
124
125void intvec::show(int notmat,int spaces)
126{
127  if (spaces>0)
128    Print("%-*.*s%s",spaces,spaces," ",ivString(notmat,spaces));
129  else
130    PrintS(ivString(notmat,0));
131}
132
133void intvec::operator+=(int intop)
134{
135  for (int i=0; i<row*col; i++) { v[i] += intop; }
136}
137
138void intvec::operator-=(int intop)
139{
140  for (int i=0; i<row*col; i++) { v[i] -= intop; }
141}
142
143void intvec::operator*=(int intop)
144{
145  for (int i=0; i<row*col; i++) { v[i] *= intop; }
146}
147
148void intvec::operator/=(int intop)
149{
150  if (intop == 0) return;
151  int bb=ABS(intop);
152  for (int i=0; i<row*col; i++)
153  {
154    int r=v[i];
155    int c=r%bb;
156    if (c<0) c+=bb;
157    r=(r-c)/intop;
158    v[i]=r;
159  }
160}
161
162void intvec::operator%=(int intop)
163{
164  if (intop == 0) return;
165  int bb=ABS(intop);
166  for (int i=0; i<row*col; i++)
167  {
168    int r=v[i];
169    int c=r%bb;
170    if (c<0) c+=bb;
171    v[i]=c;
172  }
173}
174
175int intvec::compare(intvec* op)
176{
177  if ((col!=1) ||(op->cols()!=1))
178  {
179    if((col!=op->cols())
180    || (row!=op->rows()))
181      return -2;
182  }
183  int i;
184  for (i=0; i<si_min(length(),op->length()); i++)
185  {
186    if (v[i] > (*op)[i])
187      return 1;
188    if (v[i] < (*op)[i])
189      return -1;
190  }
191  // this can only happen for intvec: (i.e. col==1)
192  for (; i<row; i++)
193  {
194    if (v[i] > 0)
195      return 1;
196    if (v[i] < 0)
197      return -1;
198  }
199  for (; i<op->rows(); i++)
200  {
201    if (0 > (*op)[i])
202      return 1;
203    if (0 < (*op)[i])
204      return -1;
205  }
206  return 0;
207}
208int intvec::compare(int o)
209{
210  for (int i=0; i<row*col; i++)
211  {
212    if (v[i] <o) return -1;
213    if (v[i] >o) return 1;
214  }
215  return 0;
216}
217
218intvec * ivCopy(intvec * o)
219{
220  intvec * iv=new intvec(o);
221  return iv;
222}
223
224intvec * ivAdd(intvec * a, intvec * b)
225{
226  intvec * iv;
227  int mn, ma, i;
228  if (a->cols() != b->cols()) return NULL;
229  mn = si_min(a->rows(),b->rows());
230  ma = si_max(a->rows(),b->rows());
231  if (a->cols() == 1)
232  {
233    iv = new intvec(ma);
234    for (i=0; i<mn; i++) (*iv)[i] = (*a)[i] + (*b)[i];
235    if (ma > mn)
236    {
237      if (ma == a->rows())
238      {
239        for(i=mn; i<ma; i++) (*iv)[i] = (*a)[i];
240      }
241      else
242      {
243        for(i=mn; i<ma; i++) (*iv)[i] = (*b)[i];
244      }
245    }
246    return iv;
247  }
248  if (mn != ma) return NULL;
249  iv = new intvec(a);
250  for (i=0; i<mn*a->cols(); i++) { (*iv)[i] += (*b)[i]; }
251  return iv;
252}
253
254intvec * ivSub(intvec * a, intvec * b)
255{
256  intvec * iv;
257  int mn, ma, i;
258  if (a->cols() != b->cols()) return NULL;
259  mn = si_min(a->rows(),b->rows());
260  ma = si_max(a->rows(),b->rows());
261  if (a->cols() == 1)
262  {
263    iv = new intvec(ma);
264    for (i=0; i<mn; i++) (*iv)[i] = (*a)[i] - (*b)[i];
265    if (ma > mn)
266    {
267      if (ma == a->rows())
268      {
269        for(i=mn; i<ma; i++) (*iv)[i] = (*a)[i];
270      }
271      else
272      {
273        for(i=mn; i<ma; i++) (*iv)[i] = -(*b)[i];
274      }
275    }
276    return iv;
277  }
278  if (mn != ma) return NULL;
279  iv = new intvec(a);
280  for (i=0; i<mn*a->cols(); i++) { (*iv)[i] -= (*b)[i]; }
281  return iv;
282}
283
284intvec * ivTranp(intvec * o)
285{
286  int i, j, r = o->rows(), c = o->cols();
287  intvec * iv= new intvec(c, r, 0);
288  for (i=0; i<r; i++)
289  {
290    for (j=0; j<c; j++)
291      (*iv)[j*r+i] = (*o)[i*c+j];
292  }
293  return iv;
294}
295
296int ivTrace(intvec * o)
297{
298  int i, s = 0, m = si_min(o->rows(),o->cols()), c = o->cols();
299  for (i=0; i<m; i++)
300  {
301    s += (*o)[i*c+i];
302  }
303  return s;
304}
305
306intvec * ivMult(intvec * a, intvec * b)
307{
308  int i, j, k, sum,
309      ra = a->rows(), ca = a->cols(),
310      rb = b->rows(), cb = b->cols();
311  intvec * iv;
312  if (ca != rb) return NULL;
313  iv = new intvec(ra, cb, 0);
314  for (i=0; i<ra; i++)
315  {
316    for (j=0; j<cb; j++)
317    {
318      sum = 0;
319      for (k=0; k<ca; k++)
320        sum += (*a)[i*ca+k]*(*b)[k*cb+j];
321      (*iv)[i*cb+j] = sum;
322    }
323  }
324  return iv;
325}
326
327/*2
328*computes a triangular matrix
329*/
330//void ivTriangMat(intvec * imat)
331//{
332//  int i=0,j=imat->rows(),k=j*imat->cols()-1;
333//
334//  ivTriangIntern(imat,i,j);
335//  i *= imat->cols();
336//  for(j=k;j>=i;j--)
337//    (*imat)[j] = 0;
338//}
339
340/* def. internals */
341static int ivColPivot(intvec *, int, int, int, int);
342static void ivNegRow(intvec *, int);
343static void ivSaveRow(intvec *, int);
344static void ivSetRow(intvec *, int, int);
345static void ivFreeRow(intvec *, int, int);
346static void ivReduce(intvec *, int, int, int, int);
347static void ivZeroElim(intvec *,int, int, int &);
348static void ivRowContent(intvec *, int, int);
349static void ivKernFromRow(intvec *, intvec *, intvec *,
350                          int, int, int);
351static intvec * ivOptimizeKern(intvec *);
352static int ivGcd(int, int);
353static void ivOptRecursive(intvec *, intvec *, intvec *,
354                          int &, int &, int);
355static void ivOptSolve(intvec *, intvec *, int &, int &);
356static void ivContent(intvec *);
357static int ivL1Norm(intvec *);
358static int ivCondNumber(intvec *, int); 
359
360/* Triangulierung in intmat.cc */
361void ivTriangIntern(intvec *imat, int &ready, int &all)
362{
363  int rpiv, colpos=0, rowpos=0;
364  int ia=ready, ie=all;
365
366  do
367  {
368    rowpos++;
369    do
370    {
371      colpos++;
372      rpiv = ivColPivot(imat, colpos, rowpos, ia, ie);
373    } while (rpiv==0);
374    if (rpiv>ia)
375    {
376      if (rowpos!=rpiv)
377      {
378        ivSaveRow(imat, rpiv);
379        ivFreeRow(imat, rowpos, rpiv);
380        ivSetRow(imat, rowpos, colpos);
381        rpiv = rowpos;
382      }
383      ia++;
384      if (ia==imat->cols())
385      {
386        ready = ia;
387        all = ie;
388        return;
389      }
390    }
391    ivReduce(imat, rpiv, colpos, ia, ie);
392    ivZeroElim(imat, colpos, ia, ie);
393  } while (ie>ia);
394  ready = ia;
395  all = ie;
396}
397
398/* Kernberechnung in intmat.cc */
399intvec * ivSolveKern(intvec *imat, int dimtr)
400{
401  int d=imat->cols();
402  int kdim=d-dimtr;
403  intvec *perm = new intvec(dimtr+1);
404  intvec *kern = new intvec(kdim,d,0);
405  intvec *res;
406  int c, cp, r, t;
407
408  t = kdim;
409  c = 1;
410  for (r=1;r<=dimtr;r++)
411  {
412    while (IMATELEM(*imat,r,c)==0) c++;
413    (*perm)[r] = c;
414    c++;
415  }
416  c = d;
417  for (r=dimtr;r>0;r--)
418  {
419    cp = (*perm)[r];
420    if (cp!=c)
421    {
422      ivKernFromRow(kern, imat, perm, t, r, c);
423      t -= (c-cp);
424      if (t==0)
425        break;
426      c = cp-1;
427    }
428    else
429      c--;
430  }
431  if (kdim>1)
432    res = ivOptimizeKern(kern);
433  else
434    res = ivTranp(kern);
435  delete kern;
436  delete perm;
437  return res;
438}
439
440/* internals */
441static int ivColPivot(intvec *imat, int colpos, int rowpos, int ready, int all)
442{
443  int rpiv;
444
445  if (IMATELEM(*imat,rowpos,colpos)!=0)
446    return rowpos;
447  for (rpiv=ready+1;rpiv<=all;rpiv++)
448  {
449    if (IMATELEM(*imat,rpiv,colpos)!=0)
450      return rpiv;
451  }
452  return 0;
453}
454
455static void ivNegRow(intvec *imat, int rpiv)
456{
457  int i;
458  for (i=imat->cols();i!=0;i--)
459    IMATELEM(*imat,rpiv,i) = -(IMATELEM(*imat,rpiv,i));
460}
461
462static void ivSaveRow(intvec *imat, int rpiv)
463{
464  int i, j=imat->rows();
465
466  for (i=imat->cols();i!=0;i--)
467    IMATELEM(*imat,j,i) = IMATELEM(*imat,rpiv,i);
468}
469
470static void ivSetRow(intvec *imat, int rowpos, int colpos)
471{
472  int i, j=imat->rows();
473
474  for (i=imat->cols();i!=0;i--)
475    IMATELEM(*imat,rowpos,i) = IMATELEM(*imat,j,i);
476  ivRowContent(imat, rowpos, colpos);
477}
478
479static void ivFreeRow(intvec *imat, int rowpos, int rpiv)
480{
481  int i, j;
482
483  for (j=rpiv-1;j>=rowpos;j--)
484  {
485    for (i=imat->cols();i!=0;i--)
486      IMATELEM(*imat,j+1,i) = IMATELEM(*imat,j,i);
487  }
488}
489
490static void ivReduce(intvec *imat, int rpiv, int colpos,
491                     int ready, int all)
492{
493  int tgcd, ce, m1, m2, j, i;
494  int piv = IMATELEM(*imat,rpiv,colpos);
495
496  for (j=all;j>ready;j--)
497  {
498    ce = IMATELEM(*imat,j,colpos);
499    if (ce!=0)
500    {
501      IMATELEM(*imat,j,colpos) = 0;
502      m1 = piv;
503      m2 = ce;
504      tgcd = ivGcd(m1, m2);
505      if (tgcd != 1)
506      {
507        m1 /= tgcd;
508        m2 /= tgcd;
509      }
510      for (i=imat->cols();i>colpos;i--)
511      {
512        IMATELEM(*imat,j,i) = IMATELEM(*imat,j,i)*m1-
513                              IMATELEM(*imat,rpiv,i)*m2;
514      }
515      ivRowContent(imat, j, colpos+1);
516    }
517  }
518}
519
520static void ivZeroElim(intvec *imat, int colpos,
521                     int ready, int &all)
522{
523  int j, i, k, l;
524
525  k = ready;
526  for (j=ready+1;j<=all;j++)
527  {
528    for (i=imat->cols();i>colpos;i--)
529    {
530      if (IMATELEM(*imat,j,i)!=0)
531      {
532        k++;
533        if (k<j)
534        {
535          for (l=imat->cols();l>colpos;l--)
536            IMATELEM(*imat,k,l) = IMATELEM(*imat,j,l);
537        }
538        break;
539      }
540    }
541  }
542  all = k;
543}
544
545static void ivRowContent(intvec *imat, int rowpos, int colpos)
546{
547  int tgcd, m;
548  int i=imat->cols();
549
550  loop
551  {
552    tgcd = IMATELEM(*imat,rowpos,i--);
553    if (tgcd!=0) break;
554    if (i<colpos) return;
555  }
556  if (tgcd<0) tgcd = -tgcd;
557  if (tgcd==1) return;
558  loop
559  {
560    m = IMATELEM(*imat,rowpos,i--);
561    if (m!=0) tgcd= ivGcd(tgcd, m);
562    if (tgcd==1) return;
563    if (i<colpos) break;
564  }
565  for (i=imat->cols();i>=colpos;i--)
566    IMATELEM(*imat,rowpos,i) /= tgcd;
567}
568
569static void ivKernFromRow(intvec *kern, intvec *imat,
570                          intvec *perm, int pos, int r, int c)
571{
572  int piv, cp, g, i, j, k, s;
573
574  for (i=c;i>(*perm)[r];i--)
575  {
576    IMATELEM(*kern,pos,i) = 1;
577    for (j=r;j!=0;j--)
578    {
579      cp = (*perm)[j];
580      s=0;
581      for(k=c;k>cp;k--)
582        s += IMATELEM(*imat,j,k)*IMATELEM(*kern,pos,k);
583      if (s!=0)
584      {
585        piv = IMATELEM(*imat,j,cp);
586        g = ivGcd(piv,s);
587        if (g!=1)
588        {
589          s /= g;
590          piv /= g;
591        }
592        for(k=c;k>cp;k--)
593          IMATELEM(*kern,pos,k) *= piv;
594        IMATELEM(*kern,pos,cp) = -s;
595        ivRowContent(kern,pos,cp);
596      }
597    }
598    if (IMATELEM(*kern,pos,i)<0)
599      ivNegRow(kern,pos);
600    pos--;
601  }
602}
603
604static int ivGcd(int a,int b)
605{
606  int x;
607
608  if (a<0) a=-a;
609  if (b<0) b=-b;
610  if (b>a)
611  {
612    x=b;
613    b=a;
614    a=x;
615  }
616  while (b!=0)
617  {
618    x = a % b;
619    a = b;
620    b = x;
621  }
622  return a;
623}
624
625static intvec * ivOptimizeKern(intvec *kern)
626{
627  int i,l,j,c=kern->cols(),r=kern->rows();
628  intvec *res=new intvec(c);
629
630  if (TEST_OPT_PROT)
631    Warn(" %d linear independent solutions\n",r);
632  for (i=r;i>1;i--)
633  {
634    for (j=c;j>0;j--)
635    {
636      (*res)[j-1] += IMATELEM(*kern,i,j);
637    }
638  }
639  ivContent(res);
640  if (r<11)
641  {
642    l = ivCondNumber(res,-c);
643    j = ivL1Norm(res);
644    ivOptRecursive(res, NULL, kern, l, j, r);
645  }
646  return res;
647}
648
649static void ivOptRecursive(intvec *res, intvec *w, intvec *kern,
650                          int &l, int &j, int pos)
651{
652  int m, k, d;
653  intvec *h;
654
655  d=kern->rows();
656  d=96/(d*d);
657  if (d<3) d=3;
658  if (w!=0)
659    h = new intvec(w);
660  else
661    h = new intvec(res->rows());
662  for (m=d;m>0;m--)
663  {
664    for(k=h->rows()-1;k>=0;k--)
665      (*h)[k] += IMATELEM(*kern,pos,k+1);
666    if(pos>1)
667      ivOptRecursive(res, h, kern, l, j, pos-1);
668    else
669      ivOptSolve(res, h, l, j);
670  }
671  delete h;
672  if (pos>1)
673    ivOptRecursive(res, w, kern, l, j, pos-1);
674  else if (w!=NULL)
675    ivOptSolve(res, w, l, j);
676}
677
678static void ivOptSolve(intvec *res, intvec *w, int &l, int &j)
679{
680  int l0, j0, k;
681
682  l0 = ivCondNumber(w, l);
683  if (l0==l)
684  {
685    ivContent(w);
686    j0 = ivL1Norm(w);
687    if(j0<j)
688    {
689      j = j0;
690      for(k=w->rows()-1;k>=0;k--)
691        (*res)[k] = (*w)[k];
692    }
693    return;
694  }
695  if(l0>l)
696  {
697    l = l0;
698    ivContent(w);
699    j = ivL1Norm(w);
700    for(k=w->rows()-1;k>=0;k--)
701      (*res)[k] = (*w)[k];
702  } 
703}
704
705static int ivL1Norm(intvec *w)
706{
707  int i, j, s = 0;
708
709  for (i=w->rows()-1;i>=0;i--)
710  {
711    j = (*w)[i];
712    if (j>0)
713      s += j;
714    else
715      s -= j;
716  }
717  return s;
718}
719
720static int ivCondNumber(intvec *w, int l)
721{
722  int l0=0, i;
723
724  if (l<0)
725  {
726    for (i=w->rows()-1;i>=0;i--)
727    {
728      if ((*w)[i]<0) l0--;
729    }
730    if (l0==0)
731    {
732      for (i=w->rows()-1;i>=0;i--)
733      {
734        if ((*w)[i]>0) l0++;
735      }
736    }
737    return l0;
738  }
739  else
740  {
741    for (i=w->rows()-1;i>=0;i--)
742    {
743      if ((*w)[i]<0) return -1;
744    }
745    for (i=w->rows()-1;i>=0;i--)
746    {
747      if ((*w)[i]>0) l0++;
748    }
749    return l0;
750  }
751}
752
753static void ivContent(intvec *w)
754{
755  int tgcd, m;
756  int i=w->rows()-1;
757
758  loop
759  {
760    tgcd = (*w)[i--];
761    if (tgcd!=0) break;
762    if (i<0) return;
763  }
764  if (tgcd<0) tgcd = -tgcd;
765  if (tgcd==1) return;
766  loop
767  {
768    m = (*w)[i--];
769    if (m!=0) tgcd= ivGcd(tgcd, m);
770    if (tgcd==1) return;
771    if (i<0) break;
772  }
773  for (i=w->rows()-1;i>=0;i--)
774    (*w)[i] /= tgcd;
775}
776
777#endif
Note: See TracBrowser for help on using the repository browser.