source: git/Singular/intvec.cc @ b009cf

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