source: git/libpolys/misc/intvec.cc @ 891122

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