source: git/Singular/splist.cc @ 634dab0

spielwiese
Last change on this file since 634dab0 was 0bb212d, checked in by Hans Schönemann <hannes@…>, 23 years ago
*hannes: spectrum fixes git-svn-id: file:///usr/local/Singular/svn/trunk@4884 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 18.1 KB
Line 
1// ----------------------------------------------------------------------------
2//  splist.cc
3//  begin of file
4//  Stephan Endrass, endrass@mathematik.uni-mainz.de
5//  23.7.99
6// ----------------------------------------------------------------------------
7
8#define SPLIST_CC
9
10#include "mod2.h"
11
12#ifdef HAVE_SPECTRUM
13
14#ifdef  SPLIST_PRINT
15#include <iostream.h>
16#ifndef SPLIST_IOSTREAM
17#include <stdio.h>
18#endif
19#endif
20
21#include "tok.h"
22#include "GMPrat.h"
23#include "numbers.h"
24#include "polys.h"
25#include "npolygon.h"
26#include "splist.h"
27#include "intvec.h"
28#include "lists.h"
29
30// ------------------------
31//  class spectrumPolyNode
32// ------------------------
33
34// ----------------------------------------------------------------------------
35//  Initialize a  spectrumPolyNode  with zero
36// ----------------------------------------------------------------------------
37
38void    spectrumPolyNode::copy_zero( void )
39{
40    next   = (spectrumPolyNode*)NULL;
41    mon    = (poly)NULL;
42    weight = (Rational)0;
43    nf     = (poly)NULL;
44}
45
46// ----------------------------------------------------------------------------
47//  Inizialize a  spectrumPolyNode  shallow from data
48// ----------------------------------------------------------------------------
49
50void    spectrumPolyNode::copy_shallow(
51                spectrumPolyNode *pnode,poly m,const Rational &w,poly f )
52{
53    next   = pnode;
54    mon    = m;
55    weight = w;
56    nf     = f;
57}
58
59// ----------------------------------------------------------------------------
60//  Inizialize a  spectrumPolyNode  shallow from another  spectrumPolyNode
61// ----------------------------------------------------------------------------
62
63void    spectrumPolyNode::copy_shallow( spectrumPolyNode &node )
64{
65    next   = node.next;
66    mon    = node.mon;
67    weight = node.weight;
68    nf     = node.nf;
69}
70
71// ----------------------------------------------------------------------------
72//  Zero constructor for  spectrumPolyNode
73// ----------------------------------------------------------------------------
74
75spectrumPolyNode::spectrumPolyNode( )
76{
77    copy_zero( );
78}
79
80// ----------------------------------------------------------------------------
81//  Data constructor for  spectrumPolyNode  is shallow
82// ----------------------------------------------------------------------------
83
84spectrumPolyNode::spectrumPolyNode(
85        spectrumPolyNode *pnode,poly m,const Rational &w,poly f )
86{
87    copy_shallow( pnode,m,w,f );
88}
89
90// ----------------------------------------------------------------------------
91//  Destructor is empty since we construct our objects shallow
92// ----------------------------------------------------------------------------
93
94spectrumPolyNode::~spectrumPolyNode( )
95{
96    if( mon!=(poly)NULL ) pDelete( &mon );
97    if( nf !=(poly)NULL ) pDelete( &nf );
98    copy_zero( );
99}
100
101// ------------------------
102//  class spectrumPolyList
103// ------------------------
104
105// ----------------------------------------------------------------------------
106//  Initialize a  spectrumPolyList  with zero
107// ----------------------------------------------------------------------------
108
109void    spectrumPolyList::copy_zero( void )
110{
111    root = (spectrumPolyNode*)NULL;
112    N    = 0;
113    np   = (newtonPolygon*)NULL;
114}
115
116// ----------------------------------------------------------------------------
117//  Inizialize a  spectrumPolyList  shallow from data
118// ----------------------------------------------------------------------------
119
120void    spectrumPolyList::copy_shallow(
121                spectrumPolyNode *node,int k,newtonPolygon *npolygon )
122{
123    root = node;
124    N    = k;
125    np   = npolygon;
126}
127
128// ----------------------------------------------------------------------------
129//  Inizialize a  spectrumPolyList  shallow from another  spectrumPolyList
130// ----------------------------------------------------------------------------
131
132void    spectrumPolyList::copy_shallow( spectrumPolyList &splist )
133{
134    copy_shallow( splist.root,splist.N,splist.np );
135}
136
137// ----------------------------------------------------------------------------
138//  Zero constructor for  spectrumPolyList
139// ----------------------------------------------------------------------------
140
141spectrumPolyList::spectrumPolyList( )
142{
143    copy_zero( );
144}
145
146// ----------------------------------------------------------------------------
147//  Data constructor for  spectrumPolyList
148// ----------------------------------------------------------------------------
149
150spectrumPolyList::spectrumPolyList( newtonPolygon *npolygon )
151{
152    copy_shallow( (spectrumPolyNode*)NULL,0,npolygon );
153}
154
155// ----------------------------------------------------------------------------
156//  Destuctor for  spectrumPolyList
157// ----------------------------------------------------------------------------
158
159spectrumPolyList::~spectrumPolyList( )
160{
161    spectrumPolyNode *node;
162
163    while( root!=(spectrumPolyNode*)NULL )
164    {
165        node = root->next;
166        delete root;
167        root = node;
168    }
169
170    copy_zero( );
171}
172
173// ----------------------------------------------------------------------------
174//  Insert a new node into a  spectrumPolyList  at position k
175//      If the list is sorted, then
176//      the new node ist inserted such that the list remains sorted.
177// ----------------------------------------------------------------------------
178
179void    spectrumPolyList::insert_node( poly m,poly f )
180{
181    #ifdef SPLIST_DEBUG
182        if( np==(newtonPolygon*)NULL )
183        {
184            #ifdef SPLIST_PRINT
185            #ifdef SPLIST_IOSTREAM
186                cerr << "void    spectrumPolyList::insert_node( poly f )" << endl;
187                cerr << "    no Newton polygon" << endl;
188                cerr << "    exiting..." << endl;
189            #else
190                fprintf( stderr,"void    spectrumPolyList::insert_node( poly f )\n" );
191                fprintf( stderr,"    no Newton polygon\n" );
192                fprintf( stderr,"    exiting...\n" );
193            #endif
194            #endif
195
196            exit( 1 );
197        }
198    #endif
199
200    spectrumPolyNode    *newnode = new spectrumPolyNode(
201        (spectrumPolyNode*)NULL,m,np->weight_shift( m ),f );
202
203    if( N==0 ||
204              root->weight>newnode->weight ||
205            ( root->weight==newnode->weight &&
206              pCmp( root->mon,newnode->mon )<0 ) )
207    {
208        // ----------------------
209        //  insert at position 0
210        // ----------------------
211
212        newnode->next = root;
213        root          = newnode;
214    }
215    else if( N==1 )
216    {
217        // ---------------
218        //  insert at end
219        // ---------------
220
221        root->next    = newnode;
222    }
223    else
224    {
225        // ----------------------------
226        //  insert according to weight
227        // ----------------------------
228
229        spectrumPolyNode *actual = root;
230        spectrumPolyNode *next   = root->next;
231
232        while( next!=(spectrumPolyNode*)NULL &&
233               ( newnode->weight>next->weight ||
234               ( newnode->weight==next->weight &&
235                 pCmp( newnode->mon,next->mon )<0 ) ) )
236        {
237            actual = next;
238            next   = next->next;
239        }
240
241        actual->next = newnode;
242        newnode->next = next;
243    }
244    N++;
245}
246
247// ----------------------------------------------------------------------------
248//  Delete a node from a  spectrumPolyList
249// ----------------------------------------------------------------------------
250
251void    spectrumPolyList::delete_node( spectrumPolyNode **node )
252{
253    spectrumPolyNode *foo = *node;
254    *node = (*node)->next;
255    delete foo;
256    N--;
257}
258
259// ----------------------------------------------------------------------------
260//  Delete all nodes where   node->mon  is a multiple of  m
261//  In every node delete all instances of  m  in  node->nf
262// ----------------------------------------------------------------------------
263
264void    spectrumPolyList::delete_monomial( poly m )
265{
266    spectrumPolyNode **node = &root;
267    poly              *f;
268
269    m = pCopy( m );
270
271    while( *node!=(spectrumPolyNode*)NULL )
272    {
273        if( pCmp( m,(*node)->mon )>=0 && pLmDivisibleByNoComp( m,(*node)->mon ) )
274        {
275            delete_node( node );
276        }
277        else if( (*node)->nf!=(poly)NULL )
278        {
279            f = &((*node)->nf);
280
281            while( *f!=(poly)NULL )
282            {
283                if( pCmp( m,*f )>=0 && pLmDivisibleByNoComp( m,*f ) )
284                {
285                    pDeleteLm(f);
286                }
287                else
288                    {
289                    f = &(pNext( *f ));
290                }
291            }
292
293            if( (*node)->nf==(poly)NULL )
294            {
295                delete_node( node );
296            }
297            else
298            {
299                node = &((*node)->next);
300            }
301        }
302        else
303        {
304            node = &((*node)->next);
305        }
306    }
307    pDelete( &m );
308}
309
310// ----------------------------------------------------------------------------
311//  Compute the spectrum of a  spectrumPolyList
312// ----------------------------------------------------------------------------
313
314spectrumState   spectrumPolyList::spectrum( lists *L,int fast )
315{
316    spectrumPolyNode  **node = &root;
317    spectrumPolyNode  *search;
318
319    poly              f,tmp;
320    int               found,cmp;
321
322    Rational smax( ( fast==0 ? 0 : pVariables ),
323                   ( fast==2 ? 2 : 1 ) );
324
325    Rational weight_prev( 0,1 );
326
327    int     mu = 0;          // the milnor number
328    int     pg = 0;          // the geometrical genus
329    int     n  = 0;          // number of different spectral numbers
330    int     z  = 0;          // number of spectral number equal to smax
331
332    int     k = 0;
333
334    while( (*node)!=(spectrumPolyNode*)NULL &&
335           ( fast==0 || (*node)->weight<=smax ) )
336    {
337        // ---------------------------------------
338        //  determine the first normal form which
339        //  contains the monomial  node->mon
340        // ---------------------------------------
341
342        found  = FALSE;
343        search = *node;
344
345        while( search!=(spectrumPolyNode*)NULL && found==FALSE )
346        {
347            if( search->nf!=(poly)NULL )
348            {
349                f = search->nf;
350
351                do
352                {
353                    // --------------------------------
354                    //  look for  (*node)->mon  in   f
355                    // --------------------------------
356
357                    cmp = pCmp( (*node)->mon,f );
358
359                    if( cmp<0 )
360                    {
361                        f = pNext( f );
362                    }
363                    else if( cmp==0 )
364                    {
365                        // -----------------------------
366                        //  we have found a normal form
367                        // -----------------------------
368
369                        found = TRUE;
370
371                        //  normalize coefficient
372
373                        number inv = nInvers( pGetCoeff( f ) );
374                        pMult_nn( search->nf,inv );
375                        nDelete( &inv );
376
377                        //  exchange  normal forms
378
379                        tmp         = (*node)->nf;
380                        (*node)->nf = search->nf;
381                        search->nf  = tmp;
382                    }
383                }
384                while( cmp<0 && f!=(poly)NULL );
385            }
386            search = search->next;
387        }
388
389        if( found==FALSE )
390        {
391            // ------------------------------------------------
392            //  the weight of  node->mon  is a spectrum number
393            // ------------------------------------------------
394
395            mu++;
396
397            if( (*node)->weight<=(Rational)1 )              pg++;
398            if( (*node)->weight==smax )           z++;
399            if( (*node)->weight>weight_prev )     n++;
400
401            weight_prev = (*node)->weight;
402            node = &((*node)->next);
403        }
404        else
405        {
406            // -----------------------------------------------
407            //  determine all other normal form which contain
408            //  the monomial  node->mon
409            //  replace for  node->mon  its normal form
410            // -----------------------------------------------
411
412            while( search!=(spectrumPolyNode*)NULL )
413            {
414                    if( search->nf!=(poly)NULL )
415                {
416                    f = search->nf;
417
418                    do
419                    {
420                        // --------------------------------
421                        //  look for  (*node)->mon  in   f
422                        // --------------------------------
423
424                        cmp = pCmp( (*node)->mon,f );
425
426                        if( cmp<0 )
427                        {
428                            f = pNext( f );
429                        }
430                        else if( cmp==0 )
431                        {
432                            search->nf = pSub( search->nf,
433                                ppMult_nn( (*node)->nf,pGetCoeff( f ) ) );
434                            pNorm( search->nf );
435                        }
436                    }
437                    while( cmp<0 && f!=(poly)NULL );
438                }
439                search = search->next;
440            }
441            delete_node( node );
442        }
443
444    }
445
446    // --------------------------------------------------------
447    //  fast computation exploits the symmetry of the spectrum
448    // --------------------------------------------------------
449
450    if( fast==2 )
451    {
452        mu = 2*mu - z;
453        n  = ( z > 0 ? 2*n - 1 : 2*n );
454    }
455
456    // --------------------------------------------------------
457    //  compute the spectrum numbers with their multiplicities
458    // --------------------------------------------------------
459
460    intvec            *nom  = new intvec( n );
461    intvec            *den  = new intvec( n );
462    intvec            *mult = new intvec( n );
463
464    int count         = 0;
465    int multiplicity  = 1;
466
467    for( search=root; search!=(spectrumPolyNode*)NULL &&
468                     ( fast==0 || search->weight<=smax );
469                     search=search->next )
470    {
471        if( search->next==(spectrumPolyNode*)NULL ||
472            search->weight<search->next->weight )
473        {
474            (*nom) [count] = search->weight.get_num_si( );
475            (*den) [count] = search->weight.get_den_si( );
476            (*mult)[count] = multiplicity;
477
478            multiplicity=1;
479            count++;
480        }
481        else
482        {
483            multiplicity++;
484        }
485    }
486
487    // --------------------------------------------------------
488    //  fast computation exploits the symmetry of the spectrum
489    // --------------------------------------------------------
490
491    if( fast==2 )
492    {
493        int n1,n2;
494        for( n1=0, n2=n-1; n1<n2; n1++, n2-- )
495        {
496            (*nom) [n2] = pVariables*(*den)[n1]-(*nom)[n1];
497            (*den) [n2] = (*den)[n1];
498            (*mult)[n2] = (*mult)[n1];
499        }
500    }
501
502    // -----------------------------------
503    //  test if the spectrum is symmetric
504    // -----------------------------------
505
506    if( fast==0 || fast==1 )
507    {
508        int symmetric=TRUE;
509
510        for( int n1=0, n2=n-1 ; n1<n2 && symmetric==TRUE; n1++, n2-- )
511        {
512            if( (*mult)[n1]!=(*mult)[n2] ||
513                (*den) [n1]!= (*den)[n2] ||
514                (*nom)[n1]+(*nom)[n2]!=pVariables*(*den) [n1] )
515            {
516                symmetric = FALSE;
517            }
518        }
519
520        if( symmetric==FALSE )
521        {
522            // ---------------------------------------------
523            //  the spectrum is not symmetric => degenerate
524            //  principal part
525            // ---------------------------------------------
526
527            *L = (lists)omAllocBin( slists_bin);
528            (*L)->Init( 1 );
529            (*L)->m[0].rtyp = INT_CMD;    //  milnor number
530            (*L)->m[0].data = (void*)mu;
531
532            return spectrumDegenerate;
533        }
534    }
535
536    *L = (lists)omAllocBin( slists_bin);
537
538    (*L)->Init( 6 );
539
540    (*L)->m[0].rtyp = INT_CMD;    //  milnor number
541    (*L)->m[1].rtyp = INT_CMD;    //  geometrical genus
542    (*L)->m[2].rtyp = INT_CMD;    //  number of spectrum values
543    (*L)->m[3].rtyp = INTVEC_CMD; //  nominators
544    (*L)->m[4].rtyp = INTVEC_CMD; //  denomiantors
545    (*L)->m[5].rtyp = INTVEC_CMD; //  multiplicities
546
547    (*L)->m[0].data = (void*)mu;
548    (*L)->m[1].data = (void*)pg;
549    (*L)->m[2].data = (void*)n;
550    (*L)->m[3].data = (void*)nom;
551    (*L)->m[4].data = (void*)den;
552    (*L)->m[5].data = (void*)mult;
553
554    return  spectrumOK;
555}
556
557// ----------------------------------------------------------------------------
558//  Print a  spectrumPolyList
559// ----------------------------------------------------------------------------
560
561#ifdef SPLIST_PRINT
562ostream & operator << ( ostream &s,const spectrumPolyList &l )
563{
564    #ifdef SPLIST_IOSTREAM
565        s << "elements: " << l.N << endl;
566        s << "{";
567    #else
568        fprintf( stdout,"elements: %d\n",l.N );
569        fprintf( stdout,"{" );
570    #endif
571
572    if( l.root!=(spectrumPolyNode*)NULL )
573    {
574        #ifdef SPLIST_IOSTREAM
575            s << "(";
576            pWrite0( l.root->mon );
577            s << "=>";
578            pWrite0( l.root->nf );
579            cout << "," << l.root->weight << ")" << endl;
580        #else
581            fprintf( stdout,"(" );
582            pWrite0( l.root->mon );
583            fprintf( stdout,"=>" );
584            pWrite0( l.root->nf );
585            fprintf( stdout,"," );
586            cout << l.root->weight;
587            fprintf( stdout,")\n" );
588        #endif
589
590        spectrumPolyNode *node = l.root->next;
591
592        while( node!=(spectrumPolyNode*)NULL )
593        {
594            #ifdef SPLIST_IOSTREAM
595                s << ",(";
596                pWrite0( node->mon );
597                s << "=>";
598                pWrite0( node->nf );
599                cout << "," << node->weight << ")" << endl;
600            #else
601                fprintf( stdout,",(" );
602                pWrite0( node->mon );
603                fprintf( stdout,"=>" );
604                pWrite0( node->nf );
605                fprintf( stdout,"," );
606                cout << node->weight;
607                fprintf( stdout,")\n" );
608            #endif
609
610            node = node->next;
611        }
612    }
613    #ifdef SPLIST_IOSTREAM
614        s << "}";
615    #else
616        fprintf( stdout,"}" );
617    #endif
618
619    return  s;
620}
621#endif
622
623#endif /* HAVE_SPECTRUM */
624// ----------------------------------------------------------------------------
625//  splist.cc
626//  end of file
627// ----------------------------------------------------------------------------
628
Note: See TracBrowser for help on using the repository browser.