source: git/Singular/maps.cc @ dd2714

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