source: git/libpolys/misc/intvec.cc @ 94fe43

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