source: git/kernel/intvec.cc @ 3a67ea7

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