source: git/Singular/maps.cc @ 4508ce5

spielwiese
Last change on this file since 4508ce5 was 4508ce5, checked in by Hans Schönemann <hannes@…>, 23 years ago
*hannes: nMap removed nSetMap returns now the routine git-svn-id: file:///usr/local/Singular/svn/trunk@4920 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 15.7 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: maps.cc,v 1.32 2000-12-15 18:49:33 Singular Exp $ */
5/*
6* ABSTRACT - the mapping of polynomials to other rings
7*/
8
9#include "mod2.h"
10#include "tok.h"
11#include "febase.h"
12#include "polys.h"
13#include "numbers.h"
14#include "ring.h"
15#include "ideals.h"
16#include "matpol.h"
17#include "omalloc.h"
18#include "kstd1.h"
19#include "lists.h"
20#include "longalg.h"
21#include "maps.h"
22#include "prCopy.h"
23
24// This is a very dirty way to "normalize" numbers w.r.t. a
25// MinPoly
26static poly pMinPolyNormalize(poly p);
27
28/* debug output: Tok2Cmdname in maApplyFetch*/
29//#include "ipshell.h"
30
31#define MAX_MAP_DEG 128
32
33/*2
34* copy a map
35*/
36map maCopy(map theMap)
37{
38  int i;
39  map m=(map)idInit(IDELEMS(theMap),0);
40  for (i=IDELEMS(theMap)-1; i>=0; i--)
41      m->m[i] = pCopy(theMap->m[i]);
42  m->preimage=omStrDup(theMap->preimage);
43  return m;
44}
45
46
47/*2
48* return the image of var(v)^pExp, where var(v) maps to p
49*/
50poly maEvalVariable(poly p, int v,int pExp,matrix s)
51{
52  if (pExp==1)
53    return pCopy(p);
54
55  poly res;
56
57  if((s!=NULL)&&(pExp<MAX_MAP_DEG))
58  {
59    int j=2;
60    poly p0=p;
61    // find starting point
62    if(MATELEM(s,v,1)==NULL)
63    {
64      MATELEM(s,v,1)=pCopy(p/*theMap->m[v-1]*/);
65    }
66    else
67    {
68      while((j<=pExp)&&(MATELEM(s,v,j)!=NULL))
69      {
70        j++;
71      }
72      p0=MATELEM(s,v,j-1);
73    }
74    // multiply
75    for(;j<=pExp;j++)
76    {
77      p0=MATELEM(s,v,j)=ppMult_qq(p0, p);
78      pNormalize(p0);
79    }
80    res=pCopy(p0/*MATELEM(s,v,pExp)*/);
81  }
82  else //if ((p->next!=NULL)&&(p->next->next==NULL))
83  {
84    res=pPower(pCopy(p),pExp);
85  }
86  return res;
87}
88
89static poly maEvalMonom(map theMap, poly p,ring preimage_r,matrix s, nMapFunc nMap)
90{
91    poly q=pOne();
92    pSetCoeff(q,nMap(pGetCoeff(p)));
93
94    int i;
95    for(i=preimage_r->N; i>0; i--)
96    {
97      int pExp=p_GetExp( p,i,preimage_r);
98      if (pExp != 0)
99      {
100        if (theMap->m[i-1]!=NULL)
101        {
102          poly p1=theMap->m[i-1];
103          poly pp=maEvalVariable(p1,i,pExp,s);
104          q = pMult(q,pp);
105        }
106        else
107        {
108          pDelete(&q);
109          break;
110        }
111      }
112    }
113    int modulComp = p_GetComp( p,preimage_r);
114    if (q!=NULL) pSetCompP(q,modulComp);
115  return q;
116}
117
118poly maEval(map theMap, poly p,ring preimage_r,nMapFunc nMap,matrix s)
119{
120  poly result = NULL;
121  int i;
122
123//  for(i=1; i<=preimage_r->N; i++)
124//  {
125//    pTest(theMap->m[i-1]);
126//  }
127//  while (p!=NULL)
128//  {
129//    poly q=maEvalMonom(theMap,p,preimage_r,s);
130//    result = pAdd(result,q);
131//    pIter(p);
132//  }
133  if (p!=NULL)
134  {
135    int l = pLength(p)-1;
136    poly* monoms;
137    if (l>0)
138    {
139      monoms = (poly*) omAlloc(l*sizeof(poly));
140
141      for (i=0; i<l; i++)
142      {
143        monoms[i]=maEvalMonom(theMap,p,preimage_r,s, nMap);
144        pIter(p);
145      }
146    }
147    result=maEvalMonom(theMap,p,preimage_r,s, nMap);
148    if (l>0)
149    {
150      for(i = l-1; i>=0; i--)
151      {
152        result=pAdd(result, monoms[i]);
153      }
154      omFreeSize((ADDRESS)monoms,l*sizeof(poly));
155    }
156    if (currRing->minpoly!=NULL) result=pMinPolyNormalize(result);
157  }
158  pTest(result);
159  return result;
160}
161
162/*2
163*shifts the variables between minvar and maxvar of p  \in p_ring to the
164*first maxvar-minvar+1 variables in the actual ring
165*be carefull: there is no range check for the variables of p
166*/
167static poly pChangeSizeOfPoly(ring p_ring, poly p,int minvar,int maxvar)
168{
169  int i;
170  poly result = NULL,resultWorkP;
171  number n;
172
173  if (p==NULL) return result;
174  else result = pInit();
175  resultWorkP = result;
176  while (p!=NULL)
177  {
178    for (i=minvar;i<=maxvar;i++)
179      pSetExp(resultWorkP,i-minvar+1,p_GetExp(p,i,p_ring));
180    pSetComp(resultWorkP,p_GetComp(p,p_ring));
181    n=nCopy(pGetCoeff(p));
182    pSetCoeff(resultWorkP,n);
183    pSetm(resultWorkP);
184    pIter(p);
185    if (p!=NULL)
186    {
187      pNext(resultWorkP) = pInit();
188      pIter(resultWorkP);
189    }
190  }
191  return result;
192}
193
194
195/*2
196*returns the preimage of id under theMap,
197*if id is empty or zero the kernel is computed
198*/
199ideal maGetPreimage(ring theImageRing, map theMap, ideal id)
200{
201  int i,j;
202  int ordersize = rBlocks(currRing) + 1;
203  poly p,pp,q;
204  ideal temp1;
205  ideal temp2;
206  int *orders = (int*) omAlloc0(sizeof(int)*(ordersize));
207  int *block0 = (int*) omAlloc0(sizeof(int)*(ordersize));
208  int *block1 = (int*) omAlloc0(sizeof(int)*(ordersize));
209  int **wv = (int **) omAlloc0(ordersize * sizeof(int *));
210
211  int imagepvariables = theImageRing->N;
212  ring sourcering = currRing;
213  int N = pVariables+imagepvariables;
214  char** names = (char**) omAlloc0(N*sizeof(char*));
215
216  memcpy(names, currRing->names, currRing->N*sizeof(char*));
217  sip_sring tmpR;
218
219  if (theImageRing->OrdSgn == 1) orders[0] = ringorder_dp;
220  else orders[0] = ringorder_ls;
221  block1[0] = imagepvariables;
222  block0[0] = 1;
223  /*
224  *if (sourcering->order[blockmax])
225  *{
226  *  if (sourcering->OrdSgn == 1) orders[1] = ringorder_dp;
227  *  else orders[1] = ringorder_ls;
228  *  block1[1] = N;
229  *}
230  *else
231  */
232  for (i=0; i<ordersize - 1; i++)
233  {
234    orders[i+1] = sourcering->order[i];
235    block0[i+1] = sourcering->block0[i]+imagepvariables;
236    block1[i+1] = sourcering->block1[i]+imagepvariables;
237    wv[i+1] = sourcering->wvhdl[i];
238  }
239  tmpR = *currRing;
240  tmpR.N = N;
241  tmpR.order = orders;
242  tmpR.block0 = block0;
243  tmpR.block1 = block1;
244  tmpR.wvhdl = wv;
245  tmpR.names = names;
246  rComplete(&tmpR, 1);
247  rTest(&tmpR);
248
249  // change to new ring
250  rChangeCurrRing(&tmpR);
251  if (id==NULL)
252    j = 0;
253  else
254    j = IDELEMS(id);
255  int j0=j;
256  if (theImageRing->qideal!=NULL) j+=IDELEMS(theImageRing->qideal);
257  temp1 = idInit(sourcering->N+j,1);
258  for (i=0;i<sourcering->N;i++)
259  {
260    if ((i<IDELEMS(theMap)) && (theMap->m[i]!=NULL))
261    {
262      p = pChangeSizeOfPoly(theImageRing, theMap->m[i],1,imagepvariables);
263      q = p;
264      while (pNext(q)) pIter(q);
265      pNext(q) = pOne();
266      pIter(q);
267    }
268    else
269      q = p = pOne();
270    pGetCoeff(q)=nNeg(pGetCoeff(q));
271    pSetExp(q,i+1+imagepvariables,1);
272    pSetm(q);
273    temp1->m[i] = p;
274  }
275  for (i=sourcering->N;i<sourcering->N+j0;i++)
276  {
277    temp1->m[i] = pChangeSizeOfPoly(theImageRing,
278                                    id->m[i-sourcering->N],1,imagepvariables);
279  }
280  for (i=sourcering->N+j0;i<sourcering->N+j;i++)
281  {
282    temp1->m[i] = pChangeSizeOfPoly(theImageRing,
283                                    theImageRing->qideal->m[i-sourcering->N-j0],
284                                    1,imagepvariables);
285  }
286  // we ignore here homogenity - may be changed later:
287  temp2 = kStd(temp1,NULL,isNotHomog,NULL);
288  idDelete(&temp1);
289  for (i=0;i<IDELEMS(temp2);i++)
290  {
291    if (pLowVar(temp2->m[i])<imagepvariables) pDelete(&(temp2->m[i]));
292  }
293
294  // let's get back to the original ring
295  rChangeCurrRing(sourcering);
296  temp1 = idInit(5,1);
297  j = 0;
298  for (i=0;i<IDELEMS(temp2);i++)
299  {
300    p = temp2->m[i];
301    if (p!=NULL)
302    {
303      q = pChangeSizeOfPoly(&tmpR, p,imagepvariables+1,N);
304      if (j>=IDELEMS(temp1))
305      {
306        pEnlargeSet(&(temp1->m),IDELEMS(temp1),5);
307        IDELEMS(temp1)+=5;
308      }
309      temp1->m[j] = q;
310      j++;
311    }
312  }
313  id_Delete(&temp2, &tmpR);
314  idSkipZeroes(temp1);
315  rUnComplete(&tmpR);
316  omFreeSize(orders, sizeof(int)*(ordersize));
317  omFreeSize(block0, sizeof(int)*(ordersize));
318  omFreeSize(block1, sizeof(int)*(ordersize));
319  omFreeSize(wv, sizeof(int*)*(ordersize));
320  omFreeSize(names, (currRing->N)*sizeof(char*));
321  return temp1;
322}
323
324void maFindPerm(char **preim_names, int preim_n, char **preim_par, int preim_p,
325                char **names,       int n,       char **par,       int nop,
326                int * perm, int *par_perm, int ch)
327{
328  int i,j;
329  /* find correspondig vars */
330  for (i=0; i<preim_n; i++)
331  {
332    for(j=0; j<n; j++)
333    {
334      if (strcmp(preim_names[i],names[j])==0)
335      {
336        if (BVERBOSE(V_IMAP))
337          Print("// var %s: nr %d -> nr %d\n",preim_names[i],i+1,j+1);
338        /* var i+1 from preimage ring is var j+1  (index j+1) from image ring */
339        perm[i+1]=j+1;
340        break;
341      }
342    }
343    if ((perm[i+1]==0)&&(par!=NULL)
344        // do not consider par of Fq
345         && (ch < 2))
346    {
347      for(j=0; j<nop; j++)
348      {
349        if (strcmp(preim_names[i],par[j])==0)
350        {
351          if (BVERBOSE(V_IMAP))
352            Print("// var %s: nr %d -> par %d\n",preim_names[i],i+1,j+1);
353          /* var i+1 from preimage ring is par j+1 (index j) from image ring */
354          perm[i+1]=-(j+1);
355        }
356      }
357    }
358  }
359  if (par_perm!=NULL)
360  {
361    for (i=0; i<preim_p; i++)
362    {
363      for(j=0; j<n; j++)
364      {
365        if (strcmp(preim_par[i],names[j])==0)
366        {
367          if (BVERBOSE(V_IMAP))
368            Print("// par %s: par %d -> nr %d\n",preim_par[i],i+1,j+1);
369          /* var i+1 from preimage ring is var j+1  (index j+1) from image ring */
370          par_perm[i]=j+1;
371          break;
372        }
373      }
374      if ((par!=NULL) && (par_perm[i]==0))
375      {
376        for(j=0; j<nop; j++)
377        {
378          if (strcmp(preim_par[i],par[j])==0)
379          {
380            if (BVERBOSE(V_IMAP))
381              Print("// par %s: nr %d -> par %d\n",preim_par[i],i+1,j+1);
382            /* var i+1 from preimage ring is par j+1 (index j) from image ring */
383            par_perm[i]=-(j+1);
384          }
385        }
386      }
387    }
388  }
389}
390
391/*2
392* embeds poly p from the subring r into the current ring
393*/
394poly maIMap(ring r, poly p)
395{
396  /* the simplest case:*/
397  if(r==currRing) return pCopy(p);
398  nMapFunc nMap=nSetMap(r);
399  int *perm=(int *)omAlloc0((r->N+1)*sizeof(int));
400  //int *par_perm=(int *)omAlloc0(rPar(r)*sizeof(int));
401  maFindPerm(r->names,r->N, r->parameter, r->P,
402             currRing->names,currRing->N,currRing->parameter, currRing->P,
403             perm,NULL, currRing->ch);
404  poly res=pPermPoly(p,perm,r, nMap /*,par_perm,rPar(r)*/);
405  omFreeSize((ADDRESS)perm,(r->N+1)*sizeof(int));
406  //omFreeSize((ADDRESS)par_perm,rPar(r)*sizeof(int));
407  return res;
408}
409
410/*3
411* find the max. degree in one variable, but not larger than MAX_MAP_DEG
412*/
413static int maMaxDeg_Ma(ideal a,ring preimage_r)
414{
415  int i,j;
416  int N = preimage_r->N;
417  poly p;
418  int *m=(int *)omAlloc0(N*sizeof(int));
419
420  for (i=MATROWS(a)*MATCOLS(a)-1;i>=0;i--)
421  {
422    p=a->m[i];
423    //pTest(p); // cannot test p because it is from another ring
424    while(p!=NULL)
425    {
426      for(j=N-1;j>=0;j--)
427      {
428        m[j]=max(m[j],p_GetExp( p,j+1,preimage_r));
429        if (m[j]>=MAX_MAP_DEG)
430        {
431          i=MAX_MAP_DEG;
432          goto max_deg_fertig_id;
433        }
434      }
435      pIter(p);
436    }
437  }
438  i=m[0];
439  for(j=N-1;j>0;j--)
440  {
441    i=max(i,m[j]);
442  }
443max_deg_fertig_id:
444  omFreeSize((ADDRESS)m,N*sizeof(int));
445  return i;
446}
447
448/*3
449* find the max. degree in one variable, but not larger than MAX_MAP_DEG
450*/
451static int maMaxDeg_P(poly p,ring preimage_r)
452{
453  int i,j;
454  int N = preimage_r->N;
455  int *m=(int *)omAlloc0(N*sizeof(int));
456
457//  pTest(p);
458  while(p!=NULL)
459  {
460    for(j=N-1;j>=0;j--)
461    {
462      m[j]=max(m[j],p_GetExp(p,j+1,preimage_r));
463      if (m[j]>=MAX_MAP_DEG)
464      {
465        i=MAX_MAP_DEG;
466        goto max_deg_fertig_p;
467      }
468    }
469    pIter(p);
470  }
471  i=m[0];
472  for(j=N-1;j>0;j--)
473  {
474    i=max(i,m[j]);
475  }
476max_deg_fertig_p:
477  omFreeSize((ADDRESS)m,N*sizeof(int));
478  return i;
479}
480
481/*2
482* maps the expression w to res,
483* switch what: MAP_CMD: use theMap for mapping, N for preimage ring
484*              //FETCH_CMD: use pOrdPoly for mapping
485*              IMAP_CMD: use perm for mapping, N for preimage ring
486*              default: map only poly-structures,
487*                       use perm and par_perm, N and P,
488*/
489BOOLEAN maApplyFetch(int what,map theMap,leftv res, leftv w, ring preimage_r,
490                     int *perm, int *par_perm, int P, nMapFunc nMap)
491{
492  int i;
493  int N = preimage_r->N;
494  //Print("N=%d what=%s ",N,Tok2Cmdname(what));
495  //if (perm!=NULL) for(i=1;i<=N;i++) Print("%d -> %d ",i,perm[i]);
496  //PrintS("\n");
497  //Print("P=%d ",P);
498  //if (par_perm!=NULL) for(i=0;i<P;i++) Print("%d -> %d ",i,par_perm[i]);
499  //PrintS("\n");
500  void *data=w->Data();
501  res->rtyp = w->rtyp;
502  switch (w->rtyp)
503  {
504    case NUMBER_CMD:
505      if (P!=0)
506      {
507        res->data=(void *)naPermNumber((number)data,par_perm,P, preimage_r);
508        res->rtyp=POLY_CMD;
509        if (currRing->minpoly!=NULL)
510          res->data=(void *)pMinPolyNormalize((poly)res->data);
511        pTest((poly) res->data);
512      }
513      else
514      {
515        res->data=(void *)nMap((number)data);
516        if (currRing->minpoly!=NULL)
517        {
518          number a=(number)res->data;
519          nNormalize(a);
520          res->data=(void *)a;
521        }
522        nTest((number) res->data);
523      }
524      break;
525    case POLY_CMD:
526    case VECTOR_CMD:
527      if ((what==FETCH_CMD)&& (nMap==nCopy))
528        res->data=(void *)prCopyR( (poly)data, preimage_r);
529      else
530      if ((what==IMAP_CMD) || ((what==FETCH_CMD) /* && (nMap!=nCopy)*/))
531        res->data=(void *)pPermPoly((poly)data,perm,preimage_r,nMap,par_perm,P);
532      else /*if (what==MAP_CMD)*/
533      {
534        matrix s=mpNew(N,maMaxDeg_P((poly)data, preimage_r));
535        res->data=(void *)maEval(theMap,(poly)data,preimage_r,nMap,s);
536        idDelete((ideal *)&s);
537      }
538      if (currRing->minpoly!=NULL)
539        res->data=(void *)pMinPolyNormalize((poly)res->data);
540      pTest((poly)res->data);
541      break;
542    case MODUL_CMD:
543    case MATRIX_CMD:
544    case IDEAL_CMD:
545    case MAP_CMD:
546    {
547      int C=((matrix)data)->cols();
548      int R;
549      if (w->rtyp==MAP_CMD) R=1;
550      else R=((matrix)data)->rows();
551      matrix m=mpNew(R,C);
552      char *tmpR=NULL;
553      if(w->rtyp==MAP_CMD)
554      {
555        tmpR=((map)data)->preimage;
556        ((matrix)data)->rank=((matrix)data)->rows();
557      }
558      if (what==FETCH_CMD)
559      {
560        for (i=R*C-1;i>=0;i--)
561        {
562          m->m[i]=prCopyR(((ideal)data)->m[i], preimage_r);
563          pTest(m->m[i]);
564        }
565      }
566      else
567      if (what==IMAP_CMD)
568      {
569        for (i=R*C-1;i>=0;i--)
570        {
571          m->m[i]=pPermPoly(((ideal)data)->m[i],perm,preimage_r,nMap,par_perm,P);
572          pTest(m->m[i]);
573        }
574      }
575      else /* if(what==MAP_CMD) */
576      {
577        matrix s=mpNew(N,maMaxDeg_Ma((ideal)data,preimage_r));
578        for (i=R*C-1;i>=0;i--)
579        {
580          m->m[i]=maEval(theMap,((ideal)data)->m[i],preimage_r,nMap,s);
581          pTest(m->m[i]);
582        }
583        idDelete((ideal *)&s);
584      }
585      if (currRing->minpoly!=NULL)
586      {
587        for (i=R*C-1;i>=0;i--)
588        {
589          m->m[i]=pMinPolyNormalize(m->m[i]);
590          pTest(m->m[i]);
591        }
592      }
593      if(w->rtyp==MAP_CMD)
594      {
595        ((map)data)->preimage=tmpR;
596        ((map)m)->preimage=omStrDup(tmpR);
597      }
598      else
599      {
600        m->rank=((matrix)data)->rank;
601      }
602      res->data=(char *)m;
603      idTest((ideal) m);
604      break;
605    }
606
607    case LIST_CMD:
608    {
609      lists l=(lists)data;
610      lists ml=(lists)omAllocBin(slists_bin);
611      ml->Init(l->nr+1);
612      for(i=0;i<=l->nr;i++)
613      {
614        if (((l->m[i].rtyp>BEGIN_RING)&&(l->m[i].rtyp<END_RING))
615        ||(l->m[i].rtyp==LIST_CMD))
616        {
617          if (maApplyFetch(what,theMap,&ml->m[i],&l->m[i],
618                           preimage_r,perm,par_perm,P,nMap))
619          {
620            ml->Clean();
621            omFreeBin((ADDRESS)ml, slists_bin);
622            res->rtyp=0;
623            return TRUE;
624          }
625        }
626        else
627        {
628          ml->m[i].Copy(&l->m[i]);
629        }
630      }
631      res->data=(char *)ml;
632      break;
633    }
634    default:
635    {
636      return TRUE;
637    }
638  }
639  return FALSE;
640}
641
642// This is a very dirty way to cancel monoms whose number equals the
643// MinPoly
644static poly pMinPolyNormalize(poly p)
645{
646  number one = nInit(1);
647  spolyrec rp;
648 
649  poly q = &rp;
650 
651  while (p != NULL)
652  {
653    // this returns 0, if p == MinPoly
654    number product = nMult(pGetCoeff(p), one);
655    if (product == NULL)
656    {
657      pDeleteLm(&p);
658    }
659    else
660    {
661      pSetCoeff(p, product);
662      pNext(q) = p;
663      q = p;
664      p = pNext(p);
665    }
666  }
667  pNext(q) = NULL;
668  return rp.next;
669}
Note: See TracBrowser for help on using the repository browser.